English CS2D Manager

9 replies
Goto Page
To the start Previous 1 Next To the start
21.07.11 11:45:01 am
Up
Manny
User
Offline Off
Hello, I'd like to make CS2D Manager because "Server RCon/Viewer Tool by kog (Alpha Version, for dedicated servers)" is not enough for me and nothing better exists, so i decided to make it on my own.

I've got problem. Does anybody know what is format for sending command to server? For example if i wanna kick somebody?

I saw this function in PHP:
Code:
1
2
3
4
5
6
7
function send_command($ip,$port,$rcon,$command) {
     $fp = @fsockopen("udp://".$ip, $port, $errno, $errstr);
     if ($fp){
          $request = chr(1).chr(0).chr(242).chr(strlen($rcon)).$rcon.pack("S",strlen($command)).$command;
          fwrite($fp, $request);
     }
}


I'm trying to make application in Lazarus (FreePascal) but all i need is to know format of packet to send... i have tried this:
Code:
1
myFormat := chr(1)+chr(0)+chr(242)+chr(1) + chr(Length(rcon)) + rcon + chr(Length(cmd)) + cmd;

... but CS2D dedicated server returned:
Code:
1
2
WARNING: Failed RCon attempt from 127.0.0.1:53130 (cmd: )
NET: Received unknown or damaged msg (118, 127.0.0.1:53130)
edited 2×, last 21.07.11 12:09:05 pm
21.07.11 03:10:05 pm
Up
Lee
Moderator
Offline Off
cmd can theoretically be over 0xff bytes long, so its length header is a short not a byte.

Code:
1
chr(Length(cmd))


If pascal has pointers and static casting, then it's possible to use this idiom: (Note: C code)

Code:
1
2
3
typedef unsigned char byte;
#define short(i) ((byte*)&(i))[0], ((byte*)&(i))[1]
char* packed = {short(strlen(cmd))};


Which offers the nice property that the endianness of the machine is preserved.

The more verbose solution is to use an AND mask for lo and a shift of one byte ( 8 ) for hi. C idiom:

Code:
1
2
3
4
typedef unsigned char byte;
short c; // assume 16 bits
byte byte1 = c & 0xff; //We mask all but 0b11111111
byte byte2 = (c >> 8) & 0xff; // shift by 8 then mask to hide overflow from certain machines


Now since cs2d standardized all of its data to be packed in small endian, our task becomes much simpler. We just concatenate the two as such:

Code:
1
2
3
short c;
...
byte* packed = {(c >> 8) & 0xff, c & 0xff};


Note that byte2 comes before byte1.
21.07.11 05:15:49 pm
Up
Manny
User
Offline Off
Excuse me if I'm wrong, so problem is that "cmd" is not in binary format?
21.07.11 05:21:41 pm
Up
DannyDeth
User
Offline Off
I doubt that would be the problem. What Lee is trying to point out ( at least what I think he is saying ) is that the length of cmd is supposed to be 16-bits wide instead of 8-bits, so using chr(length(cmd)) would be too short ( 1 byte wide snstead of 2 ).
21.07.11 05:49:43 pm
Up
Lee
Moderator
Offline Off
Quote:
Excuse me if I'm wrong, so problem is that "cmd" is not in binary format?


Danny's right, whenever CS2D sends out raw text, it must also be able to tell how many bytes of that text must be read in. So for the cmd parameter, you can have a string of text well over 256 characters long. Since a byte can hold an integer only up to 255 (0-255), we need two bytes to denote the length of the text.

Pascal's function chr only returns the most significant byte. This means that chr(1024) = chr(1024%256) = chr(0) = "\x00" , not "\x00" "\x04" as it should be.

And even if the number is less than 256, CS2D expects a short, which means two bytes, so "a" would require a header of "\x01" "\x00"
21.07.11 07:16:45 pm
Up
Manny
User
Offline Off
What's the solution of this? I though it would be simple like in PHP but it seems it's more complex. Now, i know where is the problem but i don't have skills for this. I don't want to stuck at the beginning.
21.07.11 08:46:12 pm
Up
Lee
Moderator
Offline Off
As per my previous post, the solution is to simply do the following:

byte byte1 = c & 0xff; //We mask all but 0b11111111
byte byte2 = (c >> & 0xff; // shift by 8 then mask to hide overflow from certain machines
where byte2 concat byte1 gives you the correct string.

Code:
1
2
3
4
function short(len : integer) : string;
begin
     short := chr((len shr 8) and 255) + chr(len and 255);
end


Code:
1
myFormat := chr(1)+chr(0)+chr(242)+chr(1) + chr(Length(rcon)) + rcon + short(Length(cmd)) + cmd;


For reference, here's what the shr and the and operators do: http://www.freepascal.org/docs-html/ref/refsu37.html

I'm not 100% familiar with the semantics of pascal grammar so the code may not run as is, but the gist is there.
21.07.11 09:41:52 pm
Up
Manny
User
Offline Off
Lee, thank you very much for your interest in my problem. I used your function but the result is still the same, CS2D dedicated server returned:
Code:
1
2
WARNING: Failed RCon attempt from 127.0.0.1:49874 (cmd: )
NET: Received unknown or damaged msg (118, 127.0.0.1:49874)
21.07.11 10:51:01 pm
Up
Lee
Moderator
Offline Off
oops, small endian does LSB first and not the other way around.

Code:
1
2
3
4
function short(len : integer) : string;
begin
     short :=  chr(len and 255) + chr((len shr 8) and 255);
end


at the same time, you added in an extra character into the packet right after the 242

Code:
1
myFormat := chr(1)+chr(0)+chr(242) + chr(Length(rcon)) + rcon + short(Length(cmd)) + cmd;


I just did a quick test over python and this scheme works correctly.

Code:
1
2
3
4
def short(len):
     return chr(len&0xff)+chr((len>>8)&0xff)

sock.sendto(chr(1)+chr(0)+chr(242) + chr(len(rcon)) + rcon + short(len(cmd)) + cmd, ("localhost", 36963))


Be sure to do a recvfrom on the socket, you will essentially get a packet that looks something like this:

Code:
1
2
(hexadecimal)
01 00 f0 00 03 nn nn msg


Since pascal strings are nice to work with, you can simply do a substring of this packet from index 6 (or 7 depending on how pascal handles substring).

The nn nn parameter in the return packet tells you how many bytes the message should be, but since you have only sent a single request to the server from your address, CS2D will not collate several different responses into a single packet so you can be assured that everything from index 6 onwards to the end of the string will contain only characters from the response message.

Edit:
If rcon fails authentication, the third byte of the returned packet will be ordinal 242.
edited 1×, last 21.07.11 11:01:08 pm
22.07.11 12:47:52 am
Up
Manny
User
Offline Off
Lee, thank you very much for you time to help me from the darkness It works like a charm!
To the start Previous 1 Next To the start