[nanomsg] Re: ws transport

  • From: Jack Dunaway <jack@xxxxxxxxxxxxxxxx>
  • To: nanomsg@xxxxxxxxxxxxx
  • Date: Wed, 26 Nov 2014 09:01:28 -0600

First, hearty thanks to Martin for lots of work validating and integrating
the ws:// transport!

> "I've made an equivalent of tcp tests for ws and they fail"

Have you tried applying this pull request?
https://github.com/nanomsg/nanomsg/pull/339 This PR is what enables SPs
(beyond just PAIR) to work.

As a short-term test of that PR, I tried existing SP tests by changing
their connection string to ws:// -- as a longer term goal, it would be good
to upgrade many tests to iterate over all available transports. As an
example, the REQ/REP currently only tests inproc (
https://github.com/nanomsg/nanomsg/blob/master/tests/reqrep.c#L28), but
could be upgraded to iterate over inproc/tcp/ipc/ws

> "there's a lot of stuff that's not really needed"

Most notably, content awareness (UTF-8 vs. binary) being exposed to user. I
agree that for now we can and should only support binary payloads. That
said, the ability set per-message metadata with CMSG headers is one area we
ought to continue to push forward. nanomsg currently supports pluggability
of scalability protocol and transport, and it could use growth toward
supporting pluggable message transformations as well (such as security,
compression, content awareness...)

As for the removing the resource from the URI, and also PING/PONG -- those
would need to be included as part of the minimal implementation.

One area we've not fully delved into is the Close Handshake, and the
concept of a nanomsg endpoint notifying the other endpoint(s) it is going
away. This is one feature of the WebSocket protocol that I think could
apply generally with all scalability protocols and transports in nanomsg --
which again, would rear the conversation of content awareness and message
type!

> "When sending a message from client, the message body is masked"

Good point. This is a grey area how to proceed, since WebSockets defined by
RFC 6455 have well-defined 1:1 endpoint roles of Client and Server, whereas
a nanomsg topology is more general. Maybe this means that a nanomsg
endpoint has a third type at the transport layer, "Peer", which will accept
either masked or unmasked messages? (thinking aloud; don't know
ramifications of this, such as whether intermediate reverse proxies might
get fussy) (
https://github.com/nanomsg/nanomsg/blob/master/src/transports/ws/ws_handshake.h#L42-L45
)

> "After initial WebSocket handshake, each peer sends an 8-byte SP header"

While implementing the first draft implementation, I was on the fence
whether the SP should be communicated via the HTTP handshake, or more like
TCP as an 8-byte header.

Most considerations equal, I went with putting it in the HTTP handshake, in
order that the SP might be communicated as plain-text. This is to remain
discoverable and idiomatic especially within the realm of HTTP programming
and debugging, and also as more metainformation to help steer HTTP
intermediaries.

The kink is that SPs need a canonical text representation in addition to
their numeric representation, meaning
https://github.com/nanomsg/nanomsg/blob/master/rfc/sp-protocol-ids-01.txt
reserves not only a number, but the identifying text as well. By allowing
transports to negotiate either numeric/text representation of SP, a
transport is then encouraged to remain idiomatic to its medium (e.g., a
reverse proxy could be deployed as front-end defense on top of a nanomsg
application, where the proxy is given directives to only allow REQ type
connections; this defense is lost if SP is communicated as the first 8
bytes of a connection. That failure mode could be made easy to detect,
troubleshoot, and remedy by the client: "HTTP 400 PAIR not allowed")

Basically, all we need to do for sp-protocol-ids-01.txt is state "It Is So:
either the number or text may be used to negotiate endpoint role, as
defined by the transport layer".

> make a minimal implementation of ws transport (see ws2 branch in the repo)

I sincerely appreciate how rigorously you're testing this! Reading your
TODO comments in the ws2 branch, I can intuit some of your considerations,
but it looks like we're converging on a good implementation.

To wrap up, here are the areas that I feel need most consideration:

1) Introducing a Close Handshake to nanomsg. Even though it is "application
level", and certainly not "transport level", it widely-applicable enough to
consider adding to all transports.
2) Equipping usock to enable sending of messages directly from the
transport, cooperatively scheduling/queuing them with messages from the
application. This could enable automatic PONGs for PINGs, and better Close
Handshake when a blocking operation is already currently running.
3) Using Autobahn TestSuite as a fuzzing tester. This requires the
transport be able to set the resource path in the URI on connection.
4) Canonicalizing text representation of SPs in sp-protocol-ids-01.txt in
addition to numeric ID

Best regards,

Jack R. Dunaway | Wirebird Labs LLC

On Wed, Nov 26, 2014 at 6:06 AM, Martin Sustrik <sustrik@xxxxxxxxxx> wrote:

> Hi Jack,
>
> I've spent few last days playing with the WebSocket transport. Here are
> some observations:
>
> 1. As already discussed there's a lot of stuff that's not really needed.
> 2. I've made an equivalent of tcp tests for ws and they fail.
> 3. When sending a message from client, the message body is masked. Given
> that message may be shared, this garbles the message daa for everyone else.
>
> I've tried to make a minimal implementation of ws transport (see ws2
> branch in the repo). It's still missing some pieces but good news is that
> all the tests (see ws.c and ws_shutdown.c) pass.
>
> Here's the summary of how it works:
>
> 1. The connection string has the same format as tcp transport (host+port).
> 2. The "resource" field in the request is always set to "/"
> 3. Protocol field is always set to "sp"
> 4. After initial WebSocket handshake, each peer sends an 8-byte SP header
> as a new WebSocket message. Its format is the same as in tcp transport (see
> the RFC).
>
> Missing pieces:
>
> 1. Timeout for the intial handshake.
> 2. Closing handshake
> 3. Rigorous validation of initial request and reply
> 4. Detailed error handling
> 5. Ping/pong
>
> Thoughts?
> Martin
>
>
>

Other related posts: