diff options
Diffstat (limited to 'protocols')
| -rw-r--r-- | protocols/Steam/src/api/friend_list.h | 4 | ||||
| -rw-r--r-- | protocols/Steam/src/steam_login.cpp | 141 | ||||
| -rw-r--r-- | protocols/Steam/src/steam_proto.cpp | 1 | ||||
| -rw-r--r-- | protocols/Steam/src/steam_proto.h | 40 | ||||
| -rw-r--r-- | protocols/Steam/src/steam_server.cpp | 2 |
5 files changed, 110 insertions, 78 deletions
diff --git a/protocols/Steam/src/api/friend_list.h b/protocols/Steam/src/api/friend_list.h index 84d8536bcb..857ec9ec0c 100644 --- a/protocols/Steam/src/api/friend_list.h +++ b/protocols/Steam/src/api/friend_list.h @@ -4,10 +4,10 @@ class GetFriendListRequest : public HttpRequest
{
public:
- GetFriendListRequest(const char *token, const char *steamId, const char *relationship) :
+ GetFriendListRequest(const char *token, int64_t steamId, const char *relationship) :
HttpRequest(REQUEST_GET, "/ISteamUserOAuth/GetFriendList/v0001")
{
- this << CHAR_PARAM("access_token", token) << CHAR_PARAM("steamid", steamId) << CHAR_PARAM("relationship", relationship);
+ this << CHAR_PARAM("access_token", token) << INT64_PARAM("steamid", steamId) << CHAR_PARAM("relationship", relationship);
}
};
diff --git a/protocols/Steam/src/steam_login.cpp b/protocols/Steam/src/steam_login.cpp index 7b4af8c2eb..543831e894 100644 --- a/protocols/Steam/src/steam_login.cpp +++ b/protocols/Steam/src/steam_login.cpp @@ -20,22 +20,6 @@ bool CSteamProto::IsMe(const char *steamId) return m_iSteamId == _atoi64(steamId); } -void CSteamProto::Login() -{ - CMsgClientHello hello; - hello.protocol_version = STEAM_PROTOCOL_VERSION; hello.has_protocol_version = true; - WSSend(EMsg::ClientHello, hello); - - ptrA username(getUStringA("Username")); - if (username == NULL) - LoginFailed(); - else { - CAuthenticationGetPasswordRSAPublicKeyRequest request; - request.account_name = username.get(); - WSSendService("Authentication.GetPasswordRSAPublicKey#1", request, &CSteamProto::OnGotRsaKey); - } -} - void CSteamProto::LoginFailed() { m_bTerminated = true; @@ -66,6 +50,32 @@ void CSteamProto::OnGotHosts(const JSONNode &root, void*) db_set_dw(0, STEAM_MODULE, DBKEY_HOSTS_DATE, time(0)); } +///////////////////////////////////////////////////////////////////////////////////////// +// Restore the saved session or establish a new one + +void CSteamProto::Login() +{ + CMsgClientHello hello; + hello.protocol_version = STEAM_PROTOCOL_VERSION; hello.has_protocol_version = true; + WSSend(EMsg::ClientHello, hello); + + ptrA username(getUStringA("Username")); + if (username == NULL) { + LoginFailed(); + return; + } + + m_szAccessToken = getMStringA(DBKEY_ACCESS_TOKEN); + m_szRefreshToken = getMStringA(DBKEY_REFRESH_TOKEN); + if (!m_szAccessToken.IsEmpty() && !m_szRefreshToken.IsEmpty()) + OnLoggedIn(); + else { + CAuthenticationGetPasswordRSAPublicKeyRequest request; + request.account_name = username.get(); + WSSendService("Authentication.GetPasswordRSAPublicKey#1", request, &CSteamProto::OnGotRsaKey); + } +} + void CSteamProto::OnGotRsaKey(const uint8_t *buf, size_t cbLen) { proto::AuthenticationGetPasswordRSAPublicKeyResponse reply(buf, cbLen); @@ -103,7 +113,7 @@ void CSteamProto::OnGotRsaKey(const uint8_t *buf, size_t cbLen) request.device_friendly_name = details.device_friendly_name; request.platform_type = details.platform_type; request.has_platform_type = true; - WSSendService("Authentication.BeginAuthSessionViaCredentials#1", request, &CSteamProto::OnAuthorization); + WSSendService("Authentication.BeginAuthSessionViaCredentials#1", request, &CSteamProto::OnBeginSession); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -129,7 +139,7 @@ INT_PTR CALLBACK CSteamProto::EnterTotpCode(void *param) ENTER_STRING es = {}; es.szModuleName = ppro->m_szModuleName; - es.caption = TranslateT("Enter email confimation code"); + es.caption = TranslateT("Enter the code from your authentication device"); if (EnterString(&es)) { ppro->SendConfirmationCode(false, T2Utf(es.ptszResult)); mir_free(es.ptszResult); @@ -161,7 +171,9 @@ void CSteamProto::SendConfirmationCode(bool isEmail, const char *pszCode) WSSendService("Authentication.UpdateAuthSessionWithSteamGuardCode#1", request, &CSteamProto::OnGotConfirmationCode); } -void CSteamProto::OnAuthorization(const uint8_t *buf, size_t cbLen) +///////////////////////////////////////////////////////////////////////////////////////// + +void CSteamProto::OnBeginSession(const uint8_t *buf, size_t cbLen) { proto::AuthenticationBeginAuthSessionViaCredentialsResponse reply(buf, cbLen); if (reply == nullptr) { @@ -170,11 +182,16 @@ void CSteamProto::OnAuthorization(const uint8_t *buf, size_t cbLen) } // Success + m_bPollCanceled = false; + m_iPollingInterval = (reply->has_interval) ? reply->interval : 5; + if (reply->has_client_id && reply->has_steamid) { DeleteAuthSettings(); SetId(DBKEY_STEAM_ID, m_iSteamId = reply->steamid); SetId(DBKEY_CLIENT_ID, m_iClientId = reply->client_id); - m_requestId.append(reply->request_id.data, reply->request_id.len); + + if (reply->has_request_id) + m_requestId.append(reply->request_id.data, reply->request_id.len); for (int i = 0; i < reply->n_allowed_confirmations; i++) { auto &conf = reply->allowed_confirmations[i]; @@ -206,76 +223,64 @@ void CSteamProto::OnAuthorization(const uint8_t *buf, size_t cbLen) } } +void CSteamProto::CancelLoginAttempt() +{ + m_bPollCanceled = true; + m_impl.m_poll.Stop(); +} + void CSteamProto::SendPollRequest() { + if (m_bPollCanceled) + return; + + m_impl.m_poll.Stop(); + + if (!m_iPollingStartTime) + m_iPollingStartTime = time(0); + + if (time(0) - m_iPollingStartTime >= 30) { + CancelLoginAttempt(); + return; + } + CAuthenticationPollAuthSessionStatusRequest request; request.client_id = GetId(DBKEY_CLIENT_ID); request.has_client_id = true; - request.request_id.data = m_requestId.data(); request.request_id.len = m_requestId.length(); + request.request_id.data = m_requestId.data(); request.request_id.len = m_requestId.length(); request.has_request_id = true; WSSendService("Authentication.PollAuthSessionStatus#1", request, &CSteamProto::OnPollSession); } void CSteamProto::OnPollSession(const uint8_t *buf, size_t cbLen) { proto::AuthenticationPollAuthSessionStatusResponse reply(buf, cbLen); - if (reply == nullptr || !reply->access_token || !reply->refresh_token) { + if (reply == nullptr) { LoginFailed(); return; } - m_szAccessToken = reply->access_token; - m_szRefreshToken = reply->refresh_token; + if (reply->has_new_client_id) + m_iClientId = reply->new_client_id; - ptrA szAccountName(getUStringA(DBKEY_ACCOUNT_NAME)); - - MBinBuffer machineId(getBlob(DBKEY_MACHINE_ID)); - if (!machineId.length()) { - uint8_t random[100], hashOut[20]; - Utils_GetRandom(random, sizeof(random)); - mir_sha1_hash(random, sizeof(random), hashOut); - - db_set_blob(0, m_szModuleName, DBKEY_MACHINE_ID, hashOut, sizeof(hashOut)); - machineId.append(hashOut, sizeof(hashOut)); + if (!reply->refresh_token) { + if (!m_bPollCanceled) + m_impl.m_poll.Start(m_iPollingInterval * 1000); + return; } - CMsgIPAddress privateIp; - privateIp.ip_case = CMSG_IPADDRESS__IP_V4; - privateIp.v4 = 0; - - CMsgClientLogon request; - request.access_token = reply->access_token; - request.account_name = szAccountName.get(); - request.client_language = "english"; - request.client_os_type = 16; request.has_client_os_type = true; - request.should_remember_password = false; request.has_should_remember_password = true; - request.obfuscated_private_ip = &privateIp; - request.protocol_version = STEAM_PROTOCOL_VERSION; request.has_protocol_version = true; - request.supports_rate_limit_response = request.has_supports_rate_limit_response = true; - request.machine_name = ""; - request.steamguard_dont_remember_computer = false; request.has_steamguard_dont_remember_computer = true; - request.chat_mode = 2; request.has_chat_mode = true; - request.cell_id = 7; request.has_cell_id = true; - request.machine_id.data = machineId.data(); - request.machine_id.len = machineId.length(); - WSSend(EMsg::ClientLogon, request); -} + // stop polling + CancelLoginAttempt(); -void CSteamProto::OnLoggedOn(const uint8_t *buf, size_t cbLen) -{ - proto::MsgClientLogonResponse reply(buf, cbLen); - if (reply == nullptr || !reply->has_eresult) { - LoginFailed(); - return; - } + setString(DBKEY_ACCESS_TOKEN, reply->access_token); + setString(DBKEY_REFRESH_TOKEN, reply->refresh_token); - if (reply->eresult != 1) { - debugLogA("Login failed with error %d", reply->eresult); - LoginFailed(); - return; - } + OnLoggedIn(); +} +void CSteamProto::OnLoggedIn() +{ // go to online now ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus = m_iDesiredStatus); // load contact list - // SendRequest(new GetFriendListRequest(token, steamId, "friend,ignoredfriend,requestrecipient"), &CSteamProto::OnGotFriendList); + SendRequest(new GetFriendListRequest(m_szAccessToken, m_iSteamId, "friend,ignoredfriend,requestrecipient"), &CSteamProto::OnGotFriendList); } diff --git a/protocols/Steam/src/steam_proto.cpp b/protocols/Steam/src/steam_proto.cpp index ce77ce38d7..c6c0e3ddf9 100644 --- a/protocols/Steam/src/steam_proto.cpp +++ b/protocols/Steam/src/steam_proto.cpp @@ -9,6 +9,7 @@ static int CompareRequests(const ProtoRequest *p1, const ProtoRequest *p2) CSteamProto::CSteamProto(const char *protoName, const wchar_t *userName) :
PROTO<CSteamProto>(protoName, userName),
+ m_impl(*this),
m_arRequests(10, CompareRequests),
m_wszGroupName(this, "DefaultGroup", L"Steam"),
m_wszDeviceName(this, "DeviceName", L"Miranda NG")
diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h index b32ee0953b..e49361e92c 100644 --- a/protocols/Steam/src/steam_proto.h +++ b/protocols/Steam/src/steam_proto.h @@ -12,10 +12,12 @@ #define DBKEY_HOSTS_COUNT "HostsCount"
#define DBKEY_HOSTS_DATE "HostsDate"
-#define DBKEY_CLIENT_ID "ClientID"
-#define DBKEY_STEAM_ID "SteamID"
-#define DBKEY_ACCOUNT_NAME "Username"
-#define DBKEY_MACHINE_ID "MachineId"
+#define DBKEY_CLIENT_ID "ClientID"
+#define DBKEY_STEAM_ID "SteamID"
+#define DBKEY_ACCOUNT_NAME "Username"
+#define DBKEY_MACHINE_ID "MachineId"
+#define DBKEY_ACCESS_TOKEN "AccessToken"
+#define DBKEY_REFRESH_TOKEN "RefreshToken"
struct SendAuthParam
{
@@ -68,8 +70,28 @@ class CSteamProto : public PROTO<CSteamProto> friend class PollRequest;
friend class WebSocket<CSteamProto>;
+ class CProtoImpl
+ {
+ friend class CSteamProto;
+ CSteamProto &m_proto;
+
+ CTimer m_poll;
+ void OnPoll(CTimer *)
+ {
+ m_proto.SendPollRequest();
+ }
+
+ CProtoImpl(CSteamProto &pro) :
+ m_proto(pro),
+ m_poll(Miranda_GetSystemWindow(), UINT_PTR(this))
+ {
+ m_poll.OnEvent = Callback(this, &CProtoImpl::OnPoll);
+ }
+ }
+ m_impl;
+
ptrW m_password;
- bool m_bTerminated;
+ bool m_bTerminated, m_bPollCanceled;
time_t m_idleTS;
int64_t m_iSteamId, m_iClientId;
MBinBuffer m_requestId;
@@ -84,6 +106,8 @@ class CSteamProto : public PROTO<CSteamProto> CMStringA m_szRefreshToken, m_szAccessToken;
ULONG hAuthProcess = 1;
ULONG hMessageProcess = 1;
+ int m_iPollingInterval;
+ time_t m_iPollingStartTime;
mir_cs m_addContactLock;
mir_cs m_setStatusLock;
std::map<HANDLE, time_t> m_mpOutMessages;
@@ -117,17 +141,19 @@ class CSteamProto : public PROTO<CSteamProto> void LoginFailed();
void Logout();
+ void OnLoggedIn();
+
static INT_PTR CALLBACK EnterTotpCode(void *param);
static INT_PTR CALLBACK EnterEmailCode(void *param);
- void OnAuthorization(const uint8_t *buf, size_t cbLen);
+ void OnBeginSession(const uint8_t *buf, size_t cbLen);
void OnGotRsaKey(const uint8_t *buf, size_t cbLen);
void OnGotConfirmationCode(const uint8_t *buf, size_t cbLen);
- void OnLoggedOn(const uint8_t *buf, size_t cbLen);
void OnPollSession(const uint8_t *buf, size_t cbLen);
void OnGotHosts(const JSONNode &root, void *);
+ void CancelLoginAttempt();
void DeleteAuthSettings();
void SendConfirmationCode(bool, const char *pszCode);
void SendPollRequest();
diff --git a/protocols/Steam/src/steam_server.cpp b/protocols/Steam/src/steam_server.cpp index b632695e7e..25ba12f7b6 100644 --- a/protocols/Steam/src/steam_server.cpp +++ b/protocols/Steam/src/steam_server.cpp @@ -164,7 +164,7 @@ void CSteamProto::ProcessMessage(const uint8_t *buf, size_t cbLen) // persistent callbacks switch (msgType) { case EMsg::ClientLogOnResponse: - OnLoggedOn(buf, cbLen); + OnLoggedIn(); break; } } |
