0

Trying to decode a UDP message, it is an array of 128 bytes, the first variable length string begins at the 7th byte. What I would like to do is split the array into individual elements and decode each element based on the type(byte,string). The data format/types are defined here: http://developer.valvesoftware.com/wiki/Server_queries#Goldsource_servers_2

Here is the raw data. Receive Buffer: 255 255 255 255 73 48 115 99 52 46 120 32 84 101 115 116 32 83 101 114 118 101 114 91 50 56 49 51 93 0 99 48 97 48 101 0 115 118 101 110 99 111 111 112 5 2 0 83 118 101 110 32 67 111 45 111 112 32 52 46 54 32 111 114 32 108 97 116 101 114 0 70 0 0 12 0 100 119 0 0 49 46 49 46 50 46 49 0 145 145 105 3 44 67 175 180 9 64 1 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Here is what it looks like as an array of strings split on "0x00". String Response: ????I0sc4.x Test Server[2813] c0a0e svencoop4 Sven Co-op 4.6 or later F ♀ dw 1.1.2.1 ??i♥,C?? @☺F

This works fine up to the fifth element(the "F" after the word "later"). Things get a little garbled after that and I cannot figure out how to select/decode the remaining elements.

# convert to string.
$StringResponse = [Text.Encoding]::ASCII.GetString($ReceiveBuffer)  
# make an array of strings.  
$SplitString = $StringResponse.split([char][byte]"0x00")  
# store the value of individual elements.  
$servername_split =             $SplitString[0].split([char]"0")  
             $Map =             $SplitString[1]  
   $gamedirectory =             $SplitString[2]  
 $gamedescription =             $SplitString[3]  
           $appid = [byte][char]$splitstring[4] 

Working with the raw data:
This works to access the first couple of byte elements after the four byte header 255, 255, 255, 255. Then the variable length strings begin.

                  $type = [char]$ReceiveBuffer[4]  
$NetworkProtocolVersion =       $ReceiveBuffer[5]  

So I cannot do this to access the byte elements near the end of the raw data, unless I know in advance how many bytes are used by the variable length string data.

   $numplayers =       $ReceiveBuffer[72]  
$maxnumplayers =       $ReceiveBuffer[73]  
      $numbots =       $ReceiveBuffer[74]  
    $dedicated = [char]$ReceiveBuffer[75]  
           $os = [char]$ReceiveBuffer[76]  
  $passwordreq =       $ReceiveBuffer[77]  
       $secure =       $ReceiveBuffer[78]  

Console Output:

Type: I
Network Protocol Version: 48
Server Name: sc4.x Test Server[2813]
Map: c0a0e
Game Directory: svencoop4
Game Description: Sven Co-op 4.6 or later
AppID: 70

TIA,

1 Answer 1

0

hey I think I got it figured out.

# Receive Buffer size varies from server to server.  
$ReceiveBuffer = New-Object  Byte[] 128

# Info Reply  
$BytesReceived = 0  
Try  
{  
    $BytesReceived = $UdpSocket.Receivefrom($ReceiveBuffer, [REF]$UdpSocket.LocalEndpoint)  
}  

# An Exception will be thrown if the server is down or hung.  
Catch [Net.Sockets.SocketException]  
{  
    # Set Flag  
    $Script:NoConnectionTimeOut = $False  
}  

# Verify and Decode HLDS server response.  
If ($BytesReceived -gt 0)  
{  
    # Ignore the four byte header and store the values of the first two bytes.  
    $type =       [char]$ReceiveBuffer[4]  
    $netversion =       $ReceiveBuffer[5]  

    # Loop through the byte array and store each type of data.  
    $i = 0  
    $StringNum = 0  
    $FoundAppID = $False  
    foreach ($element in $receivebuffer)  
    {  
        If ($i -gt 5 -and $i -lt 80)
        {
            If ($element -ne 0)
            {
                $string = $string + [Text.Encoding]::ASCII.GetString($element)
            }
            Else
            {
                $StringNum++
                if ($stringnum -eq 1) {      $ServerName = $string }
                if ($stringnum -eq 2) {         $MapName = $string }
                if ($stringnum -eq 3) {     $InfoGameDir = $string }
                if ($stringnum -eq 4) { $GameDescription = $string }
                $string = ""
            }
        }
        if ($i -gt 50 -and $element -eq 70 -and $FoundAppID -eq $False)
        {
            if ($element -eq 70)
            {
                $FoundAppID = $True
                $AppID = $element;$arrayIndex = $i
                $i++;$i++
                $numplayers =      $ReceiveBuffer[$i]
                $i++
                $maxnumplayers =   $ReceiveBuffer[$i]
                $i++
                $numbots =         $ReceiveBuffer[$i]
                $i++
                $dedicated = [char]$ReceiveBuffer[$i]
                $i++
                $os =        [char]$ReceiveBuffer[$i]
                $i++
                $Password =        $ReceiveBuffer[$i]
                $i++
                $Secure =          $ReceiveBuffer[$i]
                for ($j = 1; $j -lt 9; $j++)
                {
                    $i++
                    $GameVersion = $GameVersion + [Text.Encoding]::ASCII.GetString($ReceiveBuffer[$i])
                }
                $i++
                $EDF =             $ReceiveBuffer[$i]
            }
        }
        $i++
    }

    # Write the server info.
    write-host "`n                    Type: $type"
    write-host "        Protocol Version: $netversion"
    write-host "             Server Name: $ServerName"
    write-host "                     Map: $MapName"
    write-host "          Game Directory: $InfoGameDir"
    write-host "        Game Description: $GameDescription"
    write-host "                   AppID: $AppID, $arrayIndex"
    write-host "       Number of players: $numplayers"
    write-host "         Maximum players: $maxnumplayers"
    write-host "          Number of bots: $numbots"
    write-host "               Dedicated: $dedicated"
    write-host "                      OS: $os"
    write-host "                Password: $Password"
    write-host "                  Secure: $Secure"
    write-host "            Game Version: $GameVersion"
    write-host "                     EDF: $EDF"
    #"Raw Data: $ReceiveBuffer"
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.