All pastes #813898 Raw Edit

Anonymous

public text v1 · immutable
·published 2007-12-12 21:36 UTC
rendered paste body
I finally figured it out:

Arma encodes all network traffic as 16- bit integers. Therefore, to send a string (like the player name), the individual characters are paired together, the first char of each pair becoming the lower byte of the new short, the second thar becoming the upper byte.

At least that's what tank was probably thinking when he originally wrote the script (and nobody noticed it afterwards).

Well, what actually happens is this:[code]    char const * sRaw = s;

    // write first pairs of bytes
    for(i=0;i+1<len;i+=2)
        Write(sRaw[i]+(sRaw[i+1] << 8));[/code](nNetwork.cpp:~985)
It multiplies the second char by 256 and adds that to the first char to get the short to be sent. This works alright until the first char gets bigger than 127. Because sRaw is a [b]signed[b] char* sRaw[i] is actually a negative number and gets subtracted from (sRaw[i+1] << 8), therefore causing some mess (the second char's ascii value gets lowered by 1).

The code on the other end that converts the stream back to a string has the same quirk, therefore you don't notice anything in arma itself. It's just the poor php script that has to deal with it.

Anyways, here's my fix. I don't know exactly how robust/correct/ugly it is, but it appears to work:[code]		for ($c = 0; $c < strlen($this->rawpacket); $c = $c + 2)
		{
			$this->swappedpacket[$c] = $this->rawpacket[$c + 1];
			$this->swappedpacket[$c + 1] = $this->rawpacket[$c];
		}[code]becomes[code]		for ($c = 0; $c < strlen($this->rawpacket); $c = $c + 2)
		{
			$this->swappedpacket[$c] = $this->rawpacket[$c + 1];
			$this->swappedpacket[$c + 1] = $this->rawpacket[$c];
			if(ord($this->swappedpacket[$c]) > 127) {
				$this->swappedpacket[$c + 1] = chr(1 + ord($this->swappedpacket[$c + 1]));
			}
		}[/code]