aboutsummaryrefslogtreecommitdiff
path: root/src/modules/m_websocket.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2021-05-24 16:59:59 +0100
committerGravatar Sadie Powell2021-08-17 22:30:45 +0100
commit1790dacff5966212d12d88a7dc2a169d607a114d (patch)
tree691ca35c13e0f21de3e307cad63f888bd2129aa5 /src/modules/m_websocket.cpp
parentMinor clean up of the previous commit. (diff)
Implement support for websocket subprotocols.
This is based on the current IRCv3 draft but using a vendored protocol.
Diffstat (limited to 'src/modules/m_websocket.cpp')
-rw-r--r--src/modules/m_websocket.cpp25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp
index 264e295f7..672c438e9 100644
--- a/src/modules/m_websocket.cpp
+++ b/src/modules/m_websocket.cpp
@@ -138,6 +138,7 @@ class WebSocketHook : public IOHookMiddle
State state;
time_t lastpingpong;
WebSocketConfig& config;
+ bool sendastext;
static size_t FillHeader(unsigned char* outbuf, size_t sendlength, OpCode opcode)
{
@@ -398,6 +399,22 @@ class WebSocketHook : public IOHookMiddle
}
}
+ std::string selectedproto;
+ HTTPHeaderFinder protocolheader;
+ if (protocolheader.Find(recvq, "Sec-WebSocket-Protocol:", 23, reqend))
+ {
+ irc::spacesepstream protostream(protocolheader.ExtractValue(recvq));
+ for (std::string proto; protostream.GetToken(proto); )
+ {
+ bool is_text = stdalgo::string::equalsci(proto, "text.inspircd.org");
+ if (stdalgo::string::equalsci(proto, "binary.inspircd.org") || is_text)
+ {
+ selectedproto = proto;
+ sendastext = is_text;
+ break;
+ }
+ }
+ }
HTTPHeaderFinder keyheader;
if (!keyheader.Find(recvq, "Sec-WebSocket-Key:", 18, reqend))
@@ -418,7 +435,10 @@ class WebSocketHook : public IOHookMiddle
key.append(MagicGUID);
std::string reply = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ";
- reply.append(BinToBase64((*sha1)->GenerateRaw(key), NULL, '=')).append(newline).append(newline);
+ reply.append(BinToBase64((*sha1)->GenerateRaw(key), NULL, '=')).append(newline);
+ if (!selectedproto.empty())
+ reply.append("Sec-WebSocket-Protocol: ").append(selectedproto).append(newline);
+ reply.append(newline);
GetSendQ().push_back(StreamSocket::SendQueue::Element(reply));
SocketEngine::ChangeEventMask(sock, FD_ADD_TRIAL_WRITE);
@@ -434,6 +454,7 @@ class WebSocketHook : public IOHookMiddle
, state(STATE_HTTPREQ)
, lastpingpong(0)
, config(cfg)
+ , sendastext(cfg.sendastext)
{
sock->AddIOHook(this);
}
@@ -454,7 +475,7 @@ class WebSocketHook : public IOHookMiddle
if (*chr == '\n')
{
// We have found an entire message. Send it in its own frame.
- if (config.sendastext)
+ if (sendastext)
{
// If we send messages as text then we need to ensure they are valid UTF-8.
std::string encoded;