summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/Steam/src/api/friend_list.h4
-rw-r--r--protocols/Steam/src/steam_login.cpp141
-rw-r--r--protocols/Steam/src/steam_proto.cpp1
-rw-r--r--protocols/Steam/src/steam_proto.h40
-rw-r--r--protocols/Steam/src/steam_server.cpp2
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;
}
}