aboutsummaryrefslogtreecommitdiff
path: root/src/modules/m_websocket.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2022-08-04 17:32:12 +0100
committerGravatar Sadie Powell2022-08-04 18:13:01 +0100
commit88b882fcd2ce2dc440a42811f42d024bfa639118 (patch)
tree07a7d41f6d11505c2e1613eb50adb5e2553b804c /src/modules/m_websocket.cpp
parentWebSockets are a HTTP feature not a HTML5 feature. (diff)
Expose WebSocket error messages to clients.
Diffstat (limited to 'src/modules/m_websocket.cpp')
-rw-r--r--src/modules/m_websocket.cpp33
1 files changed, 27 insertions, 6 deletions
diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp
index 792f8569e..9c4608259 100644
--- a/src/modules/m_websocket.cpp
+++ b/src/modules/m_websocket.cpp
@@ -120,6 +120,13 @@ class WebSocketHook : public IOHookMiddle
}
};
+ enum CloseCode
+ {
+ CLOSE_PROTOCOL_ERROR = 1002,
+ CLOSE_POLICY_VIOLATION = 1008,
+ CLOSE_TOO_LARGE = 1009,
+ };
+
enum OpCode
{
OP_CONTINUATION = 0x00,
@@ -197,7 +204,7 @@ class WebSocketHook : public IOHookMiddle
unsigned char len1 = (unsigned char)cmyrecvq[1];
if (!(len1 & WS_MASKBIT))
{
- sock->SetError("WebSocket protocol violation: unmasked client frame");
+ CloseConnection(sock, CLOSE_PROTOCOL_ERROR, "WebSocket protocol violation: unmasked client frame");
return -1;
}
@@ -213,7 +220,7 @@ class WebSocketHook : public IOHookMiddle
// allowlarge is false for control frames according to the RFC meaning large pings, etc. are not allowed
if (!allowlarge)
{
- sock->SetError("WebSocket protocol violation: large control frame");
+ CloseConnection(sock, CLOSE_PROTOCOL_ERROR, "WebSocket protocol violation: large control frame");
return -1;
}
@@ -228,7 +235,7 @@ class WebSocketHook : public IOHookMiddle
if (len <= WS_MAX_PAYLOAD_LENGTH_SMALL)
{
- sock->SetError("WebSocket protocol violation: non-minimal length encoding used");
+ CloseConnection(sock, CLOSE_PROTOCOL_ERROR, "WebSocket protocol violation: non-minimal length encoding used");
return -1;
}
@@ -237,7 +244,7 @@ class WebSocketHook : public IOHookMiddle
}
else if (len1 == WS_PAYLOAD_LENGTH_MAGIC_HUGE)
{
- sock->SetError("WebSocket: Huge frames are not supported");
+ CloseConnection(sock, CLOSE_TOO_LARGE, "WebSocket: Huge frames are not supported");
return -1;
}
@@ -261,7 +268,7 @@ class WebSocketHook : public IOHookMiddle
{
if (lastpingpong + MINPINGPONGDELAY >= ServerInstance->Time())
{
- sock->SetError("WebSocket: Ping/pong flood");
+ CloseConnection(sock, CLOSE_POLICY_VIOLATION, "WebSocket: Ping/pong flood");
return -1;
}
@@ -332,12 +339,26 @@ class WebSocketHook : public IOHookMiddle
default:
{
- sock->SetError("WebSocket: Invalid opcode");
+ CloseConnection(sock, CLOSE_PROTOCOL_ERROR, "WebSocket: Invalid opcode");
return -1;
}
}
}
+ void CloseConnection(StreamSocket* sock, CloseCode closecode, const std::string& reason)
+ {
+ uint16_t netcode = htons(closecode);
+ std::string packedcode;
+ packedcode.push_back(netcode & 0x00FF);
+ packedcode.push_back(netcode >> 8);
+
+ GetSendQ().push_back(PrepareSendQElem(reason.length() + 2, OP_CLOSE));
+ GetSendQ().push_back(packedcode);
+ GetSendQ().push_back(reason);
+ sock->DoWrite();
+ sock->SetError(reason);
+ }
+
void FailHandshake(StreamSocket* sock, const char* httpreply, const char* sockerror)
{
GetSendQ().push_back(StreamSocket::SendQueue::Element(httpreply));