Talk:Source RCON Protocol

From Valve Developer Community
Revision as of 14:29, 20 February 2011 by Koraktor (talk | contribs) (How to receive split response?)

Jump to: navigation, search

This article was taken from a HLDS_APPS posting by Alfred Reynolds.

Additional Remarks have been added to Alfred's Documentation. This is taken from the KQuery Wiki (http://wikki.kquery.net/), as unfortunately the page is defaced. One can dig deeply through the revision history to obtain the information, some of which is vital to creating a working implementation.. I have taken the liberty of echoing it here. 20:51, 4 Feb 2006 - Erik Hollensbe

The C app (CLI / rcon.c) unfortunately does not work for me. I either get 'authentication failed' or 'Illegal size -559038737'. Maybe the app does not like 64bit Linux. Other apps (like SRCDS.py) work just fine but their code is hard to understand, and they require Python and the like. I googled for a better C implementation but couldn't come up with anything. Too bad there isn't a more official tool for this, as it can be really useful for maintaining servers remotely. Andreas Klauer 06:13, 14 Jul 2008 (PDT)

Packets splitting confusion

I have Ruby code able to receive really long RCON responses from Source servers. This works (even for cvarlist = 43 packets) almost flawlessly. But cvarlist (and maybe other requests) fails in around 1 of 4 tries. The problem is that the packet size of the split packets is wrong. It doesn't show the complete size of the packet, but only until the first zero-byte (0x00, the end of the first string component). In my experience the second string component isn't used very often, so the response is a string terminated by 2 zero-bytes in almost all cases. It's quite interesting that this error happens when the text of the response is split into the two strings. Even more interesting is that this happens always in the same section of the text (for cvarlist just in the middle of the description for ai_show_connect). In the moment I'm pretty sure this is a bug in Source as I can't imagine a purpose of this random behavior. --Koraktor 10:20, 8 Dec 2008 (PST)

I'd post that on hlcoders. --TomEdwards 10:47, 8 Dec 2008 (PST)
Already had that in mind. Thanks for the reminder. ;) --Koraktor 11:06, 8 Dec 2008 (PST)

How to receive split response?

How to receive a split response correctly? There's nothing that indicates that the packet is split, so currently I just continue listening for additional packets with the correct id and concatenate the string1 together until a timeout occurs. This works fine for cvarlist. I'm planning on optimizing this, by listening for additional packets only if the previous packet was long, i.e. if the probability for additional packets is high - this should work assuming that a split always means that the previous packets use the maximum length for string1 (4096 or something bytes according to the spec here). However this still means there is some chance I have to continue listening (and thus blocking the result) for nothing. Anyone know of a better way? Frostschutz 11:29, 26 January 2010 (UTC)

Ok, it seems a heuristic is necessary here. For a cvarlist I get 37 packets, and ignoring the last packet (3436 bytes), the split packets were between 3915 and 4103 bytes in size. The size is not constant because the output seems to be split by lines, instead of bytes... each packet starts with a cvar and ends with a \n. So I looked at the length of lines and they were between 0 and 201 characters. So for safety I will assume a maximum line length of about 400 characters (about two times the maximum of cvarlist) so if a packet is 3700 bytes or larger it will assume that another packet may follow. So my implementation will block and listen (until timeout) in this case, and otherwise just poll. This avoids unnecessary blocks for short responses or split responses that have a short last packet. If anyone has any better suggestions, please share. Frostschutz 17:24, 26 January 2010 (UTC)

I found an alternative method that does not rely on heuristics, but it might be seen as a hack: Empty requests sent to the server, return an empty response. This means that if you send a (series of) request(s) to the server, you can follow it up with an empty request. This will act as a terminator: you know that you received the reply completely as soon as you receive the response to your terminator request. The downside of this is that it will add an additional entry to your server log (rcon from "1.2.3.4:5678": command "") and will add an overhead of 2 packets to every (series of) request(s).

Even if you decide to not use terminator packets, your implementation should be aware of changing request ids when sending a series of requests, so only the last request will have to wait for additional packets that will never come if the above heuristic fails. Frostschutz 13:04, 8 February 2010 (UTC)

...and here's the hack made perfect: instead of sending an empty command, just send another SERVERDATA_AUTH request on an already authed connection as a terminator. The server will reply properly without adding an entry to the logs. Combine that with the previously used heuristic, i.e. send the terminator request only if a) you received a packet that's large enough to assume it may be split, b) there are no other requests to be sent in the queue. This way the heuristic will never wait for a packet that will never come because you definitely get a packet (your terminator packet). Worst case you have to wait $ping ms for the server to send your terminator packet back. Frostschutz 16:01, 8 February 2010 (UTC)

- There's even a better solution for sending a SERVERDATA_AUTH request. Just send an empty SERVERDATA_RESPONSE_VALUE packet. The server will reply with an empty SERVERDATA_RESPONSE_VALUE packet, too. That way you don't have to save the password for an additional SERVERDATA_AUTH request to avoid the risk of being banned for using the wrong password. --Koraktor 14:29, 20 February 2011 (UTC)