#include "common.h" void CSteamProto::InitQueue() { InitializeCriticalSection(&requests_queue_lock); m_evRequestsQueue = CreateEvent(NULL, FALSE, FALSE, NULL); } void CSteamProto::UninitQueue() { requestsQueue.destroy(); CloseHandle(m_evRequestsQueue); DeleteCriticalSection(&requests_queue_lock); } void CSteamProto::StartQueue() { isTerminated = false; if (m_hQueueThread == NULL) { ptrA token(getStringA("TokenSecret")); if (token && token[0] != '\0') { PushRequest( new SteamWebApi::LogonRequest(token), &CSteamProto::OnLoggedOn); } else { ptrA username(mir_urlEncode(ptrA(mir_utf8encodeT(getTStringA("Username"))))); if (username == NULL || username[0] == '\0') return; PushRequest( new SteamWebApi::RsaKeyRequest(username), &CSteamProto::OnGotRsaKey); } m_hQueueThread = ForkThreadEx(&CSteamProto::QueueThread, 0, NULL); } } void CSteamProto::StopQueue() { isTerminated = true; { mir_cslock lock(requests_queue_lock); while (requestsQueue.getCount() > 0) { QueueItem *item = requestsQueue[0]; requestsQueue.remove(0); // QueueItem's destructor properly free request and arg delete item; } } // logoff ptrA token(getStringA("TokenSecret")); ptrA umqid(getStringA("UMQID")); SteamWebApi::HttpRequest *request = new SteamWebApi::LogoffRequest(token, umqid); NETLIBHTTPREQUEST *response = request->Send(m_hNetlibUser); CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)response); delete request; m_hQueueThread = NULL; } void CSteamProto::PushRequest(SteamWebApi::HttpRequest *request) { PushRequest(request, NULL, NULL, ARG_NO_FREE); } void CSteamProto::PushRequest(SteamWebApi::HttpRequest *request, RESPONSE response) { PushRequest(request, response, NULL, ARG_NO_FREE); } void CSteamProto::PushRequest(SteamWebApi::HttpRequest *request, RESPONSE response, void *arg, ARG_FREE_TYPE arg_free_type) { // Always prepare QueueItem so we can use it's destructor to free request and arg QueueItem *item = new QueueItem(request, response); item->arg = arg; item->arg_free_type = arg_free_type; if (isTerminated) { // QueueItem's destructor properly free request and arg delete item; return; } { mir_cslock lock(requests_queue_lock); requestsQueue.insert(item); } SetEvent(m_evRequestsQueue); } void CSteamProto::ExecuteRequest(QueueItem *item) { if (isTerminated) { // QueueItem's destructor properly free request and arg delete item; return; } NETLIBHTTPREQUEST *response = item->request->Send(m_hNetlibUser); if (item->responseCallback != NULL) (this->*(item->responseCallback))(response, item->arg); // todo: add succeed and failed handlers if need if (response != NULL/* && response->resultCode != 200*/) { CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)response); } /*else if (requestItem->responseFailedCallback != NULL) { (this->*(requestItem->responseFailedCallback))(response); }*/ delete item; } void CSteamProto::QueueThread(void*) { debugLog(_T("CSteamProto::QueueThread: entering")); while (!isTerminated) { WaitForSingleObject(m_evRequestsQueue, 1000); while (true) { QueueItem *item = NULL; { mir_cslock lock(requests_queue_lock); if (requestsQueue.getCount() == 0) break; item = requestsQueue[0]; requestsQueue.remove(0); } if (item != NULL) ExecuteRequest(item); } } debugLog(_T("CSteamProto::QueueThread: leaving")); }