Couple of replies inline.

On 06/02/15 13:19, Rafael Schloming wrote:
A couple of questions/comments inline, but first off, any reason this isn't on the list? (I don't mind, just curious.)

No good reason; Alan PMed me and I replied, then though I'd best copy you guys. It's slightly head explodingly long, so if conversation develops it might be best to split it up a bit - it was mainly a bit of a brain dump for Alan and I got carried away :-D I've moved to the Qpid user and proton lists now for maximum exposure.


On Fri, Feb 6, 2015 at 6:20 AM, Fraser Adams <fraser.ad...@blueyonder.co.uk <mailto:fraser.ad...@blueyonder.co.uk>> wrote:

    Hi Again Alan,
    Sorry this has turned out to be massively TL;DR I kind of got on a
    roll......


    On the WebSocket thing it's worth pointing out that I've mainly
    been in the game of *using* them and have never had the pleasure
    of writing an implementation from scratch, but OTOH I've done a
    reasonable amount of"hacking around" - but that's mostly been in
    JavaScript and Python implementations so for C things are more
    awkward.

    I've copied Rafael so he's in the loop I've also copied Gordon,
    'cause I'd really quite like WebSocket support in qpidd at some
    point and Rob because he implemented the WebSocket transport in
    the Java Broker and I suspect he knows way more than me -
    especially about the trades around different implementation
    choices, he also knows the AMQP WebSocket spec intricacies way
    better than me so will be better placed to advise gotchas - and
    also I guess an approach that makes is easier for proton-j to
    introduce WebSocket support too.


    I guess first off I should say that when I suggested it might be a
    car crash if not thought through I was perhaps being a little
    parochial. As you know the JavaScript binding uses emscripten to
    compile proton-c to JavaScript - the way that works is the core
    grammar is compiled to LLVM bitcode and ends up as asm.js but
    library/system calls either wind up calling other compiled code or
    they break out into some pure JavaScript, that's the case for the
    network code and basically all the posix network calls get trapped
    and "faked" in a useful way; library.js and library_sockfs.js are
    the main places to look if you're interested.

    I guess that the key point is that all the *socket* calls in
    proton-c wind up as *WebSocket* stuff in the compiled JavaScript,
    for browsers it uses native WebSockets and for Node.js it uses the
    ws WebSocket library, which is I think the most popular one.

    The gnarly bit that I can think of is that clearly adding
    WebSocket support to proton-c risks accidentally causing the
    JavaScript stuff to implement WebSocket over WebSocket, which
    would be quite funny but probably not terribly useful :-D


It sounds like we quite probably would want to keep any web socket stuff compile-time optional and simply not build it at all with emscripten. That would a) avoid the possibility of nested websocketry, and b) keep useless code out of the already large proton.js file.

It's worth keeping an open mind. The proton-messenger.js stuff it indeed a bit big, most of that is actually down to the emscripten runtime stuff and there's a limit to what is easy to strip, there's some work ongoing on emscripten to make this a bit better. It's <500K minified and it could be compressed. I'm all for making it smaller but I doubt it'll make a huge difference I'm afraid. My main concern would be to make sure that any bits of code to add an API to select between TCP and WebSockets *weren't* removed I *want* to be able to pass that info to the emscripten code for when I get round to adding native TCP support.





    Another thing I worry a little about is how one implements the
    server side, there are two choices
    1. Have a separate WebSocket transport
    2. Note that WebSockets are actually a frame based protocol
    layered on top of TCP and initiated via an HTTP UPGRADE command.
    The spec is here: https://tools.ietf.org/html/rfc6455

    The Java Broker (currently) takes the former approach, it's a
    sensible and convenient approach because it uses Jetty as the Web
    Server for its UI and Jetty comes complete with a WebSocket
    implementation, but there's a down side - you have to stand up a
    separate port so basically AMQP over TCP connections connect to
    one port and AMQP over WebSocket connections connect over a
    different port.

    But as I say WebSockets are actually layered over TCP so it's
    possible if you have more control over the server to look at the
    data on the TCP buffers and detect that it's actually WebSocket,
    so from a user perspective it would be *really nice* and
    technically possible to have a single listen port.


When I suggested implementing it in proton I meant the latter, simply autodetecting and upgrading. Andrew has done some nice work around this sort of thing already with detecting SSL vs plain and detecting SASL vs just core AMQP, so autodetecting the HTTP header and doing the upgrade would be a natural and hopefully straightforward way to go. At that point you just configure on the transport whether you want to allow it or not.
That's cool, I thought that was what you had in mind when you mentioned Andrew's autodetect stuff but thought I should include Rob and mention the Java Broker approach to see if there were views on the relative merits of each.




    That's kind of a nice segway into another point
    1. Use a library
    2. Roll your own/copy paste reuse

    I'm torn on that, using a library is clearly good from a support
    perspective but the counter to that is illustrated by the point I
    make about using Jetty in the Java Broker. Of course you might
    *want* to force TCP and WebSocket connections to different ports
    but do we care more that it's AMQP or what the transport is
    (that's an open question BTW, I personally like the idea of just
    connecting to a single port but there may be good counter arguments).


    On a slightly library related note it's worth mentioning something
    on my TODO list. As you probably know the JavaScript binding is
    currently limited to using a WebSocket transport, that makes sense
    as a starter for ten 'cause obviously browsers have a number of
    constraints but for Node.js there's no real reason for that to be
    the case. You might have seen the TCP->WebSocket proxy stuff I
    wrote, if you have you'll see that it's actually technically
    pretty easy to implement at TCP version using the Node.js built in
    net library. The main reasons I've not done it yet are:
    1. Time - I only get to code at weekends and I'm juggling a couple
    of O/S projects at the moment #ifonlyididntneedtoworktolive :-)
    2. The emscripten network code really isn't as modular as it
    should be - I've done quite a lot of it, but I didn't originate it
    and TBH I'd quite like to pick it apart and make it a bit more
    layered, lack of time again.
    3. The biggest reason though is actually what approach to take. As
    above I'd really like to have a Node.js AMQP application that can
    just receive either a TCP or a WebSocket connection and *just
    work*. That's a bit awkward because I use ws as the WebSocket
    server. As it's so well established it's a bit daft to roll my own
    but I don't know, it's probably possible to Monkey Patch or
    otherwise expose the native TCP socket if a WebSocket connection
    fails, though probably the best approach would be to add a feature
    to ws and hope that the pull request gets accepted.


    Hopefully point three above illustrates one potentially awkward
    pinch-point, you'll be adding WebSocket server code in pure C and
    I'll be making the backend of the TCP path all WebSockety too :-)

    It *should* work out OK because  the emscripten stuff will
    establish a listener and ws will have removed all of the
    WebSockety stuff and just exposes the AMQP frames in the octet
    array that comes off the recv call, so the proton-c code *should*
    just interpret that as AMQP off a TCP socket and not send it to
    any of the proton-c WebSocket code, but depending on how its done
    it could go horribly wrong, which is why I figured I'd give a bit
    of background.


    All of the above has been from the perspective of a server
    receiving a WebSocket connection, in some respects though
    establishing a connection is actually more awkward....

    So it's not like it's technically hard to write the code to have
    Node.js establish an AMQP over TCP connection - the net library is
    pretty straightforward. The bit that I'm actually struggling with
    is how best to let applications choose between a TCP and WebSocket
    transport.

    As I say the default position is that the proton-c network code
    maps to emscripten library_sockfs.js calls that push the data over
    WebSockets - so what API to use to tell it to use TCP :-) It's
    easy to set a compile time option but that sucks, I'd like an
    application to be able to connect using either TCP or WebSockets.

    I was wondering if the getprotoent /etc/protocols stuff might be
    the best place, that's certainly where you'd get the protocol
    number for UDP, TCP or SCTP to the sockets API but that's used
    pretty much for the underlying Operating System networking and
    WebSockets currently tend to be implemented as user level
    libraries over TCP and I'm not aware of an official protocol entry
    for WebSockets.

    That's the only place in the socket API that I can think of that's
    even close to being able to specify that sort of thing though :-/


    There are certainly other ways to pass that sort of info down to
    emscripten, but as I say I'm struggling for a clean approach.


    So that conundrum is kind of relevant to the native proton-c
    implementation too 'cause if you want to allow the ability to
    connect using either TCP or WebSockets there needs to be something
    in the API that allows users to choose. Is there anything in any
    of the AMQP specs that have actually covered this? I know that
    Qpid C++ has support for rdma but I *think* that's specified in
    the Connection config which offers a slightly richer set of
    connection options than the sort of amqp connection available in
    Proton (certainly from what I'm aware of with Messenger).


I think this should be fairly straightforward in proton-c. We already have a similar set of scenarios there with SSL and SASL autodetect. When you configure a Transport, you basically construct a stack of protocols. In server mode you can it autodetect whether each layer is present and fall through to the next. In client mode the stack is just what you have specified.

So I can see how the autodetect could be extended to handle this when acting as a server, but this last bit was really about what sort of "API" one might use for a client to establish a connection giving a runtime choice between a TCP or WebSocket transport. As I say for the qpid::messaging API the Connection allows quite a range of options but in Messenger at any rate I think the options are more limited and ISTR there are some restrictions even on SASL options, so as I say it's probably not "technically" hard I'm just not sure what the best "specify the transport" API might be for Proton - if you see what I mean?





    So I've covered some of the thought processes going through my
    mind as I've been thinking around WebSockets in native proton-c
    and most of them aren't really about the technical implementation
    of the WebSocket protocol, but I think are worth bearing in mind.


    In terms of actually implementing this stuff as Rafael said I
    think that options in C are fairly limited. As well as the library
    issues I mentioned earlier there's also the little matter of
    worrying about license incompatibilities, so my gut feeling is
    that the best approach might to get "inspiration" from other
    places and to grasp the nettle and implement something that
    integrates nicely with Proton.

    If it were me implementing this the first place I'd look would be
    here:
    https://github.com/kanaka/websockify

    WebSockify is actually a TCP->WebSocket proxy and TBH bits of it
    irritate me, but itQpid user list now for maximum exposure
    seems to be used quite a lot. The most significant things though
    is that:
    1. It implements a pretty complete WebSocket stack in Python,
    which you know so should help you figure things out
    2. It actually also has an implementation in C (under the "other"
    directory) so you might want to look at that
    3. I *think* that it accepts TCP or WebSocket connections on its
    listen port and just passes through TCP (I can't swear to that but
    it rings a bell)
    4. It's well used and well maintained so is likely to be a
    reliable starting point

    I'd also take a look at ws:
    https://github.com/websockets/ws

    This is clearly JavaScript, but it's one of the most commonly used
    and well maintained WebSocket libraries in any language, so again
    as a means to figure out how it actually works it might be a good
    place to look.


    BTW Rafael mentioned the annoying thing about there being lots of
    different WebSocket versions, that's certainly true, but is much
    less of an issue now. That stuff was generally a pain as the
    WebSocket protocol was evolving, but it has now been standardised
    in the IETF RFC 6455 I linked earlier and all of the main browsers
    primarily support that. Looking on the websockify page there is a
    comment "Starting with websockify 0.5.0, only the HyBi / IETF 6455
    WebSocket protocol is supported". Unless there's a compelling
    customer reason to support pre-standard versions I don't think
    it's unreasonable to only support RFC 6455. It's also worth
    bearing in mind that the emscripten based JavaScript binding
    requires binary support anyway and I think that's only supported
    on the final versions of the spec. so there's probably little
    actual value in supporting anything else.

    Sorry for the essay, hope it's useful.

    I'm off to focus on my other project now - I'm currently trying to
    write an implementation of webcl using webgl, cause I need to do
    some GPU programming and my platform doesn't have opencl
    support.......

    Cheers,
    Frase

    On 04/02/15 19:30, Alan Conway wrote:

        On Wed, 2015-02-04 at 17:55 +0000, Fraser Adams wrote:

            Hi Alan, very quick placeholder response. I've a couple of
            family
            commitments so won't be able to give a decent response for
            a day or so -
            don't want you to think I'm rude by not getting back.

            It's a topic that deserves a bit of thought 'cause it
            could be a bit of
            a car-crash if not thought through.

        Thanks for the warning! Andrew Stitcher is making changes to the
        transport layer that will affect this (make it easier) so I'm
        not moving
        on proton till that is done. When I do I will consult
        carefully with
        yourself and Andrew to avoid crashing any cars.

        I may try some short term hackery to tide me over but if I do
        it will be
        in the dispatch codebase and strictly limited to supporting
        dispatch's
        JS management console. Longer term proton is the right place
        to do it
        and I will avail of all advice so I do it right ;)

            Frase.

            On 04/02/15 14:46, Alan Conway wrote:

                Hi Fraser,

                I need a websocket listener in dispatch. Rafi points
                out (rightly) that
                it would be of wider use to do it in proton-c than in
                dispatch. Quick
                JIRA search reveals the word websocket next to your
                name - is that
                Java-only? I know nada about websockets, and not much
                more about JS if
                you remember our prev. conversation ;) Actually on
                that - I now realize
                that (duh!) the java build does the same
                barf-in-the-source-dir thing so
                I was razzing you for nothing. git-ignore is my friend.

                Hoping to pick your brains for anything useful on
                websockets. I'm
                guessing my options are
                - find a C websockets library (looks like there are
                some but none
                packaged with popular OS distros (at least the ones
                popular with me)
                - implement the websocket spec in C. Not sure how big
                a job that is yet.
                The spec is full of non-normative waffle so I'm not
                sure just how much
                real action there is.
                - grab a python ws library and just stick with
                dispatch since it has a
                nice C+python implementation. That wouldn't help
                proton though.

                Any thoughts?

                Cheers
                Alan.





Reply via email to