diff options
| author | 2021-09-23 00:24:36 +0100 | |
|---|---|---|
| committer | 2021-09-23 00:24:36 +0100 | |
| commit | b5d7c564282f0b25458c3ca9dbd6aa9eec7d60d5 (patch) | |
| tree | f4b687e3ca0c5edfefd3ae7cdd3329012a603486 /src/modules/m_websocket.cpp | |
| parent | Merge branch 'insp3' into master. (diff) | |
| parent | Use CXX11_OVERRIDE instead of the override keyword. (diff) | |
Merge branch 'insp3' into master.
Diffstat (limited to 'src/modules/m_websocket.cpp')
| -rw-r--r-- | src/modules/m_websocket.cpp | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp index 6cf721424..242ecc372 100644 --- a/src/modules/m_websocket.cpp +++ b/src/modules/m_websocket.cpp @@ -35,17 +35,29 @@ static dynamic_reference_nocheck<HashProvider>* sha1; struct WebSocketConfig { + enum DefaultMode + { + // Reject connections if a subprotocol is not requested. + DM_REJECT, + + // Use binary frames if a subprotocol is not requested. + DM_BINARY, + + // Use UTF-8 text frames if a subprotocol is not requested. + DM_TEXT + }; + typedef std::vector<std::string> OriginList; typedef std::vector<std::string> ProxyRanges; // The HTTP origins that can connect to the server. OriginList allowedorigins; + // The method to use if a subprotocol is not negotiated. + DefaultMode defaultmode; + // The IP ranges which send trustworthy X-Real-IP or X-Forwarded-For headers. ProxyRanges proxyranges; - - // Whether to send as UTF-8 text instead of binary data. - bool sendastext; }; class WebSocketHookProvider : public IOHookProvider @@ -406,8 +418,10 @@ class WebSocketHook : public IOHookMiddle irc::spacesepstream protostream(protocolheader.ExtractValue(recvq)); for (std::string proto; protostream.GetToken(proto); ) { + bool is_binary = stdalgo::string::equalsci(proto, "binary.inspircd.org"); bool is_text = stdalgo::string::equalsci(proto, "text.inspircd.org"); - if (stdalgo::string::equalsci(proto, "binary.inspircd.org") || is_text) + + if (is_binary || is_text) { selectedproto = proto; sendastext = is_text; @@ -416,6 +430,12 @@ class WebSocketHook : public IOHookMiddle } } + if (selectedproto.empty() && config.defaultmode == WebSocketConfig::DM_REJECT) + { + FailHandshake(sock, "HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n", "WebSocket: Received HTTP request that did not send the Sec-WebSocket-Protocol header"); + return -1; + } + HTTPHeaderFinder keyheader; if (!keyheader.Find(recvq, "Sec-WebSocket-Key:", 18, reqend)) { @@ -452,11 +472,16 @@ class WebSocketHook : public IOHookMiddle WebSocketHook(std::shared_ptr<IOHookProvider> Prov, StreamSocket* sock, WebSocketConfig& cfg) : IOHookMiddle(Prov) , config(cfg) - , sendastext(cfg.sendastext) + , sendastext(config.defaultmode != WebSocketConfig::DM_BINARY) { sock->AddIOHook(this); } + bool IsHookReady() const override + { + return state == STATE_ESTABLISHED; + } + ssize_t OnStreamSocketWrite(StreamSocket* sock, StreamSocket::SendQueue& uppersendq) override { StreamSocket::SendQueue& mysendq = GetSendQ(); @@ -570,7 +595,16 @@ class ModuleWebSocket : public Module } auto tag = ServerInstance->Config->ConfValue("websocket"); - config.sendastext = tag->getBool("sendastext", true); + + const std::string defaultmodestr = tag->getString("defaultmode", tag->getBool("sendastext", true) ? "text" : "binary", 1); + if (stdalgo::string::equalsci(defaultmodestr, "reject")) + config.defaultmode = WebSocketConfig::DM_REJECT; + else if (stdalgo::string::equalsci(defaultmodestr, "binary")) + config.defaultmode = WebSocketConfig::DM_BINARY; + else if (stdalgo::string::equalsci(defaultmodestr, "text")) + config.defaultmode = WebSocketConfig::DM_TEXT; + else + throw ModuleException(defaultmodestr + " is an invalid value for <websocket:defaultmode>; acceptable values are 'binary', 'text' and 'reject', at " + tag->source.str()); irc::spacesepstream proxyranges(tag->getString("proxyranges")); for (std::string proxyrange; proxyranges.GetToken(proxyrange); ) |
