Skip to content

Protocol

Eric Liu edited this page Sep 11, 2016 · 84 revisions

General Protocol Information

The diep.io client and server communicate by means of HTML5 Websockets, a low-overhead protocol that allows for two-way information exchange and "push notifications".

By "wrapping" the Javascript WebSocket send and onmessage methods, the provided Chrome extension can snoop on the connection (e.g. view and modify packets to/from the server) without worrying about encryption. A relevant code sample from the extension is as follows:

var wsInstances = new Set();
window.WebSocket.prototype.send = function(data) {
	if(!wsInstances.has(this)){
		console.log("New WebSocket Used:");
		console.log(this);
		wsInstances.add(this);
		
		// Snoop on incoming websocket traffic.
		var inst = this;
		var proxiedRecv = inst.onmessage;
		this.onmessage = function(event) {
			event = handleRecvData.call(this, event, proxiedRecv);
			return proxiedRecv.call(this, event);
		};
		console.log("Successfully hijacked onmessage handler.");
	}
	data = handleSendData.call(this, data);
	return proxiedSend.call(this, data);
};

Type Table

Note: Sizes are given in bytes and all multi-byte values are little-endian.

Name Size Description
uint8 1 Unsigned 8-bit int
uint16 2 Unsigned 16-bit int
uint32 4 Unsigned 32-bit int
int8 1 Signed 8-bit int
float32 4 Signed 4-bit float
float64 8 Signed 8-bit float
string ≥1 Null-terminated UTF-8 string

Handling Strings

To correctly decode the strings (which are encoded in UTF-8) represented as bytes, the following function can be used:

function decodeUTF8(bytes) {
	// From: https://gist.github.com/pascaldekloe/62546103a1576803dade9269ccf76330
	var s = '';
	var i = 0;
	while (i < bytes.length) {
		var c = bytes[i++];
		if (c > 127) {
			if (c > 191 && c < 224) {
				if (i >= bytes.length) throw 'UTF-8 decode: incomplete 2-byte sequence';
				c = (c & 31) << 6 | bytes[i] & 63;
			} else if (c > 223 && c < 240) {
				if (i + 1 >= bytes.length) throw 'UTF-8 decode: incomplete 3-byte sequence';
				c = (c & 15) << 12 | (bytes[i] & 63) << 6 | bytes[++i] & 63;
			} else if (c > 239 && c < 248) {
				if (i+2 >= bytes.length) throw 'UTF-8 decode: incomplete 4-byte sequence';
				c = (c & 7) << 18 | (bytes[i] & 63) << 12 | (bytes[++i] & 63) << 6 | bytes[++i] & 63;
			} else throw 'UTF-8 decode: unknown multibyte start 0x' + c.toString(16) + ' at index ' + (i - 1);
			++i;
		}

		if (c <= 0xffff) s += String.fromCharCode(c);
		else if (c <= 0x10ffff) {
			c -= 0x10000;
			s += String.fromCharCode(c >> 10 | 0xd800)
			s += String.fromCharCode(c & 0x3FF | 0xdc00)
		} else throw 'UTF-8 decode: code point 0x' + c.toString(16) + ' exceeds UTF-16 reach';
	}
	return s;
}

Client-to-Server Communication Protocol

Diep.io Packet Logs (Client to Server)

The client always sends the server a Javascript Int8Array (an array of 8-bit signed integers). These packets' functionality vary by header (first number) and by length.

All the following packets are organized by category and header value.

Client Info (0x01)

This packet contains information about the player.

Offset Type Description
+0 uint8 Packet header
+1...3 int8[3] Cursor X coordinate relative to map
+4 uint8 ???
+5...7 int8[3] Cursor Y coordinate relative to map
+8 uint8 ???
+9 uint8 Tank movement and firing

Bullet Packet

An array of at least size 9 that has the last number 1, for example [1, -116, -5, -32, 15, -116, -65, -63, 6, 1]. If auto-fire is turned on, all following packets will have last number 1 (unless you are also moving).

Note that all cursor information is encoded as normal in the other fields of the packet.

Movement Packet

An array of at least size 9 with a last number greater than 1, for example [1, -116, -1, -128, 5, -116, -69, -95, 9, 4]. Last byte corresponds to the keys that are currently pressed, and the corresponding bit is set by a logical OR operation. The five possible masks are as follows:

Key Code (byte) Code (binary)
Mouse left button 0x01 0b00000001
Up Arrow 0x02 0b00000010
Left Arrow 0x04 0b00000100
Down Arrow 0x08 0b00001000
Right Arrow 0x10 0b00010000

Some examples of last numbers and their corresponding directions are as follows:

Last Number Direction
2 North
4 West
6 Northwest
8 South
12 Southwest
16 East
18 Northeast
24 Southeast

Name Packet (0x02)

An array of variable size, where the first number is 2, contains the name you choose encoded in UTF-8 followed by a \0. For example, if I choose the name "bob", my browser would send the packet [2, 98, 111, 98, 0].

Offset Type Description
+0 uint8 Packet header
+1 string Your chosen name

Upgrade Packets (0x03 or 0x04)

An array of size 2 with header value 3 is sent when you upgrade a parameter (for example, movement speed) and takes the form [3, X]. For actual tank upgrades (e.g. to Twin, Tri-Angle, etc.), a packet with header 4 of the form [4, Y] is sent.

Offset Type Description
+0 uint8 Packet header
+1 uint8 X or Y value

More information on parameter upgrade packets, including all X and Y-values as well as their corresponding parameters or tanks, is available on the wiki page entitled "Upgrade Packets".

Heartbeat (0x05)

An array of size 1 will simply be an array of size 1 containing only the number 5 (e.g. [5]). These appear to be a heartbeat/keep-alive message and do not contain any other information.

Offset Type Description
+0 uint8 Packet header

Other packets (0x00)

  • An array of size 6 seems to be sent whenever the mouse cursor starts moving over the spawn screen (e.g. when it says "this is the tale of...").

  • An array of size 7 also is only sent when viewing the spawn screen, but this one is sent when the cursor is moving (as opposed to starting to move).

  • An array of size 8 has an unknown purpose, but we have observed length-8 packets (just not sure what they do yet).

  • An array of size 9 or 10 is only sent when you are either in the game, or observing it, and appears to contain information about your cursor location and angle (e.g. cursor 120 degrees from the center at point AxB, etc.)

Server-to-Client Communication Protocol

Server to client communication samples

The server sends the client an ArrayBuffer, with the difference being that these appear to have random length, but do somehow communicate the locations/types of other tanks/shapes/etc. Note that we have not deciphered much of the server-to-client protocol yet.

We have discovered that that the first 2 8-bit categories appear to be a header for the message:

  • The first 8-bit sequence contains either a 0 or a 2. If it contains a 0, it is a "regular" packet, and if it contains 2, it appears to be a special packet.

  • The second 8-bit sequence is used as a "counter" if the first number is 0 (you can observe this in the image above). If the first number is 2, it contains information about the current game, such as the leaderboard (read below).

Unfortunately, server-to-client communication remains largely undeciphered.

In the client JS code (filename: d.js), the (prettified) section of code responsible for handling server communications is:

b.onmessage = function(a) {
	a = new Uint8Array(a.data);
	var c = D(a.length);
	ka(a, c);
	b.events.push([1, c, a.length]);
	va()
}

Interestingly enough, the b.events.push([1, c, a.length]) line always appears to push [1, INTEGER1, INTEGER2]. INTEGER1 is computed by the D(a.length) method that does some complicated number crunching and returns an integer.

The ka(a, c) method appears to simply copy the values in array a to array c, and va() appears to be a handler to redraw or update the interface.

Server Info (0x00)

This packet may contain information about the server.

Offset Value Type Description
+0 uint8 Packet Header
+1 uint8[2-3] Server Uptime
??? ??? ???

??? (0x02)

This packet has an unknown purpose.

Server Location (0x04)

This packet contains a message about the server (most likely server name). It cannot be detected by our script.

Offset Type Description
+0 uint8 Packet header
+1 string Server info

Heartbeat (0x05)

An array of size 1 will simply be an array of size 1 containing only the number 5 (e.g. [5]). These appear to be a heartbeat/keep-alive message and do not contain any other information.

Offset Type Description
+0 uint8 Packet header

Leaderboard Packet (0x00 or 0x02)

This section has been moved to Server Packets