Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 3.1.1
    • Fix Version/s: 3.1.1
    • Component/s: core
    • Labels:
      None
    • Environment:
      Web browser
    • Proposal:
      Hide
      Add an Appendix to describe MQTT protocol over websocket connections.

      MQTT can be transported over a WebSocket connection using the following conventions:

       - WebSocket binary frames are used. A single frame may contain multiple or partial MQTT Control Packets; they are not required to be aligned.
       - The WebSocket Protocol Name consists of the MQTT Protocol Name concatenated with the ASCII representation of the MQTT Protocol Version number. For MQTT v3.1.1, this will be "MQTT4".
       - No restriction is placed on the path portion of the WebSocket url


      Note to editors: need to add references to the WebSocket RFC
      Show
      Add an Appendix to describe MQTT protocol over websocket connections. MQTT can be transported over a WebSocket connection using the following conventions:  - WebSocket binary frames are used. A single frame may contain multiple or partial MQTT Control Packets; they are not required to be aligned.  - The WebSocket Protocol Name consists of the MQTT Protocol Name concatenated with the ASCII representation of the MQTT Protocol Version number. For MQTT v3.1.1, this will be "MQTT4".  - No restriction is placed on the path portion of the WebSocket url Note to editors: need to add references to the WebSocket RFC

      Description

      Constraints and considerations for flowing MQTT binary protocol over a Websocket, RFC 6455.

      See also http://wiki.eclipse.org/Paho/Paho_Websockets

      Making MQTT over Websockets inter-operable:

      Must support WebSockets as defined by RFC 6455
      Must use websocket binary frames.
      This enables MQTT v3,1 per the specification to flow over websockets with no change to the MQTT packets
      Must use "mqttv3.1" as the websocket protocol name.
      This is applicable when creating the websocket: e.g. new WebSocket(wsurl, 'mqttv3.1')
      The path portion of the url specified on the MQTT connect should be "mqtt"
      For instance ws://m2m.eclipse.org:800/mqtt . mqtt should be the default with the option for an alternative to be configured / specified

      Open points for further discussion:

      Should an MQTT packet be aligned with a WebSocket frame? Should MQTT Protocol messages be sent exactly one per frame or should the framing be arbitrary with multiple or partial MQTT messages per frame with no frame alignment.?

        Activity

        Hide
        Raphael Cohen added a comment -
        My 2 cents worth:-

        Path portion: I'd argue that's out of scope. The 'path portion' is duplicating the functionality of the subprotocol. Many, many users either (a) can't control it or (b) will want to expose the same resource with different protocols (eg STOMP, MQTT, something else). So I'd simply say we say (a) nothing or (b) say there is no default.

        Version: we'd want to register 3.1.1 or 3.2 or whatever we finally use

        Packet alignment: I'd go for anything goes - ie no alignment of any sort, so we maximise compatibility and interop; we allow people to pick any WebSockets gateway, and wire in any broker or client; to tunnel TCP generically over WebSockets; to use an existing java client with a Java socket that 'wraps' websockets, to use legacy code, to avoid the need for brokers to implement a different network / socket driver, etc. It is also far more efficient. When writing MQTT frames, you just want to do POSIC writev() (a scattered write) of an array of iovec. With frame alignment, you can't do that nearly as efficiently. The downside of anything goes is it is *slightly* more complex for a javascript client. Slightly, because onMessage() != a frame, so you just keep a buffer, iterate over frames, and keep the last 'fragment' and push (compact) to the front of your buffer in preparation for the next call. it'd be no more than a tweak to the excellent Paho code, for instance.

        Other WebSocket features: I'd like a simple statement that other things (ping-pong, gzip extensions, use of headers for security / cookies are out-of-scope / not required / extend at your own risk / something, for implementation, so we can maximise interop).

        Most importantly: is this core or can it be dealt with a technical note, etc post-spec? How do people feel?
        Show
        Raphael Cohen added a comment - My 2 cents worth:- Path portion: I'd argue that's out of scope. The 'path portion' is duplicating the functionality of the subprotocol. Many, many users either (a) can't control it or (b) will want to expose the same resource with different protocols (eg STOMP, MQTT, something else). So I'd simply say we say (a) nothing or (b) say there is no default. Version: we'd want to register 3.1.1 or 3.2 or whatever we finally use Packet alignment: I'd go for anything goes - ie no alignment of any sort, so we maximise compatibility and interop; we allow people to pick any WebSockets gateway, and wire in any broker or client; to tunnel TCP generically over WebSockets; to use an existing java client with a Java socket that 'wraps' websockets, to use legacy code, to avoid the need for brokers to implement a different network / socket driver, etc. It is also far more efficient. When writing MQTT frames, you just want to do POSIC writev() (a scattered write) of an array of iovec. With frame alignment, you can't do that nearly as efficiently. The downside of anything goes is it is *slightly* more complex for a javascript client. Slightly, because onMessage() != a frame, so you just keep a buffer, iterate over frames, and keep the last 'fragment' and push (compact) to the front of your buffer in preparation for the next call. it'd be no more than a tweak to the excellent Paho code, for instance. Other WebSocket features: I'd like a simple statement that other things (ping-pong, gzip extensions, use of headers for security / cookies are out-of-scope / not required / extend at your own risk / something, for implementation, so we can maximise interop). Most importantly: is this core or can it be dealt with a technical note, etc post-spec? How do people feel?
        Hide
        Nick O'Leary added a comment -
        I agree with Raphael on all points.

        Specifically, I don't think the path element should be of any concern, and the MQTT packet should not be required to be aligned to the WebSocket frame.

        Within other javascript environments it is pretty standard to receive partial packets and to buffer as appropriate. Having implemented a Websocket/TCP gateway in node.js, it was a pain to have to add in MQTT packet awareness to ensure the fragmented packets coming in over TCP were correctly reassembled before sending over ws. Other that for that, the code didn't need to know anything about the structure of an MQTT packet.
        As Raphael points out, this does then put that burden on the javascript client side, but that code will already have MQTT packet awareness, so is not really that much of a burden.

        I also don't think this should be part of the core spec. A tech-note, or otherwise, depending on what options are available within OASIS, would be a better place for it.
        Show
        Nick O'Leary added a comment - I agree with Raphael on all points. Specifically, I don't think the path element should be of any concern, and the MQTT packet should not be required to be aligned to the WebSocket frame. Within other javascript environments it is pretty standard to receive partial packets and to buffer as appropriate. Having implemented a Websocket/TCP gateway in node.js, it was a pain to have to add in MQTT packet awareness to ensure the fragmented packets coming in over TCP were correctly reassembled before sending over ws. Other that for that, the code didn't need to know anything about the structure of an MQTT packet. As Raphael points out, this does then put that burden on the javascript client side, but that code will already have MQTT packet awareness, so is not really that much of a burden. I also don't think this should be part of the core spec. A tech-note, or otherwise, depending on what options are available within OASIS, would be a better place for it.
        Hide
        Andrew Banks added a comment -
        Some counter arguments.

        Leaving the path unspecified means that it cannot be specified in the future. It also means that security software or firewalls cannot use this field to include or exclude the MQTT WebSocket traffic.

        The WebSocket implementations must do framing, the interfaces provide access to the frames. If we ignore framing it is done twice, once by the Websocket layer and then again by the MQTT protocol layer to discover the MQTT command messages. This adds redundant implementation and processing in the receipt of messages in both the client and server.
        Show
        Andrew Banks added a comment - Some counter arguments. Leaving the path unspecified means that it cannot be specified in the future. It also means that security software or firewalls cannot use this field to include or exclude the MQTT WebSocket traffic. The WebSocket implementations must do framing, the interfaces provide access to the frames. If we ignore framing it is done twice, once by the Websocket layer and then again by the MQTT protocol layer to discover the MQTT command messages. This adds redundant implementation and processing in the receipt of messages in both the client and server.
        Hide
        Raphael Cohen added a comment -
        I understand the concerns but I disagree that they actually matter.

        (1) Path specification
        Firewalls fall into 3 types here:-
        - Stateful or Stateless port-based (the vast majority; eg Linux iptables)
        - Vanilla HTTP ones (and we should add simpler load balancers, eg HAProxy, here, and things like nginx's 'firewall' plugin)
        - WebSocket aware ones (quite rare)

        The first set are unaffected by path but would probably be used for regulating any TCP traffic that was bridged to the protocol
        The second set can mostly be set up to use HTTP headers, and so should be looking for the mqtt3.x subprotocol. They don't have to be WebSockets aware, thankfully.
        The third set are a fancier second set.

        In practice, it's exceedingly rare to firewall on path. Instead, you just 404.

        (2) Framing
        I don't understand this - it seems quite wrong. Framing in WebSockets is nothing more than a header, the most important thing of which is 'there are X bytes in this frame'. In real use, no one sane is going to use extension frames. Instead, they'll do:-

        how many iovecs in my outbound queue / array? Total length?

        Write websocket frame, binary, complete, size == total length of all my iovecs. Do write().
        Do writev(), repeating if need be using epoll / poll / select / io completion if interuptted / would block /etc

        Frame alignment is not an issue. There is no redundant processing.

        As for reading, its pretty simple. All sent frames have that silly XOR nonsense, so one has to do a non-zero-copy off the wire regardless:-

        - receive frame
        - copy and xor into receive buffer
        - process as much as possible
        - would block, so return control to epoll
        - get called when more data
        Show
        Raphael Cohen added a comment - I understand the concerns but I disagree that they actually matter. (1) Path specification Firewalls fall into 3 types here:- - Stateful or Stateless port-based (the vast majority; eg Linux iptables) - Vanilla HTTP ones (and we should add simpler load balancers, eg HAProxy, here, and things like nginx's 'firewall' plugin) - WebSocket aware ones (quite rare) The first set are unaffected by path but would probably be used for regulating any TCP traffic that was bridged to the protocol The second set can mostly be set up to use HTTP headers, and so should be looking for the mqtt3.x subprotocol. They don't have to be WebSockets aware, thankfully. The third set are a fancier second set. In practice, it's exceedingly rare to firewall on path. Instead, you just 404. (2) Framing I don't understand this - it seems quite wrong. Framing in WebSockets is nothing more than a header, the most important thing of which is 'there are X bytes in this frame'. In real use, no one sane is going to use extension frames. Instead, they'll do:- how many iovecs in my outbound queue / array? Total length? Write websocket frame, binary, complete, size == total length of all my iovecs. Do write(). Do writev(), repeating if need be using epoll / poll / select / io completion if interuptted / would block /etc Frame alignment is not an issue. There is no redundant processing. As for reading, its pretty simple. All sent frames have that silly XOR nonsense, so one has to do a non-zero-copy off the wire regardless:- - receive frame - copy and xor into receive buffer - process as much as possible - would block, so return control to epoll - get called when more data
        Hide
        Raphael Cohen added a comment -
        Admittedly, this isn't as well explained as I would like. Oh, for a whiteboard!
        Show
        Raphael Cohen added a comment - Admittedly, this isn't as well explained as I would like. Oh, for a whiteboard!
        Hide
        Richard Coppen added a comment -
        Discussed on Scrub call (22.08.2013)

        TC should debate the question "Should an MQTT packet be aligned with a WebSocket frame?" and vote
        Show
        Richard Coppen added a comment - Discussed on Scrub call (22.08.2013) TC should debate the question "Should an MQTT packet be aligned with a WebSocket frame?" and vote
        Hide
        Nick O'Leary added a comment -
        Following today's TC call, the following points were agreed to be taken forward in the proposal.

        It was proposed this content should be included in the main specification document as an Appendix.

        -----------------------------------------
        MQTT can be transported over a WebSocket connection using the following conventions:

         - WebSocket binary frames are used. A single frame may contain multiple or partial MQTT Control Packets; they are not required to be aligned.
         - The WebSocket Protocol Name consists of the MQTT Protocol Name concatenated with the ASCII representation of the MQTT Protocol Version number. For MQTT v3.1.1, this will be "MQTT4".
         - No restriction is placed on the path portion of the WebSocket url

        -----------------------------------------

        Show
        Nick O'Leary added a comment - Following today's TC call, the following points were agreed to be taken forward in the proposal. It was proposed this content should be included in the main specification document as an Appendix. ----------------------------------------- MQTT can be transported over a WebSocket connection using the following conventions:  - WebSocket binary frames are used. A single frame may contain multiple or partial MQTT Control Packets; they are not required to be aligned.  - The WebSocket Protocol Name consists of the MQTT Protocol Name concatenated with the ASCII representation of the MQTT Protocol Version number. For MQTT v3.1.1, this will be "MQTT4".  - No restriction is placed on the path portion of the WebSocket url -----------------------------------------
        Hide
        Richard Coppen added a comment -
        Take to TC call 19.09.2013
        Show
        Richard Coppen added a comment - Take to TC call 19.09.2013
        Hide
        Andrew Banks added a comment -
        Fixed in WD12
        Show
        Andrew Banks added a comment - Fixed in WD12

          People

          • Assignee:
            Unassigned
            Reporter:
            Andrew Banks
          • Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: