Master Server Query Protocol/Parsing packet

From Valve Developer Community
Jump to: navigation, search

To get each octet you must convert the hex pairs into int32. When the packet is received by your UDP client, the hex values will be converted into their integer values. For example hex "ff" will be converted into "255" in a byte array. We don't want that 255 because the addresses that we are receiving are made up of 6 pairs. 4 pairs are for the octets and the remaining two are combined together to create the port.

An example code for parsing the packet:


        Public Function browser_ConnectMaster(Byval ipStartSeed As String, Byval allFilters As String, Byval regionCode As String) As Byte()
            Dim ip As String = browser_ToString(UnicodeEncoding.ASCII.GetBytes(ipStartSeed))
            Dim filter As String = browser_ToString(UnicodeEncoding.ASCII.GetBytes(allFilters))
            hexString = "31" & regionCode & ip & "00" & filter & "00"
            byteArray = browser_GetBytes(hexString, discarded)
            Public WithEvents udpClientM1, udpClient As New Sockets.UdpClient
            Dim receivedBytes As Byte() = New Byte() {}
            Dim pret As Integer
            Public RemoteIpEndPoint As New System.Net.IPEndPoint(System.Net.IPAddress.Any, 0)
            udpClientM1.Connect("72.165.61.136", 27010) ' Main Server
            RemoteIpEndPoint = udpClientM1.Client.RemoteEndPoint
            pret = udpClientM1.Send(byteArray, byteArray.Length)
            receivedBytes = udpClientM1.Receive(RemoteIpEndPoint)
            Dim retrievedServers() As String = browser_ToStringOriginal(receivedBytes).Split(" ")
            Return retrievedServers
        End Function

        Public Shared Function browser_ToStringOriginal(ByVal bytes As Byte()) As String
            Dim hexString As String = ""
            For i As Integer = 0 To bytes.Length - 1
                Dim newByteStr As String = Convert.ToString(bytes(i), 16)
                If newByteStr.Length < 2 Then ' Hex pair must always have two chars
                    hexString += "0" & newByteStr & " "
                Else               
                    hexString += newByteStr & " "
                End If
            Next
            Return hexString
        End Function

        Public Shared Function browser_ToString(ByVal bytes As Byte()) As String
            Dim hexString As String = ""
            For i As Integer = 0 To bytes.Length - 1
                hexString += bytes(i).ToString("X2")
            Next
            Return hexString
        End Function

        Public Shared Function browser_GetBytes(ByVal hexString As String, ByRef discarded As Integer) As Byte()
            discarded = 0
            Dim newString As String = ""
            Dim c As Char
            ' remove all none A-F, 0-9, characters
            For i As Integer = 0 To hexString.Length - 1
                c = hexString(i)
                If IsHexDigit(c) Then
                    newString += c
                Else
                    discarded += 1
                End If
            Next
            ' if odd number of characters, discard last character
            If newString.Length Mod 2 <> 0 Then
                discarded += 1
                newString = newString.Substring(0, newString.Length - 1)
            End If

            Dim byteLength As Integer = newString.Length / 2
            Dim bytes As Byte() = New Byte(byteLength - 1) {}
            Dim hex As String
            Dim j As Integer = 0
            For i As Integer = 0 To bytes.Length - 1
                hex = New [String](New [Char]() {newString(j), newString(j + 1)})
                bytes(i) = HexToByte(hex)
                j = j + 2
            Next
            Return bytes
        End Function

The above code will do the following: Connect to the master server, send a UDP query with specific variables (region code, start seed, filters), receive packet into byte array, convert byte array in hex array.

Now that we have converted the byte array into a hex array, we must convert each hex pair into its int32 equivalent.

    Dim serverList As New Hashtable()

    Private Sub browser_ParsePacket(Byval packet As String())
        Dim countPrimary, countSecondary As Integer
        Dim address, portBuilder, lastAddress As String

        Try
            For Each hexPair As String In packet
                If Not hexPair = Nothing Then
                    countPrimary += 1
                    If countPrimary > 6 Then
                        If countSecondary <= 2 Then ' Get first 3 octets
                            address = address & Convert.ToInt32(hexPair, 16) & "."
                        ElseIf countSecondary = 3 Then ' Fourth octet must have a trailing :
                            address = address & Convert.ToInt32(hexPair, 16)
                        ElseIf countSecondary > 3 Then ' Get last two hex pairs to form the port
                            portBuilder = portBuilder & hexPair
                        End If
                        If countSecondary = 5 Then ' Convert the combined hex pairs into an integer
                            portBuilder = Convert.ToInt32(portBuilder, 16)
                        End If
                        countSecondary += 1
                    End If
                    If countSecondary = 6 Then
                        lastAddress = address & ":" & portBuilder
                        serverList.Add(serverList.Count + 1, address & ":" & portBuilder)
                        countSecondary = 0
                        portBuilder = 0
                        address = String.Empty
                    End If
                End If
            Next
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

        If Not lastAddress = "0.0.0.0:0" Then
            browser_ConnectMaster(lastAddress, "\napp\500", "00")
            Exit Sub
        Else
            For Each item As DictionaryEntry In serverList
                    browser_HostConnect(item.Value)
            Next
        End If
    End Sub

This above code will go through each and every hex pair in the array. Ever 6 pairs (12 characters) is another IP address. It will add the found IP address to hashtable which can again be put through a loop to extract the addresses to connect and query later on.

(Code written by Erix920, your welcome devs :))