Commit c24becf2152e131882af98d5e0810d13162aefc6
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.
Showing
3 changed files
with
12 additions
and
8 deletions
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(); |
utils.h
| @@ -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 &websocketKey); | @@ -85,7 +85,7 @@ std::string generateWebsocketAcceptString(const std::string &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 |