Commit c24becf2152e131882af98d5e0810d13162aefc6

Authored by Wiebe Cazemier
1 parent 1ca1bdf6

Allow for any websocket protocol containing mqtt

I've see various variations, like mqtt and mqttv31. The 3.1.1 specs are
clear what it should be, but the 3.1 specs aren't. So, allowing
anything with mqtt in it.
iowrapper.cpp
@@ -371,7 +371,8 @@ ssize_t IoWrapper::readWebsocketAndOrSsl(int fd, void *buf, size_t nbytes, IoWra @@ -371,7 +371,8 @@ ssize_t IoWrapper::readWebsocketAndOrSsl(int fd, void *buf, size_t nbytes, IoWra
371 { 371 {
372 std::string websocketKey; 372 std::string websocketKey;
373 int websocketVersion; 373 int websocketVersion;
374 - if (parseHttpHeader(websocketPendingBytes, websocketKey, websocketVersion)) 374 + std::string subprotocol;
  375 + if (parseHttpHeader(websocketPendingBytes, websocketKey, websocketVersion, subprotocol))
375 { 376 {
376 if (websocketKey.empty()) 377 if (websocketKey.empty())
377 throw BadHttpRequest("No websocket key specified."); 378 throw BadHttpRequest("No websocket key specified.");
@@ -380,7 +381,7 @@ ssize_t IoWrapper::readWebsocketAndOrSsl(int fd, void *buf, size_t nbytes, IoWra @@ -380,7 +381,7 @@ ssize_t IoWrapper::readWebsocketAndOrSsl(int fd, void *buf, size_t nbytes, IoWra
380 381
381 const std::string acceptString = generateWebsocketAcceptString(websocketKey); 382 const std::string acceptString = generateWebsocketAcceptString(websocketKey);
382 383
383 - std::string answer = generateWebsocketAnswer(acceptString); 384 + std::string answer = generateWebsocketAnswer(acceptString, subprotocol);
384 parentClient->writeText(answer); 385 parentClient->writeText(answer);
385 websocketState = WebsocketState::Upgrading; 386 websocketState = WebsocketState::Upgrading;
386 websocketPendingBytes.reset(); 387 websocketPendingBytes.reset();
utils.cpp
@@ -348,7 +348,7 @@ bool isPowerOfTwo(int n) @@ -348,7 +348,7 @@ bool isPowerOfTwo(int n)
348 return (n != 0) && (n & (n - 1)) == 0; 348 return (n != 0) && (n & (n - 1)) == 0;
349 } 349 }
350 350
351 -bool parseHttpHeader(CirBuf &buf, std::string &websocket_key, int &websocket_version) 351 +bool parseHttpHeader(CirBuf &buf, std::string &websocket_key, int &websocket_version, std::string &subprotocol)
352 { 352 {
353 const std::string s(buf.tailPtr(), buf.usedBytes()); 353 const std::string s(buf.tailPtr(), buf.usedBytes());
354 std::istringstream is(s); 354 std::istringstream is(s);
@@ -397,8 +397,11 @@ bool parseHttpHeader(CirBuf &buf, std::string &websocket_key, int &websocket_ver @@ -397,8 +397,11 @@ bool parseHttpHeader(CirBuf &buf, std::string &websocket_key, int &websocket_ver
397 websocket_key = value; 397 websocket_key = value;
398 else if (name == "sec-websocket-version") 398 else if (name == "sec-websocket-version")
399 websocket_version = stoi(value); 399 websocket_version = stoi(value);
400 - else if (name == "sec-websocket-protocol" && value_lower == "mqtt") 400 + else if (name == "sec-websocket-protocol" && strContains(value_lower, "mqtt"))
  401 + {
  402 + subprotocol = value;
401 subprotocol_seen = true; 403 subprotocol_seen = true;
  404 + }
402 } 405 }
403 406
404 if (doubleEmptyLine) 407 if (doubleEmptyLine)
@@ -489,14 +492,14 @@ std::string generateBadHttpRequestReponse(const std::string &msg) @@ -489,14 +492,14 @@ std::string generateBadHttpRequestReponse(const std::string &msg)
489 return oss.str(); 492 return oss.str();
490 } 493 }
491 494
492 -std::string generateWebsocketAnswer(const std::string &acceptString) 495 +std::string generateWebsocketAnswer(const std::string &acceptString, const std::string &subprotocol)
493 { 496 {
494 std::ostringstream oss; 497 std::ostringstream oss;
495 oss << "HTTP/1.1 101 Switching Protocols\r\n"; 498 oss << "HTTP/1.1 101 Switching Protocols\r\n";
496 oss << "Upgrade: websocket\r\n"; 499 oss << "Upgrade: websocket\r\n";
497 oss << "Connection: Upgrade\r\n"; 500 oss << "Connection: Upgrade\r\n";
498 oss << "Sec-WebSocket-Accept: " << acceptString << "\r\n"; 501 oss << "Sec-WebSocket-Accept: " << acceptString << "\r\n";
499 - oss << "Sec-WebSocket-Protocol: mqtt\r\n"; 502 + oss << "Sec-WebSocket-Protocol: " << subprotocol << "\r\n";
500 oss << "\r\n"; 503 oss << "\r\n";
501 oss.flush(); 504 oss.flush();
502 return oss.str(); 505 return oss.str();
@@ -77,7 +77,7 @@ std::string str_tolower(std::string s); @@ -77,7 +77,7 @@ std::string str_tolower(std::string s);
77 bool stringTruthiness(const std::string &val); 77 bool stringTruthiness(const std::string &val);
78 bool isPowerOfTwo(int val); 78 bool isPowerOfTwo(int val);
79 79
80 -bool parseHttpHeader(CirBuf &buf, std::string &websocket_key, int &websocket_version); 80 +bool parseHttpHeader(CirBuf &buf, std::string &websocket_key, int &websocket_version, std::string &subprotocol);
81 81
82 std::vector<char> base64Decode(const std::string &s); 82 std::vector<char> base64Decode(const std::string &s);
83 std::string base64Encode(const unsigned char *input, const int length); 83 std::string base64Encode(const unsigned char *input, const int length);
@@ -85,7 +85,7 @@ std::string generateWebsocketAcceptString(const std::string &amp;websocketKey); @@ -85,7 +85,7 @@ std::string generateWebsocketAcceptString(const std::string &amp;websocketKey);
85 85
86 std::string generateInvalidWebsocketVersionHttpHeaders(const int wantedVersion); 86 std::string generateInvalidWebsocketVersionHttpHeaders(const int wantedVersion);
87 std::string generateBadHttpRequestReponse(const std::string &msg); 87 std::string generateBadHttpRequestReponse(const std::string &msg);
88 -std::string generateWebsocketAnswer(const std::string &acceptString); 88 +std::string generateWebsocketAnswer(const std::string &acceptString, const std::string &subprotocol);
89 89
90 void testSsl(const std::string &fullchain, const std::string &privkey); 90 void testSsl(const std::string &fullchain, const std::string &privkey);
91 91