diff options
author | George Hazan <george.hazan@gmail.com> | 2024-06-13 16:39:12 +0300 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2024-06-13 16:39:12 +0300 |
commit | 004f3d1f49c54bc62743a838161ac157ffc37e41 (patch) | |
tree | 722b78c8e8f32c16cf9959068d86f7bf775e41cf /src | |
parent | 778558984c08b787d0e73d692086b6935e56a156 (diff) |
websocket internal code went to MWebSocket
Diffstat (limited to 'src')
-rw-r--r-- | src/mir_app/src/mir_app.def | 16 | ||||
-rw-r--r-- | src/mir_app/src/mir_app64.def | 16 | ||||
-rw-r--r-- | src/mir_app/src/netlib_websocket.cpp | 242 |
3 files changed, 217 insertions, 57 deletions
diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def index db2c589d2f..9486812235 100644 --- a/src/mir_app/src/mir_app.def +++ b/src/mir_app/src/mir_app.def @@ -676,8 +676,8 @@ UnregisterHppLogger @786 ?RegisterSrmmLog@@YGPAXPAUCMPlugin@@PBDPB_WP6APAVCSrmmLogWindow@@AAVCMsgDialog@@@Z@Z @805 NONAME
?UnregisterSrmmLog@@YGXPAX@Z @806 NONAME
?GetType@CRtfLogWindow@@UAEHXZ @807 NONAME
-_WebSocket_InitHeader@12 @809 NONAME
-_WebSocket_Connect@12 @810 NONAME
+?run@MWebSocket@@QAEXXZ @809 NONAME
+?connect@MWebSocket@@QAEPAUMHttpResponse@@PAXPBDPBUMHttpHeaders@@@Z @810 NONAME
?log@CSrmmBaseDialog@@QBEPAVCSrmmLogWindow@@XZ @811 NONAME
Netlib_Dump @812 NONAME
?ProtoBroadcastAsync@PROTO_INTERFACE@@QAEXIHHPAXJ@Z @813 NONAME
@@ -736,8 +736,8 @@ _Netlib_GetTlsUnique@12 @831 NONAME ?IsPluginOnWhiteList@@YG_NPBD@Z @866 NONAME
?SetPluginOnWhiteList@@YGXPBD_N@Z @867 NONAME
Chat_Mute @868
-_WebSocket_SendBinary@12 @869 NONAME
-_WebSocket_SendText@8 @870 NONAME
+?sendBinary@MWebSocket@@QAEXPBXI@Z @869 NONAME
+?sendText@MWebSocket@@QAEXPBD@Z @870 NONAME
?OnContactAdded@PROTO_INTERFACE@@UAEXI@Z @871 NONAME
_Netlib_SslConnect@12 @872 NONAME
_Netlib_SslFree@4 @873 NONAME
@@ -977,3 +977,11 @@ g_hevEventSetJson @1109 NONAME ?addReaction@EventInfo@DB@@QAEXPBD@Z @1113 NONAME
?delReaction@EventInfo@DB@@QAEXPBD@Z @1114 NONAME
?getText@EventInfo@DB@@QBEPA_WXZ @1115 NONAME
+??0MWebSocket@@QAE@XZ @1116 NONAME
+??1MWebSocket@@QAE@XZ @1117 NONAME
+??_7MWebSocket@@6B@ @1118 NONAME
+?terminate@MWebSocket@@QAEXXZ @1119 NONAME
+??0MJsonWebSocket@@QAE@XZ @1120 NONAME
+??1MJsonWebSocket@@QAE@XZ @1121 NONAME
+??_7MJsonWebSocket@@6B@ @1122 NONAME
+?process@MJsonWebSocket@@EAEXPBEI@Z @1123 NONAME
diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def index f4c00a0a66..a1a44174a0 100644 --- a/src/mir_app/src/mir_app64.def +++ b/src/mir_app/src/mir_app64.def @@ -676,8 +676,8 @@ UnregisterHppLogger @786 ?RegisterSrmmLog@@YAPEAXPEAUCMPlugin@@PEBDPEB_WP6APEAVCSrmmLogWindow@@AEAVCMsgDialog@@@Z@Z @805 NONAME
?UnregisterSrmmLog@@YAXPEAX@Z @806 NONAME
?GetType@CRtfLogWindow@@UEAAHXZ @807 NONAME
-WebSocket_InitHeader @809 NONAME
-WebSocket_Connect @810 NONAME
+?run@MWebSocket@@QEAAXXZ @809 NONAME
+?connect@MWebSocket@@QEAAPEAUMHttpResponse@@PEAXPEBDPEBUMHttpHeaders@@@Z @810 NONAME
?log@CSrmmBaseDialog@@QEBAPEAVCSrmmLogWindow@@XZ @811 NONAME
Netlib_Dump @812 NONAME
?ProtoBroadcastAsync@PROTO_INTERFACE@@QEAAXIHHPEAX_J@Z @813 NONAME
@@ -736,8 +736,8 @@ Netlib_GetTlsUnique @831 NONAME ?IsPluginOnWhiteList@@YA_NPEBD@Z @866 NONAME
?SetPluginOnWhiteList@@YAXPEBD_N@Z @867 NONAME
Chat_Mute @868
-WebSocket_SendBinary @869 NONAME
-WebSocket_SendText @870 NONAME
+?sendBinary@MWebSocket@@QEAAXPEBX_K@Z @869 NONAME
+?sendText@MWebSocket@@QEAAXPEBD@Z @870 NONAME
?OnContactAdded@PROTO_INTERFACE@@UEAAXI@Z @871 NONAME
Netlib_SslConnect @872 NONAME
Netlib_SslFree @873 NONAME
@@ -977,3 +977,11 @@ g_hevEventSetJson @1103 NONAME ?addReaction@EventInfo@DB@@QEAAXPEBD@Z @1107 NONAME
?delReaction@EventInfo@DB@@QEAAXPEBD@Z @1108 NONAME
?getText@EventInfo@DB@@QEBAPEA_WXZ @1109 NONAME
+??0MWebSocket@@QEAA@XZ @1110 NONAME
+??1MWebSocket@@QEAA@XZ @1111 NONAME
+??_7MWebSocket@@6B@ @1112 NONAME
+?terminate@MWebSocket@@QEAAXXZ @1113 NONAME
+??0MJsonWebSocket@@QEAA@XZ @1114 NONAME
+??1MJsonWebSocket@@QEAA@XZ @1115 NONAME
+??_7MJsonWebSocket@@6B@ @1116 NONAME
+?process@MJsonWebSocket@@EEAAXPEBE_K@Z @1117 NONAME
diff --git a/src/mir_app/src/netlib_websocket.cpp b/src/mir_app/src/netlib_websocket.cpp index 9ce6f72be9..b92d3c168f 100644 --- a/src/mir_app/src/netlib_websocket.cpp +++ b/src/mir_app/src/netlib_websocket.cpp @@ -27,8 +27,73 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../../libs/zlib/src/zlib.h"
-MIR_APP_DLL(MHttpResponse*) WebSocket_Connect(HNETLIBUSER nlu, const char *szHost, const MHttpHeaders *pHeaders)
+struct WSHeader
{
+ WSHeader()
+ {
+ memset(this, 0, sizeof(*this));
+ }
+
+ bool bIsFinal, bIsMasked;
+ int opCode, firstByte;
+ size_t payloadSize, headerSize;
+
+ bool init(const void *pData, size_t bufSize)
+ {
+ if (bufSize < 2)
+ return false;
+
+ auto *buf = (const uint8_t *)pData;
+ bIsFinal = (buf[0] & 0x80) != 0;
+ bIsMasked = (buf[1] & 0x80) != 0;
+ opCode = buf[0] & 0x0F;
+ firstByte = buf[1] & 0x7F;
+ headerSize = 2 + (firstByte == 0x7E ? 2 : 0) + (firstByte == 0x7F ? 8 : 0) + (bIsMasked ? 4 : 0);
+ if (bufSize < headerSize)
+ return false;
+
+ uint64_t tmpSize = 0;
+ switch (firstByte) {
+ case 0x7F:
+ tmpSize += ((uint64_t)buf[2]) << 56;
+ tmpSize += ((uint64_t)buf[3]) << 48;
+ tmpSize += ((uint64_t)buf[4]) << 40;
+ tmpSize += ((uint64_t)buf[5]) << 32;
+ tmpSize += ((uint64_t)buf[6]) << 24;
+ tmpSize += ((uint64_t)buf[7]) << 16;
+ tmpSize += ((uint64_t)buf[8]) << 8;
+ tmpSize += ((uint64_t)buf[9]);
+ break;
+
+ case 0x7E:
+ tmpSize += ((uint64_t)buf[2]) << 8;
+ tmpSize += ((uint64_t)buf[3]);
+ break;
+
+ default:
+ tmpSize = firstByte;
+ }
+ payloadSize = tmpSize;
+ return true;
+ }
+};
+
+MWebSocket::MWebSocket()
+{
+}
+
+MWebSocket::~MWebSocket()
+{
+ if (m_hConn)
+ Netlib_CloseHandle(m_hConn);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+MHttpResponse* MWebSocket::connect(HANDLE nlu, const char *szHost, const MHttpHeaders *pHeaders)
+{
+ m_nlu = (HNETLIBUSER)nlu;
+
CMStringA tmpHost(szHost);
// connect to the gateway server
@@ -54,57 +119,19 @@ MIR_APP_DLL(MHttpResponse*) WebSocket_Connect(HNETLIBUSER nlu, const char *szHos for (auto &it: *pHeaders)
nlhr.AddHeader(it->szName, it->szValue);
- auto *pReply = Netlib_HttpTransaction(nlu, &nlhr);
+ auto *pReply = Netlib_HttpTransaction(m_nlu, &nlhr);
if (pReply == nullptr) {
- Netlib_Logf(nlu, "Error establishing WebSocket connection to %s, send failed", tmpHost.c_str());
+ Netlib_Logf(m_nlu, "Error establishing WebSocket connection to %s, send failed", tmpHost.c_str());
return nullptr;
}
+ m_hConn = pReply->nlc;
if (pReply->resultCode != 101)
- Netlib_Logf(nlu, "Error establishing WebSocket connection to %s, status %d", tmpHost.c_str(), pReply->resultCode);
+ Netlib_Logf(m_nlu, "Error establishing WebSocket connection to %s, status %d", tmpHost.c_str(), pReply->resultCode);
return pReply;
}
-MIR_APP_DLL(bool) WebSocket_InitHeader(WSHeader &hdr, const void *pData, size_t bufSize)
-{
- if (bufSize < 2)
- return false;
-
- auto *buf = (const uint8_t *)pData;
- hdr.bIsFinal = (buf[0] & 0x80) != 0;
- hdr.bIsMasked = (buf[1] & 0x80) != 0;
- hdr.opCode = buf[0] & 0x0F;
- hdr.firstByte = buf[1] & 0x7F;
- hdr.headerSize = 2 + (hdr.firstByte == 0x7E ? 2 : 0) + (hdr.firstByte == 0x7F ? 8 : 0) + (hdr.bIsMasked ? 4 : 0);
- if (bufSize < hdr.headerSize)
- return false;
-
- uint64_t tmpSize = 0;
- switch (hdr.firstByte) {
- case 0x7F:
- tmpSize += ((uint64_t)buf[2]) << 56;
- tmpSize += ((uint64_t)buf[3]) << 48;
- tmpSize += ((uint64_t)buf[4]) << 40;
- tmpSize += ((uint64_t)buf[5]) << 32;
- tmpSize += ((uint64_t)buf[6]) << 24;
- tmpSize += ((uint64_t)buf[7]) << 16;
- tmpSize += ((uint64_t)buf[8]) << 8;
- tmpSize += ((uint64_t)buf[9]);
- break;
-
- case 0x7E:
- tmpSize += ((uint64_t)buf[2]) << 8;
- tmpSize += ((uint64_t)buf[3]);
- break;
-
- default:
- tmpSize = hdr.firstByte;
- }
- hdr.payloadSize = tmpSize;
- return true;
-}
-
/////////////////////////////////////////////////////////////////////////////////////////
static void WebSocket_Send(HNETLIBCONN nlc, const void *pData, int64_t dataLen, uint8_t opCode)
@@ -156,14 +183,131 @@ static void WebSocket_Send(HNETLIBCONN nlc, const void *pData, int64_t dataLen, Netlib_Send(nlc, sendBuf, int(dataLen + cbLen), MSG_NODUMP);
}
-MIR_APP_DLL(void) WebSocket_SendText(HNETLIBCONN nlc, const char *pData)
+void MWebSocket::sendText(const char *pData)
+{
+ if (m_hConn && pData) {
+ mir_cslock lck(m_cs);
+ WebSocket_Send(m_hConn, pData, strlen(pData), 1);
+ }
+}
+
+void MWebSocket::sendBinary(const void *pData, size_t dataLen)
{
- if (nlc && pData)
- WebSocket_Send(nlc, pData, strlen(pData), 1);
+ if (m_hConn && pData) {
+ mir_cslock lck(m_cs);
+ WebSocket_Send(m_hConn, pData, dataLen, 2);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void MWebSocket::terminate()
+{
+ m_bTerminated = true;
+
+ if (m_hConn)
+ Netlib_Shutdown(m_hConn);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void MWebSocket::run()
+{
+ int offset = 0;
+ MBinBuffer netbuf;
+
+ while (!m_bTerminated) {
+ unsigned char buf[2048];
+ int bufSize = Netlib_Recv(m_hConn, (char *)buf + offset, _countof(buf) - offset, MSG_NODUMP);
+ if (bufSize == 0) {
+ Netlib_Log(m_nlu, "Websocket connection gracefully closed");
+ break;
+ }
+ if (bufSize < 0) {
+ Netlib_Log(m_nlu, "Websocket connection error, exiting");
+ break;
+ }
+
+ WSHeader hdr;
+ if (!hdr.init(buf, bufSize)) {
+ offset += bufSize;
+ continue;
+ }
+ offset = 0;
+
+ // we have some additional data, not only opcode
+ if ((size_t)bufSize > hdr.headerSize) {
+ size_t currPacketSize = bufSize - hdr.headerSize;
+ netbuf.append(buf, bufSize);
+ while (currPacketSize < hdr.payloadSize) {
+ int result = Netlib_Recv(m_hConn, (char *)buf, _countof(buf), MSG_NODUMP);
+ if (result == 0) {
+ Netlib_Log(m_nlu, "Websocket connection gracefully closed");
+ break;
+ }
+ if (result < 0) {
+ Netlib_Log(m_nlu, "Websocket connection error, exiting");
+ break;
+ }
+ currPacketSize += result;
+ netbuf.append(buf, result);
+ }
+ }
+
+ // read all payloads from the current buffer, one by one
+ size_t prevSize = 0;
+ while (true) {
+ switch (hdr.opCode) {
+ case 0: // text packet
+ case 1: // binary packet
+ case 2: // continuation
+ if (hdr.bIsFinal) {
+ // process a packet here
+ process((uint8_t*)netbuf.data() + hdr.headerSize, (int)hdr.payloadSize);
+ }
+ break;
+
+ case 8: // close
+ Netlib_Log(m_nlu, "server required to exit");
+ m_bTerminated = true; // simply reconnect, don't exit
+ break;
+
+ case 9: // ping
+ Netlib_Log(m_nlu, "ping received");
+ Netlib_Send(m_hConn, (char *)buf + hdr.headerSize, bufSize - int(hdr.headerSize), 0);
+ break;
+ }
+
+ if (hdr.bIsFinal)
+ netbuf.remove(hdr.headerSize + hdr.payloadSize);
+
+ if (netbuf.length() == 0)
+ break;
+
+ // if we have not enough data for header, continue reading
+ if (!hdr.init(netbuf.data(), netbuf.length()))
+ break;
+
+ // if we have not enough data for data, continue reading
+ if (hdr.headerSize + hdr.payloadSize > netbuf.length())
+ break;
+
+ if (prevSize == netbuf.length()) {
+ netbuf.remove(prevSize);
+ break;
+ }
+
+ prevSize = netbuf.length();
+ }
+ }
}
-MIR_APP_DLL(void) WebSocket_SendBinary(HNETLIBCONN nlc, const void *pData, size_t dataLen)
+void MJsonWebSocket::process(const uint8_t *buf, size_t cbLen)
{
- if (nlc && pData)
- WebSocket_Send(nlc, pData, dataLen, 2);
+ CMStringA szJson((char*)buf, (int)cbLen);
+ Netlib_Logf(m_nlu, "JSON received:\n%s", szJson.c_str());
+
+ JSONNode root = JSONNode::parse(szJson);
+ if (root)
+ process(root);
}
|