Internet Pong Protocol
Tom Anderson suggested to a friend that they write (and play) a networked pong game (you know, the ancient ping-pong game). The obvious starting point is definition of a protocol for communication between the players; hence, the Internet Pong Protocol.
Game model
The game universe consists of a rectangular table, a ball and two paddles. The table has defined dimensions, the ball has defined position and velocity, and the paddles have defined positions. The table has four edges: two 'sides' and two 'ends'; the paddles are located at the ends.
When the ball strikes a side of the table, it bounces off. When the ball strikes a paddle, it bounces off. When the ball strikes an end, it falls off the table, and the player at the other end scores.
All coordinates are measured on an integer grid, whose origin is at the top left corner of the table; the X axis runs parallel to the sides, and the Y axis parallel to the ends. The player at the end with X = 0 is the left player, the player at the other end is the right player. Coordinate values never exceed 32767 (2^32 - 1).
Protocol context
This is a client-server protocol. A server manages the game, carries out the physics, etc, and a client interacts with the user. This protocol connects client and server; two such connections will be required per two-player game, one from the server to each player.
Connection state
When the connection is first opened, it is in the opening state. The client then logs in, and the connection moves to the open state. The client can then become involved in a game, in which case the connection moves to the ready state. When the game starts, the connection moves to the playing state. The connection can move from ready or playing back to open if the client or server aborts a game.
Elementary protocol format
IPP is a binary protocol. It consists of a stream of messages. Each message consists of a message-type byte, a length byte, and a series of data bytes, equal in number to the length byte.
All numbers transmitted are in unsigned or two's-complement signed format, in network byte order. All strings are in UTF8? (of which ASCII is a safe subset) and are not null-terminated (if necessary, a length byte is prepended).
Messages
In this section, messages are defined in list items, with the format "name <message-type number, in hex>: description; data format". In general, client messages have the high bit clear, and server messages have the high bit set.
Most messages may only be sent in a particular connection state; it is a protocol error to send a message in the wrong state.
General
- noop <00>: sent to keep the connection alive; data should be empty but could be anything.
- close <FF>: closes the connection, possibly in response to a protocol error; data is a string describing the reason for closure.
Messages permitted in the opening state
- login <01>: when sent in the opening state, logs the user in, and is a protocol error at any other time; data is a string containing the user's nickname.
- login-response <81>: sent in response to a login message; if the login is successful, the data is empty, and if not, is a string indicating why not. Transmission of a successful login-response indicates that the connection is now in the open state.
Messages permitted in the open state
- create-game <02>: creates a new game; the data should be: a two-byte unsigned integer specifying the table length (on the X axis), a two-byte unsigned integer specifying the table width (on the Y axis), a one-byte unsigned integer specifying the target score, and a string (occupying the rest of the data) describing the game, which may be empty.
- create-game-response <82>: acknowledges creation of a game; if the game is created, the data is empty, and the connection moves to the reaady state, else the data contains a string indicating what went wrong, and the connection remains in the open state.
- list-games <03>: requests a list of the available games; no data is sent.
- games <83>: indicates that a sequence of game-info messages about the games available is about to be sent; the data is a four-byte integer specifying the number of available games.
- game-info <84>: gives information about a game; data is a string, preceded by a length byte, giving the name of the offering player, followed by the data sent in the create-game message.
- join-game <05>: asks to join a game; the data is the name of the offering player.
- join-game-response <85>: acknowledges the request to join a game; if the data is empty, the game is joined and the connection moves to the ready state, else the data is a message indicating why the game could not be joined.
need to describe the game initiation process in the model section
need to say that the initiating player is the left player
need to tidy up states in request-response situations to rule out multiple sequential requests
Messages permitted in the ready state
- request-bot <06>: asks for a bot to play against; data is a one-byte unsigned integer indicating the toughness of the bot, with 100 equivalent to a normal human player. If a bot is provided, the server proceeds as if a normal player had joined the game.
- leave-game <07>: leaves the game; no data is sent. The connection returns to the open state.
- set <88>: sent by the server to a ready player to enquire if they are ready to play; data is the name of the opponent. Clients should respond with a 'go' message.
- go <08>: sent by a client to indicate that they are ready to go; no data is needed. This message may only be sent in response to a 'set' message, and when sent, moves the connection into the 'playing' state.
Messages permitted in the playing state
- move <09>: moves the paddle; data is a two-byte unsigned integer indicating the amount of movement on the Y-axis.
- world <89>: indicates the state of the world; data is a pair of two-byte unsigned integers, indicating the positions of the paddles of the left and right players, respectively, followed by another pair giving the X and Y coordinates of the ball
- score <8A>: indicates that the ball has crossed an end; data is three one-byte unsigned integers, where the first says who has scored (80 for left, 01 for right - geddit?), and the second and third are the scores of the left and right players, respectively. Note that the ball may well reset to the middle of the table after this, but it might not.
- retire <0B>: sent by a player to leave the game; no data is needed.
- game-over <8B>: indicates that the game is over; data is three unsigned one-byte integers, where the first says who won (80 for left, 01 for right) and the other two are the final scores of the left and right players, respectively. After this, the connection returns to the open state.
Binding to transport protocol
At present, IPP is only bound to TCP, although it would be trivial to adapt this to other reliable ordered stream protocols, or to reliable ordered datagram protocols.
IPP may be used over TCP, in which case port 0x7067 (28775 in denary, "pg" as ASCII characters) should be used. Messages are simply packed into the data stream in order. Implementations should flush the stream after each message, or after the last message in a series.
Category Geekery