WebSocket Supports SSL Connections

As we know, Apple to require HTTPS encryption on all iOS apps by 2017 in WWDC 2016.

But in the latest Cocos2d-X, WebSocket SSL Connections is still not supported. Many developers have required this feature, and yes, it should be supported in Cocos2d-X. :slight_smile:
We uses a 3rd-party websocket library called libwebsockets (https://github.com/warmcat/libwebsockets) . We wrapped the interfaces and make it more easier use for our developers. The wrapper code could be found at cocos/network/WebSocket.h/.cpp.
To support SSL for WS isn’t as easy as you guess. We have to build OpenSSL libraries for all platforms and rebuild libwebsockets library to enable SSL support.
And totally refactored WebSocket class to make it support SSL. The Pull Request is https://github.com/cocos2d/cocos2d-x/pull/17172.

WHY DO WE HAVE TO REFACTOR A LOT ?

Since before, each WebSocket class will use a sub-thread and maintain an independent libwebsockets context.
Therefore, if you create many WebSocket instances at the same time, there will be as many thread/context as the instances.

This old way will not work by just rebuilding libwebsockets library. Crashes will be triggered while initializing libwebsockets context because libwebsockets or openssl isn’t thread-safe.

I finally found a way, that’s using only one context for all WebSocket instances, uses the feature of virtual host in libwebsockets to simulate different Websocket client.
Then, there will be only one thread, one libwebsockets context, some libwebsockets instances, some virtual hosts for all WebSocket instances. So the refactoring is a lot.

HOW TO USE TO SUPPORT SSL CONNECTION?

It’s really as easy as before. Just notice the init method.

Before, we use

auto ws = new WebSocket();
ws->init("ws://echo.websocket.org");

to make a non-ssl connection.

Currently, we use

auto ws = new WebSocket();
ws->init("wss://echo.websocket.org", nullptr, "your CA root file path"); 

to make a SSL connection.

CA Root file could be exported from your browser or just use which in curl
(http://curl.haxx.se/ca/cacert.pem)

We need your help to test this new feature and feel free to give us feedback. Thanks.

James

1 Like

@dumganhar for the test project should this work?
void SocketIOTest::onMenuSIOClientClicked(cocos2d::Ref *sender)
{
_sioEndpoint = SocketIO::connect(“wss://echo.websocket.org”, *this,“cacert.pem”);
}

CA root path is correct??

i get the following log when i try to connect

2017-10-06 15:00:00.276280+0500 cpp-tests Mac[14441:855952] Starting to load https://echo.websocket.org/socket.io/1/?EIO=2&transport=polling&b64=true
2017-10-06 15:00:01.778660+0500 cpp-tests Mac[14441:855952] Received response from request to url https://echo.websocket.org/socket.io/1/?EIO=2&transport=polling&b64=true
D/WebSocket.cpp (415): WebSocket thread start, helper instance: 0x6080000430a0
D/WebSocket.cpp (167): NOTICE: Initial logging level 911

D/WebSocket.cpp (167): NOTICE: Libwebsockets version: 2.1.0 james@James-Chen.local-v3.4-139-gbdcf7f8

D/WebSocket.cpp (167): NOTICE: IPV6 compiled in and enabled

D/WebSocket.cpp (167): NOTICE: libev support not compiled in

D/WebSocket.cpp (167): NOTICE: libuv support not compiled in

D/WebSocket.cpp (167): NOTICE: Threads: 1 each 9472 fds

D/WebSocket.cpp (167): NOTICE: mem: platform fd map: 75776 bytes

D/WebSocket.cpp (167): NOTICE: Compiled with OpenSSL support

D/WebSocket.cpp (167): NOTICE: mem: per-conn: 512 bytes + protocol rx buf

D/WebSocket.cpp (873): scheme: wss, host: echo.websocket.org, port: 0, path: /socket.io/1/websocket/
D/WebSocket.cpp (167): NOTICE: Creating Vhost ‘default’ port -1, 1 protocols, IPv6 on

D/WebSocket.cpp (167): NOTICE: lws_protocol_init

D/WebSocket.cpp (1322): WebSocket (0x6130001581c0) Unhandled websocket event: 32
D/WebSocket.cpp (1322): WebSocket (0x6130001581c0) Unhandled websocket event: 29
D/WebSocket.cpp (1322): WebSocket (0x6130001581c0) Unhandled websocket event: 24
D/WebSocket.cpp (1197): WebSocket (0x6130001581c0) onConnectionError, state: 0 …
D/WebSocket.cpp (1226): WebSocket (0x6130001581c0) onConnectionClosed, state: 2 …
D/WebSocket.cpp (1256): onConnectionClosed, WebSocket (0x6130001581c0) is closing by server.
D/WebSocket.cpp (1279): WebSocket (0x6130001581c0) onConnectionClosed DONE!
D/WebSocket.cpp (1322): WebSocket (0x6130001581c0) Unhandled websocket event: 45
D/WebSocket.cpp (1322): WebSocket (0x6130001581c0) Unhandled websocket event: 33
D/WebSocket.cpp (1226): WebSocket (0x6130001581c0) onConnectionClosed, state: 3 …
Websocket error received: 1
D/WebSocket.cpp (545): In the destructor of WebSocket (0x6130001581c0)
D/WebSocket.cpp (565): before join ws thread
D/WebSocket.cpp (167): NOTICE: lws_context_destroy

D/WebSocket.cpp (425): WebSocket thread exit, helper instance: 0x6080000430a0
D/WebSocket.cpp (567): after join ws thread

@dumganhar it turns out cocos2d-x doesn’t support v2 socket.io

You used SocketIO protocol to connect a WebSocket server (echo.websocket.org).
It definitely trigger errors.

@dumganhar thanks i got it working by using a different server… it was still causing errors because i think cocos2d-x doesn’t support v2… what happens is when using v2 it selects _version to be SocketIOPacket::SocketIOVersion::V09x:.

So when changing the socket.io version to 1.x or 0.x chooses the correct version in cocos and works perfectly thanks :smiley:

@dumganhar should i report this on git?

Yep, you could report it on github for requiring new version support in SocketIO.
We will consider to upgrade it.

1 Like

Hi @bilalmirza @dumganhar
Edit:
I got it working after i downloaded pem file from here http://curl.haxx.se/ca/cacert.pem and changed format to der by simply rename cacert.der
But i have problem with 3g/4g connections, its not working in iphone.
Any suggestions?

@smitpatel88 glad you got it working… I’ve never tried it with 3g/4g connection so I can’t really help you there.