DoctorMcKay / node-steam-client

API-compatible fork of node-steam's SteamClient
https://steamcommunity.com/groups/SteamRE/discussions/1/
MIT License
52 stars 19 forks source link

self._connection.setTimeout is not a function #14

Closed zaksmok closed 6 years ago

zaksmok commented 6 years ago

Hi. From time to time I receive unhandled error when using this module:

TypeError: self._connection.setTimeout is not a function at /home/node_modules/steam-client/lib/cm_client.js:175:21 at ClientRequest.<anonymous> (/home/node_modules/steam-client/lib/tcp_connection.js:76:4) at emitThree (events.js:136:13) at ClientRequest.emit (events.js:217:7) at Socket.socketOnData (_http_client.js:472:11) at emitOne (events.js:116:13) at Socket.emit (events.js:211:7) at addChunk (_stream_readable.js:263:12) at readableAddChunk (_stream_readable.js:250:11) at Socket.Readable.push (_stream_readable.js:208:10)

Any idea how to fix it?

DoctorMcKay commented 6 years ago

Are you up to date?

Aareksio commented 6 years ago

Are you calling CMClient.connect more than once in short timespan by any chance?

After a few hours of thinking I came up with only one possible reason and managed to replicate it.

Using minimal implementation of CMClient and TCPConnection I managed to reproduce the error with following code:

https://gist.github.com/Aareksio/434d2e472b941a5ff2040df45bc77c06

const httpProxy = 'http://123.45.67.89';
const server = { host: '208.78.164.12', port: 27018 }; // Steam server

const client = new Client();
client.connect(server, httpProxy); // The error comes from THIS call
client.connect(server, httpProxy); // But it's reason is `_connection` created here

Result:

TypeError: this._connection.setTimeout is not a function
    at _connection.connect (Z:\X\polygon\proxyRequest.js:55:22)

Important bit is that client.connect() calls doesn't have to be next to each other, there may be delay, max length of which seems to depend on response time.

Problem

It is happening, because we're overridding client._connection property when calling client.connect().

The request adds connection.setTimeout to itself after connecting, then invokes callback. callback calls client._connection.setTimeout, but client._connection may be already overridden by 2nd call.

Solution

client.connect() already calls client.disconnect() in case there's a connection, but it doesn't affect pending ones.

The solution would be to keep request object from client.connect() (https://github.com/DoctorMcKay/node-steam-client/blob/master/lib/tcp_connection.js#L56) and call request.abort() whenever new connection is created. Probably connection.end() is the most appropriate place for that.

zaksmok commented 6 years ago

I have interval set to 15 seconds where im checking if bot isLogged: return this.user.publicIP && this.client.loggedOn && this.community.steamID && this.manager.apiKey;

If it's return false i logout: this.community.stopConfirmationChecker(); this.user.logOff();

and relogin: this.user.logOn({...})

Aareksio commented 6 years ago

I don't have much expirience with node's HTTP module, so on first glance req.setTimeout(5000) indicated that request will be aborted if not answered within 5000ms, yet tests shown that's not the case.

With 123.123.123.123 proxy address, I got ETIMEOUT after 21s:

callback: 21005.935ms

Error: connect ETIMEDOUT 123.123.123.123:80
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1174:14)

I'm pretty sure 15 second interval/timeout may lead to behavior described in my comment above.

zaksmok commented 6 years ago

Ok, i will try to add connection timeout. Next step will be request.about() call. Thank's for you time