Page MenuHomeFeedback Tracker

Steam Query Yielding Random Packet Orders
Acknowledged, WishlistPublic

Description

Upon querying game servers, locations of certain values are non-deterministic (player count, gametags as two examples)
As shown here:
https://community.bistudio.com/wiki/STEAMWORKSquery#SetGameTags_in_detail

Packet sequence 6 is normally blank for empty servers, so we interpret that for the player count.
However it seems that SetGameTags get pushed to sequence 11 when the server is empty on query.

Since you block .dat extensions here is the download URL: http://inchshare.net/packetsA3.7z

I've linked several outputs (in the zip).
PacketIncorrect.dat
PacketOK.dat
Packet-emptyserver.dat

These should be self explanatory.
Segment delimiter is 0x00, first 6/7 bytes are to be ignored.

Details

Legacy ID
13852806
Severity
None
Resolution
Open
Reproducibility
Random
Category
Dedicated Server
Steps To Reproduce

List<byte[]> serverValues = GetSubArrays(responseBytes, 0x00);

name = Encoding.Default.GetString(serverValues[0]);
map = Encoding.Default.GetString(serverValues[1]);
game = Encoding.Default.GetString(serverValues[2]);
description = Encoding.Default.GetString(serverValues[3]);

if (serverValues[6].Count() > 0)
{

  var gameTags = GetSubArrays(serverValues[10], 0x2c);

  players = serverValues[6][0];
  playersmax = serverValues[6][1];
  locked = gameTags[6][1] == 't';

}
else
{

var gameTags = GetSubArrays(serverValues[11], 0x2c);
players = 0;
playersmax = serverValues[7][0];
locked = gameTags[6][1] == 't';

}

-------------------------------------------------------------------

public List<byte[]> GetSubArrays(byte[] array, byte delimiter)
{

  if (array == null)
  return null;

  var retval = new List<byte[]>();
  var sectionStart = 6; //first 6 bytes of the response are a header, we don't need it
  var sectionEnd = 0;

  for (; sectionEnd < array.Length; sectionEnd++)
  {
    if (array[sectionEnd] != delimiter) continue;
    var tempArray = new byte[sectionEnd - sectionStart];
    Buffer.BlockCopy(array,sectionStart,tempArray,0,sectionEnd - sectionStart);
    retval.Add(tempArray); 
    sectionStart = sectionEnd + 1;
  }

  return retval;

}

Additional Information

You could create a simple application to debug the packet sequence in development then have it output servers sending packets in random orders, or not sending SetGameTags. Something like the above. Feel free to use the above for parsing data :)

Event Timeline

Inch edited Steps To Reproduce. (Show Details)Jul 3 2015, 8:15 PM
Inch edited Additional Information. (Show Details)
Inch set Category to Dedicated Server.
Inch set Reproducibility to Random.
Inch set Severity to None.
Inch set Resolution to Open.
Inch set Legacy ID to 13852806.May 8 2016, 12:19 PM
Inch edited a custom field.
Bohemia added a subscriber: Dwarden.Jul 3 2015, 8:15 PM

Hello Inch,
the NUL (0x00) char is only used as terminal character of the string. But it's not a separator! Some of the fields in the protocol are numbers of fixed length and in those the 0x00 is part of the values itself.

The protocol is described here: https://developer.valvesoftware.com/wiki/Server_queries#A2S_INFO

Also when parsing game tags string, you should identify the tags by their identifier that relying on theirs ordinal position - that is not guaranteed and that's why the identifiers are there.