Skip to content

Instantly share code, notes, and snippets.

@MatrixManAtYrService
Last active September 22, 2017 20:03
Show Gist options
  • Save MatrixManAtYrService/fba771f56ef130deef535a6e7dd4717a to your computer and use it in GitHub Desktop.
Save MatrixManAtYrService/fba771f56ef130deef535a6e7dd4717a to your computer and use it in GitHub Desktop.

The Problem

When the SWSS (Simple-WebSocket-Server) client connects to a server running libwebsockets:

  • The connection gets set up, and data moves through
  • The server fails to to call the appropriate callback for the specified protocol (/sky/api/v0/controller-sky in the example shown here)

This libwebsockets implementation is working, which I know because:

  • The connection gets up, and data moves through
  • The server calls the correct callback for the specified protocol (front-panel-protocol)

What I've done

Captured the output of libwebsockets from a known working connection (see other files in this gist)

Dumped the TCP traffic for SWSS from a known working connection (see other files in this gist)

Things I notice

  • I notice that "101 Web Socket Protocol Handshake" is not the same as "101 Switching Protocols".

    • Per this it doesn't matter.
  • In order to support multiple connection types, there must be some way of distinguishing between connections

    • It looks like libwebsockets is using the Sec-WebSocket-Protocol field for this

    • It looks like Simple-WebSocket-Server is using specifying the HTTP Resource for this

    • Here's what RFC 6455 says about the field in question:

        11.3.4.  Sec-WebSocket-Protocol
      
         This section describes a header field registered in the Permanent
         Message Header Field Names registry [RFC3864].
      
         Header field name
            Sec-WebSocket-Protocol
      
         Applicable protocol
            http
      
         Status
            standard
      
         Author/Change controller
            IETF
      
         Specification document(s)
            RFC 6455
      
         Related information
            This header field is only used for the WebSocket opening
            handshake.
      
         The |Sec-WebSocket-Protocol| header field is used in the WebSocket
         opening handshake.  It is sent from the client to the server and back
         from the server to the client to confirm the subprotocol of the
         connection.  This enables scripts to both select a subprotocol and be
         sure that the server agreed to serve that subprotocol.
      

Hunch

I think I have conflated the protocol string with the endpoint string. Either of these should work:

  • Expand WSS client to allow me to specify Sec-WebSocket-Protocol in the handshake, and include "controller-sky" in that field, then libwebsockets will have what it needs to route traffic to the the correct callback.

  • Configure libwebsockets to listen for connections on the /sky/api/v2/controller-sky resource, and assume that connections there are part of the 'controller-sky' protocol

Initial page reqest from browser
    GET / HTTP /1.1
    Host: 127.0.1.1:8081
    Connection:keep-alive
    User-Agent: Mozilla/5.0 (X11; Linux x86_64)
    AppleWebkit/537.36  (KHTML, like Gecko) Chrome/61.0.3163.91 Safari/537.36
    Upgrade-Insecure-Requests: 1
    Accept: text/html, application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding:gzip, deflate, br
    Accept-Language:en-US,en;q=0.8
Served page contains a script that prompts browser to initiate a websocket connection
    GET / HTTP/1.1
    Host:127.0.0.1:8081
    Connection: Upgrade
    Pragma: no-cache
    Cache-Control: no-cache
    Upgrade: websocket
    Origin: http://127.0.0.1:8081
    Sec-Websocket-Version: 13
    User-Agent: Mozilla/5.0 (X11; Linux x86-64) AppleWebkit/537.36 (KHTMML, like Gecko) Chome/61.0.3163.91 Safari/537.36
    Accept-Encoding: gzip, deflate, br
    Accept-Language:en-US,en;q=0.8
    Sec-Websocket-Key: xgd/vB9Q+gK9fXhNZux07g==
    Sec-Websocket-Extensions: permessage-deflate;client_max_window_bits
    Sec-Websocket-Protocol: front-panel-protocol
Libwebsockets (on server) recognizes handshake as belonging to a know protocol, Emits the following messages:
    LWS (PARSER): known hdr 12
    LWS (PARSER): WSI_TOK_(12) ' '
    LWS (HTTP/1.1 101 Switching Protocols
    // presumably this is the response that libwebsockets sends:
    Upgrade: WebSocket 
    Connection: Upgrade
    Sec-WebSocket-Accept: JipJQFlcs2IVSzkH94K9VShpdHQ=
    Sec-WebSocket-Protocol: front-panel-protocol
Browser continues rendering pages, asks for image to display:
    GET /globe.svg HTTP/1.1
    Host: 127.0.0.1:8081
    Connection:keep-alive
    User-Agent: Mozilla/5.0 (X11; Linux x86-64) AppleWebkit/537.36 (KHTMML, like Gecko) Chome/61.0.3163.91 Safari/537.36
    Accept: imate/webp, image/apng, image/*,*/*;q=0.8
    Referer: http://127.0.0.1/8081
    Accept-Encoding: zip, deflate, br
    Accept-Language:en-US,en;q=0.8
WS Client sends the connection request
GET /sky/api/v2/controller-sky HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: gVEjfGhbVMzVj686Ll2bDQ==
Sec-WebSocket-Version: 13
WS Server responds
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: M/4M2t7+6A/U6AOcGiStKbmPCLQ=
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment