Internal XBlast network reference

original xbcomm.txt

Low-level socket handling

The low-level socket routines are declared in socket.h and contain routines to start/cleanup socket management, create/destroy XBSocket structures, access socket data, address creation, registration for select and the usual BSD calls to configure socket operation. Finally, socket.h declares the network interface detection routines.

The windows implementation of these declarations is done in w32_socket.c, requiring Winsock 2. The sockets are stored in a static map; via the register routines the system is told which socket events it has to report, which it then does by raising a MSG_XBLAST_SELECT event that is caught in w32_event.c.

The unix/linux implementation is done in x11_socket.c. Socket events are handled by fd_set's. By using the register routines, the read and write fd_sets are set accordingly and then used in the select call in SelectSockets, which is part of the main xblast event loop. In contrast to the windows implementation, x11_socket.c also registers x11, sound and joystick events.


Medium-level socket handling

Medium-level socket routines are declared and defined in net_socket.c/h. This includes the generation of a tcp socket connected to a address, a tcp listen socket on a given local port, a tcp socket accepted from a tcp listen socket, a udp socket bound to a given local port, "connecting" a bound udp socket to a given address and a socket close routine, which closes the socket and frees the corresponding XBSocket structure.

Normally udp sockets bound to any port (=0) and tcp connection sockets are assigned a port number by the system. If USER_MINPORT/USER_MAXPORT are defined at compile time, the port is chosen in the defined range, if possible. The latter option is new since late .23 cvs.


  • High-level socket handling: XBComm structures
  • The XBComm structure declared and defined in com.c/h stores a XBSocket structure plus its event handlers for readability writeability and deletion. Whenever a XBComm is created, it will be stored in linked list in com_base.c. Now, when readability or writeability is detected, either through a system event in the windows implementation or by the select() call in unix/linux implementation, the shared event handlers CommReadable and CommWriteable are called for the socket triggering the event. The XBComm structure containing the socket will be found, after which the appropriate XBComm read/write handler can be called. Should the handler return with an error value, a call to the XBComm delete handler will follow, which is supposed to clean up the XBComm structure and remove it from the XBComm list.


  • XBCommListen
  • TCP listen server - accepts tcp connections of a given type. Implemented in com_listen.c/h, used by server and central to receive connections.

    To initialize the XBCommListen structure, a port and the type (server, central) have to be provided for CommCreateListen(). The init routine then tries to establish a basic XBComm structure around a tcp listen socket, which is then stored with type and cleared shutdown flag in the XBCommListen structure. The socket is constantly registered for reading and unregistered for writing.

    To actively remove the structure, a user can call CommDeleteListen(), which sets the shutdown flag so that the subsequently called delete handler will report an expected shutdown. A shutdown is also caused when either the read or write handler return an error, in which case the shutdown flag will still be cleared. Currently, read/write handler never return an error, though.

    The read handler of the XBComm generates a XBCommStream structure of the provided type, accept'ed from the receiving socket. The Server type XBCommStream structure is the XBCommToClient structure, the Central type structure is the XBCommFromCentral structure. It always returns OK.

    The write handler of the XBComm just returns OK, no writing on the socket is needed.

    The delete handler of the basic XBComm first removes the basic XBComm structure from the XBComm list. The other specific XBCommListen data need no clean up. Upon deletion, Server/Central are notified of the close and are passed the current shutdown flag, to enable them to deal with unexpected shutdowns.


  • XBCommStream
  • general TCP connection. Implemented in com_stream.c/h.

    To initialize the XBCommStream structure, a connected tcp socket is required for Stream_CommInit() as well handlers for parsing, events and deletion. A basic XBComm structure will be established around the socket, using the provided delete handler. In addition, a send and receive queue are allocated. The prepFinish flag is cleared.

    The structure is removed by a call to Stream_CommFinish, which will remove the XBComm and the queues and send the CLOSE event to the application.

    By setting the prepFinish flag, the socket will be shutdown for writing when the queue is emptied and once EOF is received, the XBCommStream is automatically removed. It is assumed that higher level-data has been removed prior to the setting the flag.

    The read handler will first try to read the data and push them onto the rcv queue.

    The write handler will try to write a single queued telegram from the rcv queue.

    The provided delete handler should free the XBCommStream structure and all specific data of the XBComm implementation.

    The job of the event handler is to pass the stream events described above to the next higher-level of the application.

    The parse handler should analyze a single received telegram. Valid telegrams are then acted upon. Parse errors will trigger deletion.


  • XBCommToClient
  • server-side TCP connection to client. Imlemented in com_to_client.c/h, used by server to negotiate with client.

    This structure is initialized by calling S2C_CreateComm. A free serial is chosen which is then stored as local data next to XBCommStream structure around the tcp socket connected to the client.

    The structure is removed automatically by an error event in the basic XBComm. The removal can actively be initiated by using S2C_SendDisconnect which will queue a disconnect sequence to the client, free the client slot, shutdown the socket for writing once the sequence is sent and then wait for an eof to finish the removal of the XBCommStream substructure.

    The parse handler passes any parse errors to the server code which decides if the error is ignored or should result in the deletion of the communication.

    The event handler transforms the stream events to appropriate server constants.

    The delete handler frees the serial for the next client connection and removes the XBCommToClient structure. This will trigger the event handler with the CLOSE stream event.


  • XBCommToServer
  • client-side TCP connection to server. Implemented in com_to_server.c/h, used by client to negotiate with server.

    This structure is initialized by calling C2S_CreateComm. It merely contains a XBCommStream structure around a tcp socket that will be connected to the server.

    The structure is removed automatically by an error event in the basic XBComm. To actively remove the structure, the generic call CommDelete suffices which will trigger the delete handler.

    The parse handler passes any parse errors to the client code which decides if the error is ignored or should result in the deletion of the communication.

    The event handler transforms the stream events to appropriate client constants.

    The delete handler removes the XBCommToClient structure. This will trigger the event handler with the CLOSE stream event, notifying the client code.


  • XBCommToCentral
  • user-side TCP connection to central. Implemented in com_to_central.c/h, used by server to send scores to central, used by client to get rankings and register players from central.

    This structure is initialized by calling X2C_CreateComm. It merely contains a XBCommStream structure around a tcp socket that will be connected to central.

    The structure is removed automatically by an error event in the basic XBComm. To actively remove the structure, the generic call CommDelete suffices which will trigger the delete handler.

    The parse handler will return an error for cot's which are not DataAvailable or DataNotAvailable.

    The event handler returns an error for i/o errors and eof, which will trigger the delete handler.

    The delete handler removes the XBCommToClient structure. This will trigger the event handler with the CLOSE stream event, notifying the user code.


  • XBCommFromCentral
  • central-side TCP connection to user. Implemented in com_from_central.c/h, used by central to send rankings and player id to client.

    This structure is initialized by calling C2X_CreateComm. A free serial is chosen which is then stored as local data next to a XBCommStream structure around the tcp socket connected to the user.

    The structure is removed automatically by an error event in the basic XBComm. The removal can actively be initiated by using X2C_SendDisconnect which will queue a disconnect sequence to the client, free the client slot, shutdown the socket for writing once the sequence is sent and then wait for an eof to finish the removal of the XBCommStream substructure.

    The parse handler will return a parse error for cot's other than Requestdata, SendData, Activate, Spontaneous, triggering the delete handler.

    The event handler returns an error for i/o errors and eof on the tcp socket, triggering the delete handler.

    The delete handler frees the serial for the next client connection and removes the XBCommToClient structure. This will trigger the event handler with the CLOSE stream event.


  • XBCommDgram
  • general UDP server/client for pings and player actions. Implemented in com_dgram.c/h, used as base by XBCommDgramServer, XBCommDGramClient.

    Initialization of XBCommDgram structure is done by calling Dgram_CommInit(). An established udp socket is required which is wrapped in basic XBComm structure, as well as handlers for pings, actions and events. Additional local data involve a local buffer which holds a single datagram to be written to the socket, as well as data about the connection status of the socket, ping time and frame data.

    The basic XBComm is assigned a read handler, which first checks the sender of a datagram with the hostname entry. If the hostname entry is NULL, any sender is allowed, otherwise the sender ip has to match exactly. If there is an exact match in the latter case, the udp socket is connected to the sender which will either trigger a XBDI_CONSUCC or XBDI_CONFAIL, depending on the outcome. The hostname is unset on success, so that subsequent datagrams are not checked for sender. The received data is then parsed:

    The delete handler of the basic XBComm removes the basic XBComm and the datagram and informs the application with XBDI_CLOSE.

    The write handler of the basic XBComm attempts to write the stored buffer. On failure, XBDI_WRITEERR is raised. Otherwise the buffer is cleared, the frame data and time of last send updated.

    The user ping handler should be able to deal with (id,time) pairs with (0,0) denoting a ping request.

    The user action handler has to accept a gametime and a packed array of player keys.

    The user information handler takes the XBCommDgram and the event as argument. A return of XBTrue indicates that the application wishes to shutdown the communication. The return value is ignored for certain purely informational events (FINISH, IGNORE, PARSED).

    The structure is closed up by a call to the delete handler which can be achieved by using CommDelete on the structure. This triggers a XBDI_CLOSE, so that higher level data can be cleaned up as well.


  • XBCommDgramClient
  • server-side UDP server/client for pings and player actions (com_dg_client.c/h, used by server to receive/send keys from/to client)

    The server initializes this structure by calling D2C_CreateComm, with client id, host name and the fixedUdp flag as parameter. A udp socket will be created on a local port determined by fixedUdp (if set, 16168+id, otherwise any port) and wrapped in a XBCommDgram. Moreover a polling function is installed in the GUI event loop which checks for timeouts on the udp sockets.

    The ping handler ignores ping times and calculates the current ping time for ping requests, which is passed to server.

    The action handler passes game time and action to server.

    The event handler passes some events to server (LOSS, CONFAIL, WRITEERR) and informs server for the FINISH event. The CLOSE event clears the client slot and removes the polling function.

    To remove the socket either D2C_Disconnect is called or an error is returned for some of the dgram events. In both case, the basic XBComm structure will be removed. That triggers a CLOSE that will clear the slot and and remove the poll, completely freeing the structure.


  • XBCommDgramServer
  • client-side UDP server/client for pings and player actions (com_dg_server.c/h, used by client to send/receive pings and keys to/from server)


  • XBCommBrowse
  • general UDP server/client for game information (com_browse.c/h)


  • XBCommQuery
  • client-side UDP client for game information, either from LAN or central (com_query.c/h, used by client to search for games)


  • XBCommReply
  • server-side UDP server for game information (com_reply.c/h, used by server to respond to LAN broadcasts from client)


  • XBCommNewGame
  • server-side UDP client for game information, to central (com_newgame.c/h, used by server to notify central of game)


  • XBCommCentral
  • central-side UDP server for game information (com_central.c/h, used by central to send game info to client)