Design Overview

Table of Contents
The GGZ server (ggzd)
Individual Game Servers
Config Utility
Key Subsystems
Data Structures

Warning

This chapter is horribly out of date. We will be fixing it soon

There are four parts which comprise the server side:

We will discuss each of these in turn, but first we'll look at the overall architecture.

Figure 1. Server Architecture

The GGZ server will handle incoming connections, manage the user database, and keep track of all of the games being played (referred to as game tables). Clients are always in direct communication with control.

Note that ggzd will not handle the specifics of how to play any particular game. That logic is contained in the individual game servers. It is expected (and hoped!) that game developers will write their own games servers for use with GGZ. GGZ will attempt to provide a simple framework for writing network games in which developers need not worry about connections or user logins or maintaining statistics. All of that will be done by GGZ. Game developers should only have to concern themselves with gameplay.

The third item is more loosely connected. We will provide some sort of run-time configuration utilities for GGZ, so the main server will not have to be restarted (or worse.. recompiled!) in order for various options to be changed. The first such utily is ggzduedit, with which the user database can be edited.

Some options may include:


The GGZ server (ggzd)

This is the main brain for the server side of GGZ. It handles client logins and new user registrations. It manages option negotiation with the clients, and launches new game sessions. It maintains a list of running game sessions and keeps a database of win/lose statistics for each user. It coordinates games, users, and databases, and is responsible for interacting with the client, the running games, and the config utility.

Several possible designs were being considered before settling on the current one. It is possible that as GGZ develops this design will change as well. Since ggzd must communicate with multiple parties (game tables, users, etc.) it was decided to use a multi-threaded concurrent server where each connection (be it user or game table) gets its own thread. This avoids the situation where ggzd is servicing a request and therefore cannot handle any incoming connections or other requests. Brent chose threads rather than forking child processes because threads have a smaller overhead and it is easier to share memory between threads than between processes.

Every time a new user connects, ggzd creates a new thread to handle all requests for that user. This thread is known as the player handler. If the user decides to launch a new game table, the player handler creates a thread to handle all requests from the game table. This new thread is known as the table handler. The table handler waits until enough players have joined the table and then forks a process, known as the game table process, in which to run the game server. (The reason game servers are not run within a thread is so that game developers not be required to worry about writing thread-safe code.)

During the course of the game, the player thread for each player acts as a liaison between the player and the game table, passing requests back and forth transparent to the player and the game server. When a player logs out, the player handler thread is destroyed.


Interactions between ggzd and running games

Quite a few game servers will be provided with GGZ, but it is hoped that others will write game modules, and either submit them for inclusion in the GGZ package, or maintain and distribute them separately. The following API describes how ggzd will interact with the game processes.

Note: All interaction is enclosed within the ggzdmod library. Game developers should use it (or any of its wrappers) so they don't have to deal with the protocol in use directly.

Four types of data are exchanged between ggzd and game servers:

  • chr: a 1-byte signed char

  • int: a 4-byte signed integer in network byte order

  • str: a multibyte null-terminated string preceded by its length (including null-termination) as an integer.

  • fd: a file descriptor passed via sendmsg() along with a single byte of dummy data

The following is a complete list of messages between the game module and the control section of the server. Again, I have chosen to intersperse game module requests with the corresponding control responses.

Please note: the following is not written stone, merely a list of ideas.
	REQ_GAME_LAUNCH
	int: number of seats at table
	sequence of
	int: seat assignment (-1 for OPEN, -2 for COMP, -3 RESV)
	str: name of player (if assignment >=0 or == RESV)
	fd:  file dscriptor of player (if assignment >= 0)
	RSP_GAME_LAUNCH
	chr: success flag (0 if OK, -1 if error)

	REQ_GAME_JOIN
	int: seat number
	str: name of player
	fd:  file dscriptor of player 
	RSP_GAME_JOIN
	chr: success flag (0 if OK, -1 if error)

	REQ_GAME_LEAVE
	str: name of player
	RSP_GAME_LEAVE
	chr: success flag (0 if OK, -1 if error)

	MSG_GAME_OVER
	int: number of statistics
	sequence of
	int: player index
	int: number of games won
	int: number of games lost

	MSG_LOG
	int: log level mask
	str: log message

	MSG_DBG
	int: debug level mask
	str: debug message
      


Interactions between ggzd and config utilities

Since the server runs non-interactively in the background, there needs to be some run-time configuration tools so that server options may be changed without restarting. Updates are either executed indirectly (e.g. when removing a player from the database), or explicitely (e.g. when changing some configuration parameters and sending a hangup signal to ggzd). The latter one will be steered by a configuration utily as well at some point.

Messages between ggzd and the config utilities might include:

  • Request available game types (loaded modules)

  • Add/Remove Game types

  • Remove users

  • Request list of active games

  • Clear Player statistics

  • Modify logging