Hi Ernie,
It has been a little while since I tinkered around in this space (sorry
I've been so Qpid quiet recently BTW, I'm working on another project
that's turned into a bit of a time-sink), but the fact that you are
using websockify rings a few alarm bells with me.
Not that there's anything wrong with websockify per se, it's just that
from my recollection it makes use of websocket subprotocols
So specifically websockify expects the websocket subprotocol to be
"binary" for binary websockets or "base64" for, well, base64. OTOH the
AMQP spec expects the websocket subprotocol to be "AMQPWSB10"
There was a conversation around that back in December when Rafi had some
problems with websockify and the JavaScript binding.
The most relevant mail in the thread is (hopefully) attached.
Basically it needed a slightly hacked websockify to default to binary
and only explicitly check for base64 or alternatively some compile time
(or run time) tweaks to the JavaScript to use binary instead of AMQPWSB10
Looking at the description below it looks like you've got it working,
but I'm curious what you did because last time I played with websockify
it didn't just work out of the box when using a proper AMQPWSB10
subprotocol.
Cheers,
Frase
On 14/07/15 19:55, Ernie Allen wrote:
-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://reviews.apache.org/r/36480/
-----------------------------------------------------------
Review request for qpid, Alan Conway, Ganesh Murthy, Kenneth Giusti, mick
goulish, and Ted Ross.
Repository: qpid-dispatch
Description
-------
This modifies the schema by adding a console entity. In the console entity you
can define the attributes needed to run a proxy server that translates
websockets to tcp and also serves http file requests.
listener {
...
name: proxy
...
}
console {
listener: proxy
dir: /home/eallen/dispatch-svn/tools/websockify/
home: webapps
proxy: qdproxy
wsport: 5673
}
Diffs
-----
trunk/python/qpid_dispatch/management/qdrouter.json 1690252
trunk/python/qpid_dispatch_internal/management/agent.py 1690252
Diff: https://reviews.apache.org/r/36480/diff/
Testing
-------
bin/test.sh passes all tests.
I replaced the nodejs proxy I was using with the new python/websockify server.
In the 6 router network, I changed A.conf and added a name to the listener and
added a console section that runs the python proxy/server.
The web console retrieves all html/js/css files, connects and communicates to
the router network through the proxy.
Thanks,
Ernie Allen
--- Begin Message ---
On 12/12/14 18:30, Rafael Schloming wrote:
Hmm, so I hacked websockify to ignore what is specifed in the
protocols header and hard coded it first to use binary, and second to
use base64. Neither option seemed to work.
Hi again Rafi,
My bet is that when you hacked Websockify you didn't update the
response, my hack of websockify/websockify.py (do_websocket_handshake)
looks like:
def do_websocket_handshake(self, headers, path):
h = self.headers = headers
self.path = path
prot = 'WebSocket-Protocol'
protocols = h.get('Sec-'+prot, h.get(prot, '')).split(',')
ver = h.get('Sec-WebSocket-Version')
if ver:
# HyBi/IETF version of the protocol
# HyBi-07 report version 7
# HyBi-08 - HyBi-12 report version 8
# HyBi-13 reports version 13
if ver in ['7', '8', '13']:
self.version = "hybi-%02d" % int(ver)
else:
raise self.EClose('Unsupported protocol version %s' % ver)
key = h['Sec-WebSocket-Key']
# Choose binary unless the client explicityly asks for Base64
if 'base64' in protocols:
self.base64 = True
else:
self.base64 = False
#raise self.EClose("Client must support 'binary' or
'base64' protocol")
# Generate the hash value for the accept header
accept = b64encode(sha1(s2b(key + self.GUID)).digest())
response = self.server_handshake_hybi % b2s(accept)
if self.base64:
response += "Sec-WebSocket-Protocol: base64\r\n"
else:
response += "Sec-WebSocket-Protocol: " + ',
'.join(protocols) + "\r\n"
response += "\r\n"
else:
# Hixie version of the protocol (75 or 76)
if h.get('key3'):
trailer = self.gen_md5(h)
pre = "Sec-"
self.version = "hixie-76"
else:
trailer = ""
pre = ""
self.version = "hixie-75"
# We only support base64 in Hixie era
self.base64 = True
response = self.server_handshake_hixie % (pre,
h['Origin'], pre, self.scheme, h['Host'], path)
if 'base64' in protocols:
response += "%sWebSocket-Protocol: base64\r\n" % pre
else:
self.msg("Warning: client does not report 'base64'
protocol support")
response += "\r\n" + trailer
return response
The changed bits are:
# Choose binary unless the client explicitly asks for Base64
if 'base64' in protocols:
self.base64 = True
else:
self.base64 = False
#raise self.EClose("Client must support 'binary' or
'base64' protocol")
and
if self.base64:
response += "Sec-WebSocket-Protocol: base64\r\n"
else:
response += "Sec-WebSocket-Protocol: " + ',
'.join(protocols) + "\r\n"
BTW for info I also tried hacking the JavaScript binding CMakeLists.txt
to remove the
-s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\"
and that works too (emscripten defaults to 'binary' unless a WebSocket
sub-protocol is specified, that's done mainly so Websockify works out of
the box, 'cause Websockify is what's used on the emscripten tests). The
relevant bits are in emscripten/src/settings.js:
// As well as being configurable at compile time via the "-s" option the
WEBSOCKET_URL and WEBSOCKET_SUBPROTOCOL
// settings may configured at run time via the Module object e.g.
// Module['websocket'] = {subprotocol: 'base64, binary, text'};
// Module['websocket'] = {url: 'wss://', subprotocol: 'base64'};
// Run time configuration may be useful as it lets an application select
multiple different services.
var WEBSOCKET_URL = 'ws://'; // A string containing either a WebSocket
URL prefix (ws:// or wss://) or a complete
// RFC 6455 URL - "ws[s]:" "//" host [ ":"
port ] path [ "?" query ].
// In the (default) case of only a prefix
being specified the URL will be constructed from
// prefix + addr + ':' + port
// where addr and port are derived from
the socket connect/bind/accept calls.
var WEBSOCKET_SUBPROTOCOL = 'binary'; // A string containing a comma
separated list of WebSocket subprotocols
// as would be present in the
Sec-WebSocket-Protocol header.
Less drastically than changing this at compile time it's also perfectly
possible to do it at run time.
If you look in say send.js you'll see a line that looks like:
var proton = require("qpid-proton");
if after that line you do:
proton['websocket']['subprotocol'] = 'binary';
That will make it work with an unhacked Websockify too, though as I
mentioned yesterday by setting this to binary rather than AMQPWSB10 it
will work with Websockify but not the Java Broker.
At least the last approach puts control firmly in your hands so you can
make it configurable. Actually I've just this moment tried:
proton['websocket']['subprotocol'] = 'binary, AMQPWSB10';
and that actually works with WebSockify too, but I've not yet checked
whether that would work with the Java Broker, if it does that might be
worth changing the compile/link flag to (though I suspect that it would
make it even more off-spec wrt. the AMQP JavaScript binding spec.).
proxy.js is tolerant to all these shenanigans though :-D I'd be the
first to admit that it needs some work in the error handling department
but it felt worth including 'cause it's pretty simple, is Node.js based
(which is already needed to compile the JavaScript binding, so no extra
dependencies), is Apache licensed.
HTH, and thanks for taking the time to have a play with the JavaScript
binding.
Cheers,
Frase
--- End Message ---
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]