Port of Ventrilo status protocol

VentriloTwo weeks ago I spent an entire day with Remco (aka Divinity), a friend of mine for another session of Freaky Twelve Hours (12 hours coding by a pair of nerds. Yep, that’s freaky allright). We set our sights to porting the UDP status protocol for Ventrilo servers and build a Atlas enabled control to show the status. We succeeded in the first. The source code is available below.

Ventrilo is a free product for Voice over IP communication. It’s similar to Skype, but different in the sense that you need to connect to a server who’s address you must know. Everyone with a permanent Internet connection can host a Ventrilo server. Another popular peer is TeamSpeak.

Ventrilo has been around for quite a while now. Up until version 2.1.2 the number of clients that are allowed to connect to a server was unlimited. Newer versions are limited to 8 concurrent users. This is the main reason that the older version is very popular amongst gamers: good codecs to offer a good quality/bandwidth ratio and a free and unlimited client/server combination.

Like many gaming related servers, a Ventrilo server can also be “ping”ed for the current status. You need to send an UDP packet to the server and you will receive one or more packets in return. These packets contain encrypted status information. After decrypting you know the characteristics of the server, such as the codec used, maximum number of clients, the channels and the clients that are connected.

Luigi Auriemma had already cracked the encryption/decryption algorithm of Ventrilo. You can find a lot of reverse engineered protocols at his site, amongst which the Ventrilo UDP status protocol. The implementation he has is in C. Remco and I wanted to create a C# version, and extend it to have a little domain model for the server, its channels and clients. You can look at our one day effort (with some documentation and refactoring afterwards) at the end. We didn’t get around to do the Atlas control yet, but a simple user control is included.

I do want to show you a little piece of code that Remco produced during that day. The header of the UDP packet that are sent to the server contain a header, that consists of 10 ulong values. We (and Luigi’s implementation) used a struct VentriloHeaderData to work with the individual ushorts. Right before sending we needed to convert the struct to a byte array, and vice versa during receival. Here’s what Remco used:

public static VentriloHeaderData FromByteArray(byte[] data)

{

  GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);

  IntPtr ptr = handle.AddrOfPinnedObject();

  VentriloHeaderData headerData = (VentriloHeaderData)Marshal.PtrToStructure(ptr, typeof(VentriloHeaderData));

  if (handle.IsAllocated)

  {

    handle.Free();

  }

  return headerData;

}

public byte[] ToByteArray()

{

  byte[] rawData = new byte[Marshal.SizeOf(typeof(VentriloHeaderData))];

  GCHandle handle = GCHandle.Alloc(rawData, GCHandleType.Pinned);

  IntPtr ptr = handle.AddrOfPinnedObject();

  Marshal.StructureToPtr(this, ptr, true);

  if (handle.IsAllocated)

  {

    handle.Free();

  }

  return rawData;

}

The byte layout of the struct is bitblitted onto a byte[] and the other way around. This will only works if you have fixed size value fields inside of your struct. And, no unsafe keyword used! Fine piece of refrigerator code if you ask me. Thanks for the nice programming day, Remco.

File Attachment: Ventrilo.zip (3013 KB)

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s