Skip to content

Commit

Permalink
Added timeout when waiting for ClientLogOnResponse
Browse files Browse the repository at this point in the history
  • Loading branch information
DoctorMcKay committed May 6, 2020
1 parent 905b648 commit e9bbe6f
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 11 deletions.
7 changes: 5 additions & 2 deletions components/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ const SteamCrypto = require('@doctormckay/steam-crypto');
const SteamUser = require('../index.js');

SteamUser.prototype._handleConnectionClose = function() {
clearTimeout(this._logonMsgTimeout);
delete this._logonMsgTimeout;

if (!this.steamID) {
// connection closed while connecting; reconnect
clearInterval(this._heartbeatInterval);
this._doConnection();
} else {
// connection closed while we were connected; fire logoff
this._handleLogOff(SteamUser.EResult.NoConnection, "NoConnection");
this._handleLogOff(SteamUser.EResult.NoConnection, 'NoConnection');
}
};

Expand Down Expand Up @@ -57,5 +60,5 @@ SteamUser.prototype._handlerManager.add(SteamUser.EMsg.ChannelEncryptResult, fun
delete this._connection._tempSessionKey;

this.emit('Encryption success; now logging on');
this._send(this._logOnDetails.game_server_token ? SteamUser.EMsg.ClientLogonGameServer : SteamUser.EMsg.ClientLogon, this._logOnDetails);
this._sendLogOn();
});
2 changes: 1 addition & 1 deletion components/connection_protocols/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ WebSocketConnection.prototype._chooseAndConnect = function() {
this.stream.on('connected', () => {
this.user.emit('debug', 'WebSocket connection success; now logging in');
this.stream.setTimeout(0); // Disable timeout
this.user._send(this.user._logOnDetails.game_server_token ? SteamUser.EMsg.ClientLogonGameServer : SteamUser.EMsg.ClientLogon, this.user._logOnDetails);
this.user._sendLogOn();
});

this.stream.on('timeout', () => {
Expand Down
42 changes: 34 additions & 8 deletions components/logon.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,35 @@ SteamUser.prototype._doConnection = function() {
}
};

/**
* Send the actual ClientLogOn message.
* @private
*/
SteamUser.prototype._sendLogOn = function() {
// Realistically, this should never need to elapse since at this point we have already established a successful connection
// with the CM. But sometimes, Steam appears to never respond to the logon message. Valve.
this._logonMsgTimeout = setTimeout(() => {
this.emit('debug', 'Logon message timeout elapsed. Attempting relog.');
this._disconnect(true);
this._enqueueLogonAttempt();
}, 5000);

this._send(this._logOnDetails.game_server_token ? SteamUser.EMsg.ClientLogonGameServer : SteamUser.EMsg.ClientLogon, this._logOnDetails);
};

/**
* Enqueue another logon attempt.
* Used after we get ServiceUnavailable, TryAnotherCM, or a timeout waiting for ClientLogOnResponse.
* @private
*/
SteamUser.prototype._enqueueLogonAttempt = function() {
let timer = this._logonTimeoutDuration || 1000;
this._logonTimeoutDuration = Math.min(timer * 2, 60000); // exponential backoff, max 1 minute
this._logonTimeout = setTimeout(() => {
this.logOn(true);
}, timer);
};

/**
* Log off of Steam gracefully.
*/
Expand All @@ -262,6 +291,7 @@ SteamUser.prototype.logOff = function() {
SteamUser.prototype._disconnect = function(suppressLogoff) {
this._clearChangelistUpdateTimer();
clearTimeout(this._logonTimeout); // cancel any queued reconnect attempt
clearTimeout(this._logonMsgTimeout);

if (this.steamID && !suppressLogoff) {
this._loggingOff = true;
Expand Down Expand Up @@ -343,6 +373,9 @@ SteamUser.prototype.relog = function() {
// Handlers

SteamUser.prototype._handlerManager.add(SteamUser.EMsg.ClientLogOnResponse, function(body) {
clearTimeout(this._logonMsgTimeout);
delete this._logonMsgTimeout;

switch (body.eresult) {
case EResult.OK:
delete this._logonTimeoutDuration; // success, so reset reconnect timer
Expand Down Expand Up @@ -451,14 +484,7 @@ SteamUser.prototype._handlerManager.add(SteamUser.EMsg.ClientLogOnResponse, func
case EResult.TryAnotherCM:
this.emit('debug', 'Log on response: ' + EResult[body.eresult]);
this._disconnect(true);

let timer = this._logonTimeoutDuration || 1000;
this._logonTimeoutDuration = Math.min(timer * 2, 60000); // exponential backoff, max 1 minute

this._logonTimeout = setTimeout(() => {
this.logOn(true);
}, timer);

this._enqueueLogonAttempt();
break;

default:
Expand Down

0 comments on commit e9bbe6f

Please sign in to comment.