subprotocol? #155

Closed
robagar opened this Issue Oct 19, 2012 · 8 comments

Projects

None yet

5 participants

@robagar
robagar commented Oct 19, 2012

If I open a connection like this in javascript

var ws =  new WebSocket('ws://localhost:9000', 'foo');

what happens to the "foo". Should it be returned in connection::get_subprotocols() in the on_open callback?

@zaphoyd
Owner
zaphoyd commented Oct 19, 2012

if the browser supports subprotocols, you will send them as an array in javascript.

new WebSocket(String url, Array subprotocol)

On the WebSocket++ end, the validate() method will be able to use get_subprotocols() to view which ones the client suggests (it returns const std::vector<std::string>&). The server then needs to select one of them using select_subprotocol(std::string). This concludes the subprotocol negotiation and if the client doesn't immediately disconnect that subprotocol should be considered to be in effect.

On the client end, WebSocket++ clients can use add_subprotocol(const std::string& value) to add subprotocols to the request before the initial connection is made.

It looks like I don't have a great way to grab the final negotiated subprotocol from on_open though (short of remembering which one you sent in validate() ). I'll look into that.

@robagar
robagar commented Oct 22, 2012

I think there may be a bug - get_subprotocols() is returning an empty list for me. I have tried it with Firefox 16 and Chromium 20 on linux, passing the subprotocol both as an array and as just a string (which I believe is allowd by the WebSocket spec)

@jeffjcrowe

I got the same results as @robagar. It doesn't look like anything ever writes to m_requested_subprotocols.
I added a small patch to server.hpp which made it work for me.

index 1e1f13a..a60948a 100644
--- a/src/roles/server.hpp
+++ b/src/roles/server.hpp
@@ -608,6 +608,20 @@ void server<endpoint>::connection<connection_type>::handle_read_request(
             }

             m_connection.m_processor->validate_handshake(m_request);
+
+            std::string subprotocols = m_request.header("Sec-WebSocket-Protocol");
+            if(subprotocols.length() > 0) {
+               boost::char_separator<char> sep(",");
+               boost::tokenizer<boost::char_separator<char>> tokens(subprotocols, sep);
+               for(boost::tokenizer<boost::char_separator<char>>::iterator it = tokens.begin(); it != tokens.end(); ++it){
+                   std::string proto = *it;
+                   boost::trim(proto);
+                   if (proto.length() > 0){
+                       m_requested_subprotocols.push_back(proto);
+                   }
+               }
+            }
+
             m_origin = m_connection.m_processor->get_origin(m_request);
             m_uri = m_connection.m_processor->get_uri(m_request);
@zaphoyd
Owner
zaphoyd commented Dec 11, 2012

This is indeed a bug. It has been fixed and unit tested now in 0.3.x. I've applied jeffjcrowe's patch to the 0.2.0d branch.

@zaphoyd zaphoyd added a commit that closed this issue Dec 11, 2012
@zaphoyd m_requested_subprotocols wasn't getting populated. fixes #155
Thank you to robagar for finding this bug and jeffjcrowe for supplying
a patch
0318700
@zaphoyd zaphoyd closed this in 0318700 Dec 11, 2012
@jamesjenner

Thanks for this. Just spent a couple of hours trying to figure out what I had did wrong and then saw this. Tested on Chrome 23.0.1271.95 and works perfectly.

@pettno
pettno commented Aug 5, 2013

Could this be an issue with the latest version now as well? I can't get any subprotocols in on_validate().

@zaphoyd
Owner
zaphoyd commented Aug 5, 2013

I just re-tested 0.3.0/HEAD with the latest version of Safari, Chrome, and FireFox and it seems to correctly pull the subprotocol sent by the browser. Can you provide any more information about what isn't working for you?

@pettno
pettno commented Aug 12, 2013

Never mind. The bug was located in my own code. Sorry for the noise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment