summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorPeter Powell <petpow@saberuk.com>2018-10-31 02:45:05 +0000
committerPeter Powell <petpow@saberuk.com>2018-10-31 05:28:20 +0000
commit99af213a58946185621b3e4de01970a7c21cce93 (patch)
tree687e9b05470696f25bea0e888f8fad43f8b0d52a /src/modules
parentdfe7e7da97d1fb47290814eb4c3728df282e47ec (diff)
WebSocket: use one WebSocket message per IRC message.
This makes more sense for WebSocket clients than CR+LF termination as the protocol already understands the concept of messages.
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/m_websocket.cpp50
1 files changed, 42 insertions, 8 deletions
diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp
index 5ac661ccf..7458e56b6 100644
--- a/src/modules/m_websocket.cpp
+++ b/src/modules/m_websocket.cpp
@@ -242,15 +242,29 @@ class WebSocketHook : public IOHookMiddle
return 0;
unsigned char opcode = (unsigned char)GetRecvQ().c_str()[0];
- opcode &= ~WS_FINBIT;
-
- switch (opcode)
+ switch (opcode & ~WS_FINBIT)
{
case OP_CONTINUATION:
case OP_TEXT:
case OP_BINARY:
{
- return HandleAppData(sock, destrecvq, true);
+ std::string appdata;
+ const int result = HandleAppData(sock, appdata, true);
+ if (result != 1)
+ return result;
+
+ // Strip out any CR+LF which may have been erroneously sent.
+ for (std::string::const_iterator iter = appdata.begin(); iter != appdata.end(); ++iter)
+ {
+ if (*iter != '\r' && *iter != '\n')
+ destrecvq.push_back(*iter);
+ }
+
+ // If we are on the final message of this block append a line terminator.
+ if (opcode & WS_FINBIT)
+ destrecvq.append("\r\n");
+
+ return 1;
}
case OP_PING:
@@ -361,11 +375,31 @@ class WebSocketHook : public IOHookMiddle
if (state != STATE_ESTABLISHED)
return (mysendq.empty() ? 0 : 1);
- if (!uppersendq.empty())
+ std::string message;
+ for (StreamSocket::SendQueue::const_iterator elem = uppersendq.begin(); elem != uppersendq.end(); ++elem)
+ {
+ for (StreamSocket::SendQueue::Element::const_iterator chr = elem->begin(); chr != elem->end(); ++chr)
+ {
+ if (*chr == '\n')
+ {
+ // We have found an entire message. Send it in its own frame.
+ mysendq.push_back(PrepareSendQElem(message.length(), OP_BINARY));
+ mysendq.push_back(message);
+ message.clear();
+ }
+ else if (*chr != '\r')
+ {
+ message.push_back(*chr);
+ }
+ }
+ }
+
+ // Empty the upper send queue and push whatever is left back onto it.
+ uppersendq.clear();
+ if (!message.empty())
{
- StreamSocket::SendQueue::Element elem = PrepareSendQElem(uppersendq.bytes(), OP_BINARY);
- mysendq.push_back(elem);
- mysendq.moveall(uppersendq);
+ uppersendq.push_back(message);
+ return 0;
}
return 1;