koraktor / steam-condenser

A multi-language library for querying the Steam Community, Source, GoldSrc servers and Steam master servers
https://koraktor.de/steam-condenser
Other
359 stars 65 forks source link

Exceptions on Source server RCON commands that have no response #144

Closed milkmansrevenge closed 12 years ago

milkmansrevenge commented 12 years ago

Hey,

I am getting exceptions when executing RCON commands on Counter-Strike: Source servers if those RCON commands do not have any response. For example:

GameServer server = new SourceServer(ip, port);
server.rconAuth(password);
String output = server.rconExec("say hello");
logger.info("Output: {}", output);
output = server.rconExec("status");
logger.info("Output: {}", output);
output = server.rconExec("mp_c4timer 15");
logger.info("Output: {}", output);

Will run as expected until trying to exec "mp_c4timer 15" where an Exception will be thrown due to the fact that there is no data to read from the socket. However the command still gets run on the server fine. Example stacktrace below:

java.util.concurrent.TimeoutException: null
    at com.github.koraktor.steamcondenser.steam.sockets.SteamSocket.receivePacket(SteamSocket.java:111) ~[steam-condenser-1.0.1.jar:na]
    at com.github.koraktor.steamcondenser.steam.sockets.RCONSocket.getReply(RCONSocket.java:103) ~[steam-condenser-1.0.1.jar:na]
    at com.github.koraktor.steamcondenser.steam.servers.SourceServer.rconExec(SourceServer.java:162) ~[steam-condenser-1.0.1.jar:na]
    at com.example.RconStuff.doStuff(RconStuff.java:97) ~[Example-0.1.0.jar:na]

Similarly but not quite the same, I get SteamCondenserException when doing a "_restart" command on the server.

com.github.koraktor.steamcondenser.exceptions.SteamCondenserException: Connection reset by peer
    at com.github.koraktor.steamcondenser.steam.sockets.SteamSocket.receivePacket(SteamSocket.java:132) ~[steam-condenser-1.0.1.jar:na]
    at com.github.koraktor.steamcondenser.steam.sockets.RCONSocket.getReply(RCONSocket.java:103) ~[steam-condenser-1.0.1.jar:na]
    at com.github.koraktor.steamcondenser.steam.servers.SourceServer.rconExec(SourceServer.java:162) ~[steam-condenser-1.0.1.jar:na]
    at com.example.RconStuff.doStuff(RconStuff.java:97) ~[Example-0.1.0.jar:na]
Caused by: java.io.IOException: Connection reset by peer
    at sun.nio.ch.FileDispatcher.read0(Native Method) ~[na:1.6.0_18]
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39) ~[na:1.6.0_18]
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:251) ~[na:1.6.0_18]
    at sun.nio.ch.IOUtil.read(IOUtil.java:224) ~[na:1.6.0_18]
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:254) ~[na:1.6.0_18]
    at com.github.koraktor.steamcondenser.steam.sockets.SteamSocket.receivePacket(SteamSocket.java:122) ~[steam-condenser-1.0.1.jar:na]
    ... 9 common frames omitted

It should be noted that I did not experience these problems on Counter-Strike 1.6 servers (GoldSrc). I couldn't really test the first issue described here because all commands seem to have some kind of response that they send back. But issuing a "restart" to the 1.6 servers works just fine, without any exceptions.

koraktor commented 12 years ago

It seems you're using an outdated version of Steam Condenser: 1.0.1

A similar problem was discribed in issue #128 and has been fixed in e71952b29a132af5547b12159644d287f0ed9fcc which is part of version 1.0.2.

The current version is 1.1.0, though.

milkmansrevenge commented 12 years ago

Sorry about that - didn't notice the new version was out. Empty RCON responses are getting handled as expected now that I have updated.

I am still getting the SteamCondenserException when sending a "_restart" and "quit" as described above to source servers, but only getting a TimeoutException when sending "quit" to GoldSrc servers ("restart" doesn't give any exception). IMO a legitimate command that gets executed correctly shouldn't give an exception, but I currently can't see a neat way to verify that these commands have been executed.

koraktor commented 12 years ago

The problem with _restart and quit is probably, that the servers don't exit gracefully regarding RCON. Maybe we could handle this for Source, I will check this.

But we'll probably never be able to handle that case for GoldSrc. GoldSrc's protocol is based on UDP, and there's no way to know if this is intended behaviour (like the connection reset) or just some scenario that causes a real timeout.

milkmansrevenge commented 12 years ago

They exit gracefully at least for the clients on the server, giving the message ```Disconnect: Server shutting down.


Of course this done not mean we are so lucky with the RCON connection. "Connection reset by peer" could mean a bunch of things, but at least we know from the stack trace that it happens whilst trying to read a response. I can't find the exact reason because the exception appears to be thrown from a native method. I've only tested this on Debian 6 with
```java -version
java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8.10) (6b18-1.8.10-0+squeeze2)
OpenJDK 64-Bit Server VM (build 14.0-b16, mixed mode)```
koraktor commented 12 years ago

I decided to close this issue.

Application code that allows to call such commands as quit and _restart should handle connection resets itself (as well as other low level problems like timeouts and unavailable servers). Steam Condenser is an API library that cannot implement the correct behavior for each use case that a user might come up with and especially each problem that might show up on server updates by Valve.

@milkmansrevenge That said, to handle this problem yourself just do something similar to the following:

try {
    SourceServer s = new SourceServer(ip, port);
    s.rconAuth("test");
    s.rconExec("_restart");
} catch(SteamCondenserException e) {
    if(!e.getMessage().equals("Connection reset by peer")) {
        throw e;
    }
    System.out.println("Server is restarting.");
}
milkmansrevenge commented 12 years ago

Thanks @koraktor, your decision makes sense - I already have code similar to the above for these cases.