summaryrefslogtreecommitdiff
path: root/protocols/Steam
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2023-06-14 18:46:42 +0300
committerGeorge Hazan <george.hazan@gmail.com>2023-06-14 18:46:42 +0300
commitadad56d5f50eaaab8b3e9caa1cfc026ccb424d21 (patch)
tree600383c3dd1dfa2560ea99ae94a07d2efc7b8292 /protocols/Steam
parent3e0d298dfa998ffc0ea3b6687f8f04fba67c5e04 (diff)
Steam: websocket: beginning
Diffstat (limited to 'protocols/Steam')
-rw-r--r--protocols/Steam/Steam.vcxproj1
-rw-r--r--protocols/Steam/Steam.vcxproj.filters3
-rw-r--r--protocols/Steam/src/http_request.h2
-rw-r--r--protocols/Steam/src/steam_login.cpp2
-rw-r--r--protocols/Steam/src/steam_proto.cpp2
-rw-r--r--protocols/Steam/src/steam_proto.h5
-rw-r--r--protocols/Steam/src/steam_request.cpp2
-rw-r--r--protocols/Steam/src/steam_server.cpp138
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;
}