Source Protocol

McFace

Newbie
Joined
May 26, 2003
Messages
135
Reaction score
0
Alright, I'm trying to create a program in VB6 with winsock to query a server when given it's ip and port. Now I succesfully have done this, my question is how would you go about parsing this data? Some of it is in raw bytes so you'd need to asc() it (the protocol, ammount of players etc is all in bytes) but I don't know how to seperate all the information.

Source Protocol

The link above has information on the source protocol, it isn't to much different from half-life.

Each bit of information is serperated by a null byte, but I can't figure out how to do this:

BTW I've already alterted it so the 4 consecutive bytes no longer are in the received data.

[Placebo Code]
Take all the information from the beginning up until the null byte - 1.
Store it in the server name string.
Take all the information from the last null byte + 1 to the next null byte -1.
Store it in the server map string.
etc.
etc.
If I have reached the end of the packet, exit this function/procedure.
[/Placebo Code]

Anyone have any experience with winsock, vb6, and the Half-Life protocol?
 
Placebo code.

I always heard it was pseudo code.

That's a new term for it.
 
No your right it is pseduo code but I couldn't remember what it was called. Anyways more importantly, has anyone parsed server query information from regular half-life servers in vb? It could easily be adapted to source protocol.
 
If you have all the information in a large buffer then you can search where the first null mark (\0) is and then copy that data to another buffer or string.

I have done VB but I forgot almost everything otherwise I would have givin you an example.
 
I got it finally to do what I wanted, I'm sure theres a better more easy looking way to do it, but I came up with this code that works fine. This is just for anyone who's interested. I've commented hopefully to get you through this ugly code.

Code:
Public ByteHeader As String
Public ByteSep As String

ByteHeader = Chr(255) & Chr(255) & Chr(255) & Chr(255) 'Four consecutive bytes of character 255, used in every packet by SOURCE

ByteSep = Chr(0) 'The character used in SOURCE packets to determine seperation of information

Code:
Private Sub wsck_DataArrival(ByVal bytesTotal As Long)
   Dim strReceived As String
   Dim ControlByte As String
   Dim strFixed As String

   wsck.GetData strReceived, bytesTotal 'Put the received data into a string for the total ammount of bytes
   
   strFixed = Mid(strReceived, 5) 'Remove consecutive bytes from string, store this information in a new string
   
   ControlByte = Mid(strFixed, 1, 1) 'Take the first byte and store it in The ControlByte string. This byte tells what type of information is contained within the packet
   Select Case ControlByte
   
   Case Is = "I" 'If ControlByte is I, then it must be server query information...
   ServerQuery (strFixed)
   
   End Select
   
   wsck.Close 'Close the connection
End Sub

Code:
Sub ServerQuery(strReceived As String)
   Dim strFixed As String
   Dim ServerInfo(0 To 6) As String

   strFixed = Mid(strReceived, 3) 'Remove all informtion until the beginning of the first string

   i = InStr(strFixed, ByteSep) 'Find the seperator byte's position and store it's value in i
   
   ServerInfo(0) = Mid(strFixed, 1, i - 1) 'Store the string from the beginning of the packet until 1 - the byte seperator. This is the server's name

   strFixed = Replace(strFixed, ServerInfo(0) + ByteSep, "") 'Get rid of the server name and the byte seperator from the string
   
   i = InStr(strFixed, ByteSep) 'The cycle begins again....

   ServerInfo(1) = Mid(strFixed, 1, i - 1) 'Map Name
   
   strFixed = Replace(strFixed, ServerInfo(1) + ByteSep, "")
   
   i = InStr(strFixed, ByteSep)
   
   ServerInfo(2) = Mid(strFixed, 1, i - 1) 'Game DIR
   
   strFixed = Replace(strFixed, ServerInfo(2) + ByteSep, "")
   
   i = InStr(strFixed, ByteSep)
   
   ServerInfo(3) = Mid(strFixed, 1, i - 1) 'Game Description

   strFixed = Replace(strFixed, ServerInfo(3) + ByteSep, "")

'Since the rest of the data is just single bytes,
'and there are only three of them we need,
'we no longer need to search for the seperator byte because we know
'how long the information is (1 byte) and where it is positioned


   ServerInfo(4) = Asc(Mid(strFixed, 3, 3)) 'Number of active players
   
   ServerInfo(5) = Asc(Mid(strFixed, 4, 4)) 'Maximum number of players

   ServerInfo(6) = Asc(Mid(strFixed, 5, 5)) 'Number of active bot players
   
   txtget.Text = txtget.Text & "-----------Server Info-----------" & vbCrLf
   txtget.Text = txtget.Text & ServerInfo(0) & vbCrLf
   txtget.Text = txtget.Text & ServerInfo(1) & vbCrLf
   txtget.Text = txtget.Text & ServerInfo(2) & vbCrLf
   txtget.Text = txtget.Text & ServerInfo(3) & vbCrLf
   txtget.Text = txtget.Text & ServerInfo(4) & vbCrLf
   txtget.Text = txtget.Text & ServerInfo(5) & vbCrLf
   txtget.Text = txtget.Text & ServerInfo(6) & vbCrLf
End Sub
 
Now I need some help with TCP. The new Rcon protocol for SOURCE uses a tcp/ip stream instead of UDP. I think I have a general understanding of how the packet works (See Here For Protocol Details)

Can anyone whip up some code that connects to the server and auth packet? This would be of immense help. Even if you can just give pointers on how to connect with TCP etc. Cause everytime I connect to the server and try and send an auth packet with .senddata I get a "protocol or connection error in my current state".

Thanks.
 
Hiya

This c# example will connect to a Hl2.net Beef.co.uk server and return back the string of details you require.

It's rough but should give you and idea btw. it uses UDP

FluffyERug.

using System;
using System.Net;
using System.Text;

namespace Connect
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
// server 82.136.36.13:27015

// Create a udp client
System.Net.Sockets.UdpClient t;
t = new System.Net.Sockets.UdpClient();

// try to connect to source server
t.Connect("82.136.36.13",27015);

// Define query
byte [] byteBuffer = {0xFF,0xFF,0xFF,0xFF,0x55};

// send query to server
t.Send(byteBuffer,byteBuffer.Length);

// Create endpoint - listen for a reply
// it will halt here until reply is received
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

// receive reply
byte[] receiveBytes = t.Receive(ref RemoteIpEndPoint);

// convert to string and display
// will show a load of crap but it has all the details of the server
// go to http://dev.kquery.com/index.php?article=46 for an explaination
// of the server reply.
string returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine(returnData);

// close the client
t.Close();
}
}
}
 
screw pseudo code to hell. it is worthless!
I have been programming for 8 years! C++ mainly
DIE pseudo code! DIE!
 
we're talking about placebo code, dude.. it ROCKS!! ....so get with it. :rolleyes:
 
HL2-2004NOV08 said:
screw pseudo code to hell. it is worthless!
I have been programming for 8 years! C++ mainly
DIE pseudo code! DIE!

Well that certainly was thought provoking and insightful... O.o
 
has anyone had success with getting player info? i'm coding a query class in php and i can get player names, but no information as to frags, ping, time connected, etc .. just player names.

i'm just wondering if it is me error, or maybe it can't be done yet.
 
Back
Top