1

I have implemented a websockets server in C++ with libwebsockets. It works when I make calls from any web browser using or not TLS. When I call it from an android app using TooTallNate/Java-Websockets library it works if the server doesn't use a digital certificate, but if it does (which is needed if I want to use TLS) the sever is blocked (and does not respond to new messages) and the app gets a 1006 error on onClose(int code,String reason,boolean remote). It happens wether or not I use SSL on the client. The problem is on line 2040 of libwebsockets.c:

eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);

It blocks on the server until I kill the android app.

This is the relevant code on the App:

class WebSocketChatClient extends WebSocketClient { 


    public WebSocketChatClient( URI serverUri ) { 
        super( serverUri ); 
    } 

    public WebSocketChatClient( URI serverUri , Draft protocolDraft , Map<String,String> httpHeaders  )
    {
        super(serverUri,protocolDraft,httpHeaders);
    }

    @Override 
    public void onOpen( ServerHandshake handshakedata ) { 
        System.out.println( "Connected" ); 
        send("prueba");

    } 


    @Override 
    public void onMessage( String message ) { 
        System.out.println( "got: " + message ); 


    } 


    @Override 
    public void onClose( int code, String reason, boolean remote ) { 
        System.out.println( "Disconnected" ); 
        //System.exit( 0 ); 


    } 


    @Override 
    public void onError( Exception ex ) { 
        ex.printStackTrace(); 


    } 


 } 




@Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        context = getApplicationContext();

        URI uri;
        try
        {
            uri=new URI("wss://192.168.1.128:8080");

            Map<String,String> headers=new HashMap<String,String>();

            headers.put("Sec-WebSocket-Protocol", "dumb-increment-protocol");
            headers.put("User-Agent", "My Android App");
            wsClient = new WebSocketChatClient(uri,new Draft_17(),headers);
            SSLContext sslContext = null;
            try {
                sslContext = SSLContext.getInstance( "TLS" );
                sslContext.init( null, null, null ); // will use java's default key and trust store which is sufficient unless you deal with self-signed certificates
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            }



            wsClient.setWebSocketFactory( new DefaultSSLWebSocketClientFactory( sslContext ) );
            wsClient.connect();

        }
        catch(URISyntaxException e)
        {
            e.printStackTrace();
        }
}

This is the relevant code on the server:

            int port = 8080;
            const char *intrface = NULL;
            struct libwebsocket_context *context;
            // we're not using ssl
            const char *cert_path = "c:\\mydir\\1921681128.crt";
            const char *key_path = "c:\\mydir\\1921681128.key";
            // no special options
            int opts = 0;

            // create libwebsocket context representing this server
            context = libwebsocket_create_context(port, intrface, protocols,
                                          libwebsocket_internal_extensions,
                                          cert_path, key_path, NULL,-1, -1, opts);

            if (context == NULL) {
                fprintf(stderr, "libwebsocket init failed\n");
                return -1;
            }

            printf("starting server...\n");

            // infinite loop, to end this server send SIGTERM. (CTRL+C)
            int k=0;
            while (1) {
                int res=libwebsocket_service(context, 50);
                // libwebsocket_service will process all waiting events with their
                // callback functions and then wait 50 ms.
                // (this is a single threaded webserver and this will keep our server
                // from generating load while there are not requests to process)
                     }

I would like to know if there is any bug on my side or if it is a bug on libwebsockets, openssl or the java websockets client library . The client works if I call this server: ws://echo.websocket.org using or not TLS. Even if there is a bug on the java client, I would also like to know if it's right behaviour that ssl_read doesn't return and gets blocked even when the client already detects a problem and returns an error. (The ssl_read on openssl code is a bit obfuscated for me to understand it)

Regards, Juanjo

UPDATE: The libwebsockets.c code is here: https://github.com/davidgaleano/libwebsockets/blob/master/lib/libwebsockets.c and it seems I have a previous version. Now the line is 2037. Given that there isn't any release and it seems a fork from an old version of the original warmcat/libwebsockets, I suppose the main problem is in that library.

juanjo75es
  • 253
  • 1
  • 3
  • 15
  • It's a shame github doesn't make it easier to get links pointing at a specific revision; it appears [this commit][https://github.com/davidgaleano/libwebsockets/commit/6ce62c03f15304e145f0c302b9fcc2c453900651] should have addressed this issue, but from what I can tell, this libwebsockets is using blocking IO on sockets; this may be causing the handshake to lock up. Do you really need to be using a fork instead of the main code? – Phil Lello Jan 27 '15 at 18:55
  • I used this fork because it's adapted for MSVC. I actually need it running on Windows. I suppose I should use another c++ compiler. – juanjo75es Jan 28 '15 at 10:11
  • I see now that I can also use cmake to generate a Visual Studio Project. Let's see if it works ... – juanjo75es Jan 28 '15 at 10:32
  • I have verified that if I use the original libwebsockets fork it doesn't lock up. But the java client still fails to connect. – juanjo75es Feb 01 '15 at 22:10
  • I have tested using another java websockets client library and it stills fails to connect using TLS. The library in this case is [pallmerc/SecureWebSockets](https://github.com/palmerc/SecureWebSockets) – juanjo75es Feb 03 '15 at 16:35
  • This may now be a problem with the certificate; are you getting any error message? Is the server certificate self-signed or from a CA (and if so, who?) – Phil Lello Feb 03 '15 at 17:44
  • I have tried with a self-signed certificate and with one from a CA. On both cases it fails to connect even if I don't use SSL on the client. OpenSSL returns this error on the server after SSL_accept returning -1 : [11903071896:8865] ERR: error:00000001:lib(0):func(0):reason(1)). – juanjo75es Feb 04 '15 at 10:35
  • I think you are right. I think the problem is that android doesn't have the intermediate and root certificates from my CA. So I need to make the websockets server send the complete chain or to make my app install the certificates. – juanjo75es Feb 04 '15 at 18:56

1 Answers1

1

The solution was to use the original libwebsockets library (not a fork) and to implement a TrustManager wrapper to pass to sslContext.init. This wrapper validates the server certificate independently.

juanjo75es
  • 253
  • 1
  • 3
  • 15
  • with the TooTallNate's library? I have the same problem right now, but in this case my clients are web browser. Thanks in advance – Jordy Baylac Aug 31 '16 at 20:36