wampcc
wampcc copied to clipboard
websocket + SSL support
Is this possible? e.g. given a URL wss://wamp.website.whatever how would I connect?
I attempted to create an SSL socket
std::unique_ptr<ssl_socket> sock(new ssl_socket(&the_kernel));
[... connect, check the handshake was valid, etc ...]
websocket_protocol::options ws_opts;
ws_opts.serialisers = (int)serialiser_type::json;
auto session = wamp_session::create<websocket_protocol>(&the_kernel,
std::move(sock), nullptr, ws_opts);
but I always get
... WARN session #1 handhake error: http header is not a websocket upgrade
... INFO session #1 closing
added some logging code and it seemed to imply the server felt the request was bad (400 error)
Hi. I've just found a bug in the websocket upgrade code. It was assuming the Sec-WebSocket-Protocol would always be present, but turns out some browsers dont set it. That has been fixed, checked into master. I'll test to see if the same fix works on an SSL example.
Partial success with using wss.
Added a new example, examples/wamp_router
which listens on an SSL socket (and this builds automatically as part of autotools). Additionally there is a test client webpage at javascript/test_client/test_client.html
An initial attempt to use the above test-client to connect to the router fails (entering "wss://127.0.0.1:55555" in the WAMP Server text field) . In chromium it gives error 'net::ERR_INSECURE_RESPONSE'. In firefox, it complains "tlsv1 alert unknown ca". I think both of these issues are related to the self-signed SSL certificates I am using.
The only way I could get it working was to start chromium with option --ignore-certificate-errors
chromium-browser --user-data-dir=/tmp/mychromium --ignore-certificate-errors
I suppose there might be a way to improve the validity of the SSL certificates, so that chromium & firefox will accept.
@emgram769 ,yes, it can, just replace tcp_socket with ssl_socket. But i havn't figured out how to pass a function pointer to handle the repsonse data.
@emgram769 oh, the same problem happened to me at the beginning. After a whole day debugging, it turned out be the HOST field in the HTTP header, you should fill it with the dns name , not the address.
@darrenjs hi, can you give a example on how to pass a function pointer to handle the response data of in subscriber(client) mode
Hi, an example subscriber can be found at
https://github.com/darrenjs/wampcc/blob/master/examples/basic/basic_subscriber.cc
... there you can see that during the call to session->subscribe( ... ) you pass in two lambda callbacks :
t_request_id subscribe(const std::string& uri,
json_object options,
on_subscribed_fn, /* callback on success / failure */
on_event_fn, /* callback when data arrives */
void * user = nullptr);
If you want to use function pointers, then you can just pass them in via these lambdas. I.e. capture the function pointer in the lambda closure, and in the body of the lambda, make a call to your function object,
Note the two different callbacks:
on_subscribed_fn
-- called when the subscription is deemed successful or has failed. This corresponds to the WAMP SUBSCRIBED message or ERROR message. It is important to check this callback, because if your subscription request is rejected by the server (e.g. perhaps the topic you have requested is not found) then you will never receive messages for the topic.
on_event_fn
-- called each time a WAMP EVENT message arrives for the topic. These will only arrive if the subscription was successful.
@darrenjs what if i use ssl_socket, here is a example , wss://api.poloniex.com, subscribe to BTC_ETH. The connect and websocket handshake is ok, but i haven't got any event and data in on_event_fn,in fact it was never called. I am not sure whether the server actually publish no data or just the on_event_fn not called. On the other hand, i got some data printed out discontinuously when i add printf in void websocket_protocol::io_on_read(char* src, size_t len)
@darrenjs My subcription was correct, and i have got a successful msg and subscription_id
Hi.... that does sound odd, because that symbol ticks frequently. Is poloniex still supporting WAMP protocol? I thought it had been deprecated, and they are using their own API. There was a previous wampcc issue (#9) related to poloniex, could be useful for you to review.
Did you confirm that the subscription was successful, during the on_subscribed_fn
callback? Also, do you need to check with poloniex that your account is set up to allow for subscriptions?
As for the printf data that your are seeing, it could be some kind of heartbeat. I think you should be able to enable additional logging to get the bytes printed into your own application logger, maybe post some examples here.
here is the debug log , there is some prinf by my self, i have not delete them, sorry... tcp_socket::on_read_cb: @H(" tcp_socket::on_read_cb: @H(" 20171218-17:04:00.872482 6468 TRACE fd: 10, ssl handshake success (ssl_socket.cc:232) 20171218-17:04:00.873044 6467 TRACE fd: 10, http_tx: GET / HTTP/1.1 Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Connection: Upgrade Host: api.poloniex.com:443 Sec-WebSocket-Key: vgZ+3J2LXcHqj/99Z45l9A== Sec-WebSocket-Protocol: wamp.2.json,wamp.2.msgpack Sec-WebSocket-Version: 13
(websocket_protocol.cc:357) handshake: GET / HTTP/1.1 Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Connection: Upgrade Host: api.poloniex.com:443 Sec-WebSocket-Key: vgZ+3J2LXcHqj/99Z45l9A== Sec-WebSocket-Protocol: wamp.2.json,wamp.2.msgpack Sec-WebSocket-Version: 13
tcp_socket::on_read_cb: @H(" wamp_session::io_on_read: HTTP/1.1 101 Switching Protocols Date: Mon, 18 Dec 2017 09:04:04 GMT Connection: upgrade Set-Cookie: __cfduid=da6dedfdb67ee9f9531663c0aaf6e9de31513587843; expires=Tue, 18-Dec-18 09:04:03 GMT; path=/; domain=.poloniex.com; HttpOnly Upgrade: WebSocket Sec-WebSocket-Protocol: wamp.2.json Sec-WebSocket-Accept: Y6YFvpp84nn/xFISCeLpWALXWR0= Server: cloudflare-nginx CF-RAY: 3cf0f3d59a0684a8-HKG
websocket_protocol::io_on_read: HTTP/1.1 101 Switching Protocols Date: Mon, 18 Dec 2017 09:04:04 GMT Connection: upgrade Set-Cookie: __cfduid=da6dedfdb67ee9f9531663c0aaf6e9de31513587843; expires=Tue, 18-Dec-18 09:04:03 GMT; path=/; domain=.poloniex.com; HttpOnly Upgrade: WebSocket Sec-WebSocket-Protocol: wamp.2.json Sec-WebSocket-Accept: Y6YFvpp84nn/xFISCeLpWALXWR0= Server: cloudflare-nginx CF-RAY: 3cf0f3d59a0684a8-HKG
20171218-17:04:01.771371 6468 TRACE fd: 10, http_rx: HTTP/1.1 101 Switching Protocols Date: Mon, 18 Dec 2017 09:04:04 GMT Connection: upgrade Set-Cookie: __cfduid=da6dedfdb67ee9f9531663c0aaf6e9de31513587843; expires=Tue, 18-Dec-18 09:04:03 GMT; path=/; domain=.poloniex.com; HttpOnly Upgrade: WebSocket Sec-WebSocket-Protocol: wamp.2.json Sec-WebSocket-Accept: Y6YFvpp84nn/xFISCeLpWALXWR0= Server: cloudflare-nginx CF-RAY: 3cf0f3d59a0684a8-HKG
(websocket_protocol.cc:252) 20171218-17:04:01.771460 6468 INFO session #1 state: from init to sent_hello (wamp_session.cc:511) 20171218-17:04:01.771533 6468 TRACE fd: 10, json_tx: [1, "realm1", {"agent": "wampcc 1.5", "roles": {"callee": {}, "caller": {}, "publisher": {}, "subscriber": {}}}] (websocket_protocol.cc:111) 20171218-17:04:01.771574 6468 TRACE fd: 10, frame_tx: fin 1, opcode 1, payload_len 112 (websocket_protocol.cc:135) tcp_socket::on_read_cb: @H(" wamp_session::io_on_read: ~N[2,5594559062488576,{"x_cb_node_id":null,"realm":"realm1","authid":"WKFQ-49HS-YV9G-76P3-WR46-9CR5","authrole":"public","authmethod":"anonymous","authprovider":"static","roles":{"broker":{"features":{"publisher_identification":true,"pattern_based_subscription":true,"session_meta_api":true,"subscription_meta_api":true,"subscriber_blackwhite_listing":true,"publisher_exclusion":true,"subscription_revocation":true,"payload_transparency":true,"payload_encryption_cryptobox":true,"event_retention":true}},"dealer":{"features":{"caller_identification":true,"pattern_based_registration":true,"session_meta_api":true,"registration_meta_api":true,"shared_registration":true,"call_canceling":true,"progressive_call_results":true,"registration_revocation":true,"payload_transparency":true,"testament_meta_api":true,"payload_encryption_cryptobox":true}}}}] websocket_protocol::io_on_read: ~N[2,5594559062488576,{"x_cb_node_id":null,"realm":"realm1","authid":"WKFQ-49HS-YV9G-76P3-WR46-9CR5","authrole":"public","authmethod":"anonymous","authprovider":"static","roles":{"broker":{"features":{"publisher_identification":true,"pattern_based_subscription":true,"session_meta_api":true,"subscription_meta_api":true,"subscriber_blackwhite_listing":true,"publisher_exclusion":true,"subscription_revocation":true,"payload_transparency":true,"payload_encryption_cryptobox":true,"event_retention":true}},"dealer":{"features":{"caller_identification":true,"pattern_based_registration":true,"session_meta_api":true,"registration_meta_api":true,"shared_registration":true,"call_canceling":true,"progressive_call_results":true,"registration_revocation":true,"payload_transparency":true,"testament_meta_api":true,"payload_encryption_cryptobox":true}}}}] 20171218-17:04:02.051380 6468 TRACE fd: 10, frame_rx: fin 1, opcode 1, payload_len 846 (websocket_protocol.cc:460) 20171218-17:04:02.051568 6468 TRACE fd: 10, json_rx: [2, 5594559062488576, {"authid": "WKFQ-49HS-YV9G-76P3-WR46-9CR5", "authmethod": "anonymous", "authprovider": "static", "authrole": "public", "realm": "realm1", "roles": {"broker": {"features": {"event_retention": true, "pattern_based_subscription": true, "payload_encryption_cryptobox": true, "payload_transparency": true, "publisher_exclusion": true, "publisher_identification": true, "session_meta_api": true, "subscriber_blackwhite_listing": true, "subscription_meta_api": true, "subscription_revocation": true}}, "dealer": {"features": {"call_canceling": true, "caller_identification": true, "pattern_based_registration": true, "payload_encryption_cryptobox": true, "payload_transparency": true, "progressive_call_results": true, "registration_meta_api": true, "registration_revocation": true, "session_meta_api": true, "shared_registration": true, "testament_meta_api": true}}}, "x_cb_node_id": null}] (protocol.cc:172) wamp_session::on_msg_cb::msg_type: 2 json_array: [2, 5594559062488576, {"authid": "WKFQ-49HS-YV9G-76P3-WR46-9CR5", "authmethod": "anonymous", "authprovider": "static", "authrole": "public", "realm": "realm1", "roles": {"broker": {"features": {"event_retention": true, "pattern_based_subscription": true, "payload_encryption_cryptobox": true, "payload_transparency": true, "publisher_exclusion": true, "publisher_identification": true, "session_meta_api": true, "subscriber_blackwhite_listing": true, "subscription_meta_api": true, "subscription_revocation": true}}, "dealer": {"features": {"call_canceling": true, "caller_identification": true, "pattern_based_registration": true, "payload_encryption_cryptobox": true, "payload_transparency": true, "progressive_call_results": true, "registration_meta_api": true, "registration_revocation": true, "session_meta_api": true, "shared_registration": true, "testament_meta_api": true}}}, "x_cb_node_id": null}] got a message! [client] msg type: wamp_msg_welcome 20171218-17:04:02.052043 6469 INFO session #1 state: from sent_hello to open (wamp_session.cc:511) 20171218-17:04:02.052225 6467 TRACE fd: 10, json_tx: [32, 1, {}, "BTC_ETH"] (websocket_protocol.cc:111) 20171218-17:04:02.052258 6467 TRACE fd: 10, frame_tx: fin 1, opcode 1, payload_len 22 (websocket_protocol.cc:135) 20171218-17:04:02.052279 6467 INFO session #1 sending subscribe for 'BTC_ETH', request_id 1 (wamp_session.cc:1322) tcp_socket::on_read_cb: @H(" wamp_session::io_on_read: [33,1,6183330947819157]"x_cb_node_id":null,"realm":"realm1","authid":"WKFQ-49HS-YV9G-76P3-WR46-9CR5","authrole":"public","authmethod":"anonymous","authprovider":"static","roles":{"broker":{"features":{"publisher_identification":true,"pattern_based_subscription":true,"session_meta_api":true,"subscription_meta_api":true,"subscriber_blackwhite_listing":true,"publisher_exclusion":true,"subscription_revocation":true,"payload_transparency":true,"payload_encryption_cryptobox":true,"event_retention":true}},"dealer":{"features":{"caller_identification":true,"pattern_based_registration":true,"session_meta_api":true,"registration_meta_api":true,"shared_registration":true,"call_canceling":true,"progressive_call_results":true,"registration_revocation":true,"payload_transparency":true,"testament_meta_api":true,"payload_encryption_cryptobox":true}}}}] websocket_protocol::io_on_read: [33,1,6183330947819157]"x_cb_node_id":null,"realm":"realm1","authid":"WKFQ-49HS-YV9G-76P3-WR46-9CR5","authrole":"public","authmethod":"anonymous","authprovider":"static","roles":{"broker":{"features":{"publisher_identification":true,"pattern_based_subscription":true,"session_meta_api":true,"subscription_meta_api":true,"subscriber_blackwhite_listing":true,"publisher_exclusion":true,"subscription_revocation":true,"payload_transparency":true,"payload_encryption_cryptobox":true,"event_retention":true}},"dealer":{"features":{"caller_identification":true,"pattern_based_registration":true,"session_meta_api":true,"registration_meta_api":true,"shared_registration":true,"call_canceling":true,"progressive_call_results":true,"registration_revocation":true,"payload_transparency":true,"testament_meta_api":true,"payload_encryption_cryptobox":true}}}}] 20171218-17:04:02.330728 6468 TRACE fd: 10, frame_rx: fin 1, opcode 1, payload_len 23 (websocket_protocol.cc:460) 20171218-17:04:02.330816 6468 TRACE fd: 10, json_rx: [33, 1, 6183330947819157] (protocol.cc:172) wamp_session::on_msg_cb::msg_type: 33 json_array: [33, 1, 6183330947819157] got a message! [client] msg type: wamp_msg_subscribe 20171218-17:04:02.331017 6469 INFO subscribed to topic 'BTC_ETH' with subscription_id 6183330947819157 (wamp_session.cc:1387) subscription successful for 'BTC_ETH', subscription_id 6183330947819157 tcp_socket::on_read_cb: @H(" wamp_session::io_on_read: ‰W6Pj1,6183330947819157]"x_cb_node_id":null,"realm":"realm1","authid":"WKFQ-49HS-YV9G-76P3-WR46-9CR5","authrole":"public","authmethod":"anonymous","authprovider":"static","roles":{"broker":{"features":{"publisher_identification":true,"pattern_based_subscription":true,"session_meta_api":true,"subscription_meta_api":true,"subscriber_blackwhite_listing":true,"publisher_exclusion":true,"subscription_revocation":true,"payload_transparency":true,"payload_encryption_cryptobox":true,"event_retention":true}},"dealer":{"features":{"caller_identification":true,"pattern_based_registration":true,"session_meta_api":true,"registration_meta_api":true,"shared_registration":true,"call_canceling":true,"progressive_call_results":true,"registration_revocation":true,"payload_transparency":true,"testament_meta_api":true,"payload_encryption_cryptobox":true}}}}] websocket_protocol::io_on_read: ‰W6Pj1,6183330947819157]"x_cb_node_id":null,"realm":"realm1","authid":"WKFQ-49HS-YV9G-76P3-WR46-9CR5","authrole":"public","authmethod":"anonymous","authprovider":"static","roles":{"broker":{"features":{"publisher_identification":true,"pattern_based_subscription":true,"session_meta_api":true,"subscription_meta_api":true,"subscriber_blackwhite_listing":true,"publisher_exclusion":true,"subscription_revocation":true,"payload_transparency":true,"payload_encryption_cryptobox":true,"event_retention":true}},"dealer":{"features":{"caller_identification":true,"pattern_based_registration":true,"session_meta_api":true,"registration_meta_api":true,"shared_registration":true,"call_canceling":true,"progressive_call_results":true,"registration_revocation":true,"payload_transparency":true,"testament_meta_api":true,"payload_encryption_cryptobox":true}}}}] 20171218-17:04:11.830065 6468 TRACE fd: 10, frame_rx: fin 1, opcode 9, payload_len 4 (websocket_protocol.cc:460) 20171218-17:04:11.830137 6468 TRACE fd: 10, frame_tx: fin 1, opcode 10, payload_len 4 (websocket_protocol.cc:366)
@darrenjs
Ok ... the subscription seems successful. There is unexpected output in your log though ... the long json message from the initial connection handshake is repeated several times. What about subscribing to "ticker"
... does that work? Also ... try having a delay of about 1 seconds between the successful connection and the subscribe. Perhaps poloniex needs time on their side to set up your session.
I also see in the messages from poloniex server the entry "payload_encryption_cryptobox":true
... so maybe poloniex are encrypting the actual message payload? If so, wampcc doesn't support this, and as far as I can tell, payload encryption is not yet part of the WAMP specifiction.
@darrenjs whether i use “ticker" or "BTC_ETH", there is no much difference. try having a delay of about 1 seconds does not help either. If poloniex are encrypting the actual message payload, where can i get the pure payload in the lib? For now , i haven't got that yet. Thank you!
now i have turned to bitfiniex, it seems that this platform has more technical infomation&support. but here is the trouble i got: 20171219-11:57:41.293809 9103 TRACE fd: 10, ssl handshake success (ssl_socket.cc:232) 20171219-11:57:41.294343 9102 TRACE fd: 10, http_tx: GET /ws HTTP/1.1 Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Connection: Upgrade Host: api.bitfinex.com:443 Sec-WebSocket-Key: qtmv63Kb31UZHok+bLkuAw== Sec-WebSocket-Protocol: wamp.2.json,wamp.2.msgpack Sec-WebSocket-Version: 13
(websocket_protocol.cc:358) 20171219-11:57:42.570522 9103 TRACE fd: 10, http_rx: HTTP/1.1 101 Switching Protocols Date: Tue, 19 Dec 2017 03:57:45 GMT Connection: upgrade Set-Cookie: __cfduid=ddd3ae2dbe4173af36ea40726f9c881ea1513655863; expires=Wed, 19-Dec-18 03:57:43 GMT; path=/; domain=.bitfinex.com; HttpOnly Upgrade: websocket Sec-WebSocket-Accept: 4Ji7b97DkRvqOjbFwRTacCRzeCc= Sec-WebSocket-Protocol: wamp.2.json,wamp.2.msgpack Sec-WebSocket-Version: 13 WebSocket-Server: uWebSockets Server: cloudflare-nginx CF-RAY: 3cf7707d8c2c32b9-HKG
(websocket_protocol.cc:252) 20171219-11:57:42.570743 9103 WARN session #1 handhake error: failed to negotiate websocket message serialiser (wamp_session.cc:715) 20171219-11:57:43.074181 9104 WARN session #1 timeout waiting for peer (wamp_session.cc:2238) 20171219-11:57:43.074251 9104 INFO session #1 closing (wamp_session.cc:2355) time-out during session logon
it seems that the server accepted my handshake, but the client can not handle the serialiser type. on poloniex, it is ok, and here is the handshake infomation i got on poloniex: 20171219-11:58:24.028105 9108 TRACE fd: 10, ssl handshake success (ssl_socket.cc:232) 20171219-11:58:24.028536 9107 TRACE fd: 10, http_tx: GET /ws HTTP/1.1 Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Connection: Upgrade Host: api.poloniex.com:443 Sec-WebSocket-Key: i9nj3hQZhHSs3N63t2EI3Q== Sec-WebSocket-Protocol: wamp.2.json,wamp.2.msgpack Sec-WebSocket-Version: 13
(websocket_protocol.cc:358) 20171219-11:58:24.826084 9108 TRACE fd: 10, http_rx: HTTP/1.1 101 Switching Protocols Date: Tue, 19 Dec 2017 03:58:28 GMT Connection: upgrade Set-Cookie: __cfduid=dcd7d6d8842d2725e8cce88c8e45938b71513655907; expires=Wed, 19-Dec-18 03:58:27 GMT; path=/; domain=.poloniex.com; HttpOnly Upgrade: WebSocket Sec-WebSocket-Protocol: wamp.2.json Sec-WebSocket-Accept: DvSDOvsrfKXBHcayC8r1eB/ZcB8= Server: cloudflare-nginx CF-RAY: 3cf7718cdcc633b5-HKG
(websocket_protocol.cc:252) 20171219-11:58:24.826163 9108 INFO session #1 state: from init to sent_hello (wamp_session.cc:512) 20171219-11:58:24.826229 9108 TRACE fd: 10, json_tx: [1, "realm1", {"agent": "wampcc 1.5", "roles": {"callee": {}, "caller": {}, "publisher": {}, "subscriber": {}}}] (websocket_protocol.cc:111) 20171219-11:58:24.826265 9108 TRACE fd: 10, frame_tx: fin 1, opcode 1, payload_len 112 (websocket_protocol.cc:135) 20171219-11:58:25.120333 9108 TRACE fd: 10, frame_rx: fin 1, opcode 1, payload_len 846 (websocket_protocol.cc:461)
@darrenjs
Hi, looks a like a problem with the server. The client is advertising the ability to speak two serialiser types (wamp.2.json,wamp.2.msgpack) but the server is not selecting which one to use.
As a work around, you can change your client so that during the handshake it only advertises one serialiser type instead of two. E.g, lets say we only want to speak wamp.2.json.
Somewhere in your code there will be place where you construct a wamp_session
. You can give it extra arguments to specify the serialisers to support.
wampcc::websocket_protocol::options proto_opts;
wampcc::wamp_session::options session_opts;
proto_opts.serialisers = static_cast<int>(wampcc::serialiser_type::json); // Only json
ws = wampcc::wamp_session::create<wampcc::websocket_protocol>(
g_kernel.get(),
std::move(sock),
[](wampcc::wamp_session&, bool is_open) {
/* implement callback */
}, proto_opts, session_opts);
@darrenjs thank you , that works. https://docs.bitfinex.com/docs#section-unsubscribe-to-channels, it says there are channels, and i got 20000 code, and "channel:invalid" error msg, what is a channel here?
@lidehuth the bitfiniex protocol is not WAMP. They are using websocket, and json formatted messages, but they are using some other messaging protocol. You won't be able to use wampcc to interact with this protocol.
Ok , thank you
@darrenjs now i doubt that i have to supply some credential information to poloniex to receive actual publish data. Now i have enabled my api on poloniex and got a secret and a api key but i don't know how to fill the following struct: struct client_credentials { std::string realm; std::string authid; std::vector< std::string > authmethods; std::function< std::string() > secret_fn;
client_credentials() = default; client_credentials(std::string realm_) : realm(std::move(realm_)) {} };
Logon credentials can be set like this:
client_credentials credentials;
credentials.realm="MY_REALM";
credentials.authid="MY_API_KEY";
credentials.authmethods = {"wampcra"};
credentials.secret_fn = []() -> std::string { return "MY_SECRET"; };
@darrenjs i have got a msg as follows: ”message": " cannot authenticate using any of the offered authmethods [u'wampcra']"}, "wamp.error.no_auth_method" if i fill authmethod with "", i got "invalid authmethold"
worth checking this answer --> https://stackoverflow.com/questions/32154121/how-to-connect-to-poloniex-com-websocket-api-using-a-python-library/38254622#38254622
... seems poloniex might no longer support WAMP protocol.