Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
# Conflicts:
#	components/09-logon.js
#	index.js
  • Loading branch information
DoctorMcKay committed Aug 12, 2024
2 parents 351035f + 4396166 commit 705a610
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 10 deletions.
24 changes: 21 additions & 3 deletions components/02-connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ class SteamUserConnection extends SteamUserEnums {
}

this.emit('debug', `[${connPrefix}] Handling connection close`);
if (this._loggingOff) {
// We want to bail, so call _handleLogOff now (normally it's called at the end)
this._handleLogOff(EResult.NoConnection, 'Logged off');
return;
}

this._cleanupClosedConnection();

if (!this.steamID) {
Expand All @@ -37,16 +43,22 @@ class SteamUserConnection extends SteamUserEnums {
this._ttlCache.add(`CM_DQ_${this._lastChosenCM.type}_${this._lastChosenCM.endpoint}`, 1, 1000 * 60 * 2);
}

setTimeout(() => this._doConnection(), 1000);
// We save this timeout reference because it's possible that we handle connection close before we fully handle
// a logon response. In that case, we'll cancel this timeout when we handle the logon response.
// This isn't an issue in the reverse case, since a handled logon response will tear down the connection and
// remove all listeners.
this._reconnectForCloseDuringAuthTimeout = setTimeout(() => this._doConnection(), 1000);
} else {
// connection closed while we were connected; fire logoff
this._handleLogOff(EResult.NoConnection, 'NoConnection');
}
}

_cleanupClosedConnection() {
clearTimeout(this._logonTimeout); // cancel any queued reconnect attempt
clearTimeout(this._logonMsgTimeout);
this._connecting = false;
this._loggingOff = false;

this._cancelReconnectTimers();
clearInterval(this._heartbeatInterval);

this._connectionClosed = true;
Expand All @@ -56,6 +68,12 @@ class SteamUserConnection extends SteamUserEnums {
this._clearChangelistUpdateTimer();
}

_cancelReconnectTimers() {
clearTimeout(this._logonTimeout);
clearTimeout(this._logonMsgTimeout);
clearTimeout(this._reconnectForCloseDuringAuthTimeout);
}

_getProxyAgent() {
if (this.options.socksProxy && this.options.httpProxy) {
throw new Error('Cannot specify both socksProxy and httpProxy options');
Expand Down
34 changes: 30 additions & 4 deletions components/09-logon.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,24 @@ class SteamUserLogon extends SteamUserMachineAuth {
*/
logOn(details) {
// Delay the actual logon by one tick, so if users call logOn from the error event they won't get a crash because
// they appear to be already logged on (the steamID property is set to null only *after* the error event is emitted)
// they appear to be already logged on (the steamID property is set to null only *after* the error event is emitted).
// Go ahead and create the Error now, so that we'll have a useful stack trace if we need to throw it.
let alreadyLoggedOnError = new Error('Already logged on, cannot log on again');
let alreadyConnectingError = new Error('Already attempting to log on, cannot log on again');
process.nextTick(async () => {
if (this.steamID) {
throw new Error('Already logged on, cannot log on again');
throw alreadyLoggedOnError;
}

if (this._connecting) {
throw alreadyConnectingError;
}

this.steamID = null;
this._cancelReconnectTimers();
this._initProperties();

this._connecting = true;
this._loggingOff = false;

if (details !== true) {
Expand Down Expand Up @@ -301,9 +310,10 @@ class SteamUserLogon extends SteamUserMachineAuth {
}

if (++this._getCmListAttempts >= 10) {
this._cleanupClosedConnection();
this.emit('error', ex);
} else {
setTimeout(() => this._doConnection(), 500);
setTimeout(() => this._doConnection(), 1000);
}

return;
Expand All @@ -315,6 +325,7 @@ class SteamUserLogon extends SteamUserMachineAuth {
}

if (!cmListResponse.response || !cmListResponse.response.serverlist || Object.keys(cmListResponse.response.serverlist).length == 0) {
this._cleanupClosedConnection();
this.emit('error', new Error('No Steam servers available'));
return;
}
Expand Down Expand Up @@ -481,7 +492,16 @@ class SteamUserLogon extends SteamUserMachineAuth {
_enqueueLogonAttempt() {
let timer = this._logonTimeoutDuration || 1000;
this._logonTimeoutDuration = Math.min(timer * 2, 60000); // exponential backoff, max 1 minute
this.emit('debug', `Enqueueing login attempt in ${timer} ms`);
this._logonTimeout = setTimeout(() => {
if (this.steamID || this._connecting) {
// Not sure why this happened, but we're already connected
let whyFail = this.steamID ? 'already connected' : 'already attempting to connect';
this.emit('debug', `!! Attempted to fire queued login attempt, but we're ${whyFail}`);
return;
}

this.emit('debug', 'Firing queued login attempt');
this.logOn(true);
}, timer);
}
Expand Down Expand Up @@ -643,14 +663,15 @@ class SteamUserLogon extends SteamUserMachineAuth {
this.steamID = null;
} else {
// Only emit "disconnected" if we were previously logged on
let wasLoggingOff = this._loggingOff; // remember this since our 'disconnected' event handler might reset it
if (this.steamID) {
this.emit('disconnected', result, msg);
}

this._disconnect(true);

// if we're manually relogging, or we got disconnected because steam went down, enqueue a reconnect
if (!this._loggingOff || this._relogging) {
if (!wasLoggingOff || this._relogging) {
this._logonTimeout = setTimeout(() => {
this.logOn(true);
}, 1000);
Expand Down Expand Up @@ -689,6 +710,11 @@ class SteamUserLogon extends SteamUserMachineAuth {
async _handleLogOnResponse(body) {
this.emit('debug', `Handle logon response (${EResult[body.eresult]})`);

this._connecting = false;

clearTimeout(this._reconnectForCloseDuringAuthTimeout);
delete this._reconnectForCloseDuringAuthTimeout;

clearTimeout(this._logonMsgTimeout);
delete this._logonMsgTimeout;

Expand Down
2 changes: 1 addition & 1 deletion components/chatroom.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ class SteamChatRoomClient extends EventEmitter {
}

body.group_summary = processChatGroupSummary(body.group_summary, true);
body.user_chat_group_state = processUserChatGroupState(body.user_chat_group_state, true);
body.user_chat_group_state = body.user_chat_group_state ? processUserChatGroupState(body.user_chat_group_state, true) : null;
body.banned = !!body.banned;
body.invite_code = match[1];
resolve(body);
Expand Down
2 changes: 2 additions & 0 deletions components/connection_protocols/tcp.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,13 @@ class TCPConnection extends BaseConnection {

req.on('timeout', () => {
connectionEstablished = true;
this.user._cleanupClosedConnection();
this.user.emit('error', new Error('Proxy connection timed out'));
});

req.on('error', (err) => {
connectionEstablished = true;
this.user._cleanupClosedConnection();
this.user.emit('error', err);
});
} else {
Expand Down
1 change: 1 addition & 0 deletions components/connection_protocols/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class WebSocketConnection extends BaseConnection {

if (err.proxyConnecting || err.constructor.name == 'SocksClientError') {
// This error happened while connecting to the proxy
this.user._cleanupClosedConnection();
this.user.emit('error', err);
} else {
this.user._handleConnectionClose(this);
Expand Down
2 changes: 1 addition & 1 deletion components/twofactor.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class SteamUserTwoFactor extends SteamUserTrading {

/**
* Finalize the process of enabling TOTP two-factor authentication
* @param {Buffer} secret - Your shared secret
* @param {Buffer|string} secret - Your shared secret
* @param {string} activationCode - The activation code you got in your email
* @param {function} [callback] - Called with a single Error argument, or null on success
* @return {Promise}
Expand Down
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ class SteamUser extends SteamUserTwoFactor {
delete this._shouldAttemptRefreshTokenRenewal;
delete this._loginSession;
delete this._connectionClosed;

clearTimeout(this._reconnectForCloseDuringAuthTimeout);
delete this._reconnectForCloseDuringAuthTimeout;
}

get packageName() {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "steam-user",
"version": "5.0.4",
"version": "5.0.10",
"description": "Steam client for Individual and AnonUser Steam account types",
"keywords": [
"steam",
Expand Down

0 comments on commit 705a610

Please sign in to comment.