diff options
author | George Hazan <george.hazan@gmail.com> | 2023-06-14 18:46:42 +0300 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2023-06-14 18:46:42 +0300 |
commit | adad56d5f50eaaab8b3e9caa1cfc026ccb424d21 (patch) | |
tree | 600383c3dd1dfa2560ea99ae94a07d2efc7b8292 /protocols/Steam | |
parent | 3e0d298dfa998ffc0ea3b6687f8f04fba67c5e04 (diff) |
Steam: websocket: beginning
Diffstat (limited to 'protocols/Steam')
-rw-r--r-- | protocols/Steam/Steam.vcxproj | 1 | ||||
-rw-r--r-- | protocols/Steam/Steam.vcxproj.filters | 3 | ||||
-rw-r--r-- | protocols/Steam/src/http_request.h | 2 | ||||
-rw-r--r-- | protocols/Steam/src/steam_login.cpp | 2 | ||||
-rw-r--r-- | protocols/Steam/src/steam_proto.cpp | 2 | ||||
-rw-r--r-- | protocols/Steam/src/steam_proto.h | 5 | ||||
-rw-r--r-- | protocols/Steam/src/steam_request.cpp | 2 | ||||
-rw-r--r-- | protocols/Steam/src/steam_server.cpp | 138 |
8 files changed, 145 insertions, 10 deletions
diff --git a/protocols/Steam/Steam.vcxproj b/protocols/Steam/Steam.vcxproj index e739a3d50d..f1ae37c2ef 100644 --- a/protocols/Steam/Steam.vcxproj +++ b/protocols/Steam/Steam.vcxproj @@ -63,7 +63,6 @@ <ClInclude Include="src\resource.h" />
<ClInclude Include="src\stdafx.h" />
<ClInclude Include="src\steam_dialogs.h" />
- <ClInclude Include="src\steam_options.h" />
<ClInclude Include="src\steam_proto.h" />
<ClInclude Include="src\version.h" />
<None Include="res\gaming.ico" />
diff --git a/protocols/Steam/Steam.vcxproj.filters b/protocols/Steam/Steam.vcxproj.filters index 92661ea40e..14a7b387ee 100644 --- a/protocols/Steam/Steam.vcxproj.filters +++ b/protocols/Steam/Steam.vcxproj.filters @@ -71,9 +71,6 @@ <ClInclude Include="src\steam_dialogs.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="src\steam_options.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="src\steam_proto.h">
<Filter>Header Files</Filter>
</ClInclude>
diff --git a/protocols/Steam/src/http_request.h b/protocols/Steam/src/http_request.h index 192eedd9ab..4c7b83509d 100644 --- a/protocols/Steam/src/http_request.h +++ b/protocols/Steam/src/http_request.h @@ -1,6 +1,8 @@ #ifndef _HTTP_REQUEST_H_ #define _HTTP_REQUEST_H_ +#define STEAM_USER_AGENT "Valve/Steam HTTP Client 1.0" + class HttpResponse { NETLIBHTTPREQUEST *m_response; diff --git a/protocols/Steam/src/steam_login.cpp b/protocols/Steam/src/steam_login.cpp index 3c077f4dde..e23c33525e 100644 --- a/protocols/Steam/src/steam_login.cpp +++ b/protocols/Steam/src/steam_login.cpp @@ -2,7 +2,7 @@ bool CSteamProto::IsOnline() { - return m_iStatus > ID_STATUS_OFFLINE && m_hServerThread != nullptr; + return m_iStatus > ID_STATUS_OFFLINE && m_hServerConn != nullptr; } bool CSteamProto::IsMe(const char *steamId) diff --git a/protocols/Steam/src/steam_proto.cpp b/protocols/Steam/src/steam_proto.cpp index ce380c54eb..4a6f04321e 100644 --- a/protocols/Steam/src/steam_proto.cpp +++ b/protocols/Steam/src/steam_proto.cpp @@ -290,7 +290,7 @@ int CSteamProto::SetStatus(int new_status) Logout();
}
- else if (m_hServerThread == nullptr && !IsStatusConnecting(m_iStatus)) {
+ else if (m_hServerConn == nullptr && !IsStatusConnecting(m_iStatus)) {
m_iStatus = ID_STATUS_CONNECTING;
ForkThread(&CSteamProto::ServerThread);
diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h index 3df33f9988..d2992cfb8a 100644 --- a/protocols/Steam/src/steam_proto.h +++ b/protocols/Steam/src/steam_proto.h @@ -50,7 +50,7 @@ class CSteamProto : public PROTO<CSteamProto> ptrW m_password;
ptrW m_defaultGroup;
- bool isLoginAgain;
+ bool isLoginAgain, m_bTerminated;
time_t m_idleTS;
HWND m_hwndGuard;
@@ -62,8 +62,9 @@ class CSteamProto : public PROTO<CSteamProto> std::map<HANDLE, time_t> m_mpOutMessages;
// connection
- HANDLE m_hServerThread;
+ HNETLIBCONN m_hServerConn;
void __cdecl ServerThread(void *);
+ bool ServerThreadStub(const char *szHost);
// requests
bool SendRequest(HttpRequest *request);
diff --git a/protocols/Steam/src/steam_request.cpp b/protocols/Steam/src/steam_request.cpp index 9215c873ac..b91283198a 100644 --- a/protocols/Steam/src/steam_request.cpp +++ b/protocols/Steam/src/steam_request.cpp @@ -46,7 +46,7 @@ NETLIBHTTPREQUEST* HttpRequest::Get() {
if (m_szUrl[0]== '/') {
m_szUrl.Insert(0, STEAM_API_URL);
- AddHeader("User-Agent", "Valve/Steam HTTP Client 1.0");
+ AddHeader("User-Agent", STEAM_USER_AGENT);
}
szUrl = m_szUrl.GetBuffer();
return this;
diff --git a/protocols/Steam/src/steam_server.cpp b/protocols/Steam/src/steam_server.cpp index f8c206c0e0..24596894bf 100644 --- a/protocols/Steam/src/steam_server.cpp +++ b/protocols/Steam/src/steam_server.cpp @@ -21,10 +21,146 @@ void __cdecl CSteamProto::ServerThread(void *) { // load web socket servers first if needed int iTimeDiff = db_get_dw(0, STEAM_MODULE, DBKEY_HOSTS_DATE); - if (!db_get_dw(0, STEAM_MODULE, DBKEY_HOSTS_COUNT) || time(0) - iTimeDiff > 3600 * 24 * 7) { // once a week + int iHostCount = db_get_dw(0, STEAM_MODULE, DBKEY_HOSTS_COUNT); + if (!iHostCount || time(0) - iTimeDiff > 3600 * 24 * 7) { // once a week if (!SendRequest(new GetHostsRequest(), &CSteamProto::OnGotHosts)) { LoginFailed(); return; } } + + srand(time(0)); + m_hServerConn = nullptr; + + CMStringA szHost; + do { + szHost.Format("Host%d", rand() % iHostCount); + szHost = db_get_sm(0, STEAM_MODULE, szHost); + szHost.Insert(0, "wss://"); + szHost += "/cmsocket/"; + } + while (ServerThreadStub(szHost)); +} + +bool CSteamProto::ServerThreadStub(const char *szHost) +{ + NLHR_PTR pReply(WebSocket_Connect(m_hNetlibUser, szHost)); + if (pReply == nullptr) { + debugLogA("websocket connection failed"); + return false; + } + + if (pReply->resultCode != 101) { + debugLogA("websocket connection failed: %d", pReply->resultCode); + return false; + } + + m_hServerConn = pReply->nlc; + debugLogA("Websocket connection succeeded"); + + bool bExit = false; + int offset = 0; + MBinBuffer netbuf; + + while (!bExit) { + if (m_bTerminated) + break; + + unsigned char buf[2048]; + int bufSize = Netlib_Recv(m_hServerConn, (char *)buf + offset, _countof(buf) - offset, MSG_NODUMP); + if (bufSize == 0) { + debugLogA("Gateway connection gracefully closed"); + bExit = !m_bTerminated; + break; + } + if (bufSize < 0) { + debugLogA("Gateway connection error, exiting"); + break; + } + + WSHeader hdr; + if (!WebSocket_InitHeader(hdr, buf, bufSize)) { + offset += bufSize; + continue; + } + offset = 0; + + debugLogA("Got packet: buffer = %d, opcode = %d, headerSize = %d, final = %d, masked = %d", bufSize, hdr.opCode, hdr.headerSize, hdr.bIsFinal, hdr.bIsMasked); + + // 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_hServerConn, (char *)buf, _countof(buf), MSG_NODUMP); + if (result == 0) { + debugLogA("Gateway connection gracefully closed"); + bExit = !m_bTerminated; + break; + } + if (result < 0) { + debugLogA("Gateway 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 + CMStringA szJson((char *)netbuf.data() + hdr.headerSize, (int)hdr.payloadSize); + debugLogA("JSON received:\n%s", szJson.c_str()); + JSONNode root = JSONNode::parse(szJson); + // if (root) +// bExit = ProcessMessage(root); + } + break; + + case 8: // close + debugLogA("server required to exit"); + bExit = true; // simply reconnect, don't exit + break; + + case 9: // ping + debugLogA("ping received"); + Netlib_Send(m_hServerConn, (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 (!WebSocket_InitHeader(hdr, netbuf.data(), netbuf.length())) + break; + + // if we have not enough data for data, continue reading + if (hdr.headerSize + hdr.payloadSize > netbuf.length()) + break; + + debugLogA("Got inner packet: buffer = %d, opcode = %d, headerSize = %d, payloadSize = %d, final = %d, masked = %d", netbuf.length(), hdr.opCode, hdr.headerSize, hdr.payloadSize, hdr.bIsFinal, hdr.bIsMasked); + if (prevSize == netbuf.length()) { + netbuf.remove(prevSize); + debugLogA("dropping current packet, exiting"); + break; + } + + prevSize = netbuf.length(); + } + } + + Netlib_CloseHandle(m_hServerConn); + m_hServerConn = nullptr; + return bExit; } |