Files
Cesarus85--ringfall-mjolnir-vr/source/networking/network_server_message_handler.c
T

2299 lines
64 KiB
C

/*
NETWORK_SERVER_MESSAGE_HANDLER.C
symbols in this file:
0011E890 0090:
_code_0011e890 (0000)
0011E920 00a0:
_code_0011e920 (0000)
0011E9C0 0090:
_code_0011e9c0 (0000)
0011EA50 0090:
_code_0011ea50 (0000)
0011EAE0 00a0:
_code_0011eae0 (0000)
0011EB80 00a0:
_code_0011eb80 (0000)
0011EC20 0020:
_code_0011ec20 (0000)
0011EC40 0040:
_network_game_server_send_message_to_machine (0000)
0011EC80 0110:
_network_game_server_send_message_to_all_machines (0000)
0011ED90 0090:
_network_game_server_send_player_joined_info_ingame (0000)
0011EE20 00c0:
_network_game_server_send_game_data_pregame (0000)
0011EEE0 0240:
_code_0011eee0 (0000)
0011F120 00c0:
_code_0011f120 (0000)
0011F1E0 03f0:
_code_0011f1e0 (0000)
0011F5D0 00c0:
_code_0011f5d0 (0000)
0011F690 00c0:
_code_0011f690 (0000)
0011F750 00e0:
_code_0011f750 (0000)
0011F830 00d0:
_code_0011f830 (0000)
0011F900 00d0:
_code_0011f900 (0000)
0011F9D0 00f0:
_code_0011f9d0 (0000)
0011FAC0 0310:
_network_game_server_handle_datagram (0000)
0011FDD0 0400:
_network_game_server_handle_client_message (0000)
00286F00 005a:
??_C@_0FK@KMJJAKFL@failed?5to?5handle?5a?5message_clien@ (0000)
00286F60 0043:
??_C@_0ED@BONJCMOD@server?5failed?5to?5decode?5a?5messag@ (0000)
00286FA8 0065:
??_C@_0GF@BGPKJGEH@failed?5to?5handle?5a?5message_type_@ (0000)
00287010 004e:
??_C@_0EO@HMJBCLNP@server?5failed?5to?5decode?5a?5messag@ (0000)
00287060 0056:
??_C@_0FG@LPGCCINN@failed?5to?5handle?5a?5message_clien@ (0000)
002870B8 0037:
??_C@_0DH@MMOKOPCN@server?5failed?5to?5decode?5a?5messag@ (0000)
002870F0 005e:
??_C@_0FO@NHCIMMDF@failed?5to?5handle?5a?5message_clien@ (0000)
00287150 004a:
??_C@_0EK@ONPDOJKK@server?5failed?5to?5decode?5a?5messag@ (0000)
002871A0 0068:
??_C@_0GI@DLKCJODI@failed?5to?5handle?5a?5message_clien@ (0000)
00287208 004f:
??_C@_0EP@DAOANLDM@server?5failed?5to?5decode?5a?5messag@ (0000)
00287258 0033:
??_C@_0DD@FJKDMFNA@server?5failed?5to?5remove?5a?5networ@ (0000)
00287290 005b:
??_C@_0FL@NDHDFCNK@failed?5to?5handle?5a?5message_clien@ (0000)
002872F0 0045:
??_C@_0EF@MJLJMBIP@network_game_server_switch_machi@ (0000)
00287338 0059:
??_C@_0FJ@PEAAKLFN@network_game_server_write?$CI?$CJ?5fail@ (0000)
00287394 0027:
??_C@_0CH@EEEHHOGO@message_length?$DM?$DNsizeof?$CImessage_b@ (0000)
002873BC 0012:
??_C@_0BC@FDHBPMJE@server?5?$CG?$CG?5message?$AA@ (0000)
002873D0 003b:
??_C@_0DL@ICDCPLFI@c?3?2halo?2SOURCE?2networking?2networ@ (0000)
0028740C 003c:
??_C@_0DM@MOMFHJIG@failed?5to?5create?5a?5message_serve@ (0000)
00287448 0072:
??_C@_0HC@FGJDKKLC@network_game_server_send_message@ (0000)
002874C0 0058:
??_C@_0FI@LBJCENJB@failed?5to?5handle?5a?5message_serve@ (0000)
00287518 003f:
??_C@_0DP@CCCLFFGC@failed?5to?5create?5a?5message_serve@ (0000)
00287558 004b:
??_C@_0EL@NFHCHAEG@failed?5to?5send?5message_server_ga@ (0000)
002875A4 0039:
??_C@_0DJ@PCNJDMDI@failed?5to?5create?5a?5message_serve@ (0000)
002875E0 0054:
??_C@_0FE@HMKEDIDF@network_game_server_write?$CI?$CJ?5fail@ (0000)
00287634 002b:
??_C@_0CL@FOJJMNII@server?5?$CG?$CG?5source_address?5?$CG?$CG?5clie@ (0000)
00287660 002f:
??_C@_0CP@JCCANCCC@failed?5to?5create?5a?5message_serve@ (0000)
00287690 0043:
??_C@_0ED@LGNNJLKJ@network_game_server_write?$CI?$CJ?5fail@ (0000)
002876D8 0042:
??_C@_0EC@MGMKMMHI@server?5failed?5to?5decode?5a?5messag@ (0000)
0028771C 003b:
??_C@_0DL@JAHACCAG@failed?5to?5create?5a?5message_serve@ (0000)
00287758 0043:
??_C@_0ED@PLLDKIEI@client?5machine?5?8?$CFs?8?5?$EA?$CFs?5tried?5to@ (0000)
002877A0 0041:
??_C@_0EB@ONCPMINI@client?5machine?5?8?$CFs?8?5?$EA?$CFs?5tried?5to@ (0000)
002877E8 0043:
??_C@_0ED@DKNIPKFL@network_game_server_write?$CI?$CJ?5fail@ (0000)
00287830 0044:
??_C@_0EE@MGEHHOCB@server?5failed?5to?5accept?5valid?5cl@ (0000)
00287878 0075:
??_C@_0HF@HFOMEJBD@network_game_server_send_game_da@ (0000)
002878F0 0039:
??_C@_0DJ@CKOCAMEF@sent?5_message_type_server_machin@ (0000)
00287930 0064:
??_C@_0GE@MLODGBHN@network_game_server_write?$CI?$CJ?5fail@ (0000)
00287994 0029:
??_C@_0CJ@EPMEBAJK@network_machine_is_valid?$CIclient_@ (0000)
002879C0 0040:
??_C@_0EA@HPKAIHHK@server?5refused?5client?5?8?$CFs?8?5becau@ (0000)
00287A00 000d:
??_C@_0N@MPMCKMFC@d?3?2hosts?4txt?$AA@ (0000)
00287A10 002d:
??_C@_0CN@LBHCOBFK@ignoring?5redundant?5join?5request?5@ (0000)
00287A40 0062:
??_C@_0GC@IBIEHGFG@failed?5to?5handle?5a?5message_clien@ (0000)
00287AA8 004b:
??_C@_0EL@BFEPJEFO@server?5failed?5to?5decode?5a?5messag@ (0000)
00287AF8 0070:
??_C@_0HA@DHHGOECG@server?5failed?5to?5add?5a?5network?5p@ (0000)
00287B68 0072:
??_C@_0HC@LODCIJJJ@server?5failed?5to?5send?5pregame?5ga@ (0000)
00287BE0 0065:
??_C@_0GF@EKICMCEL@failed?5to?5handle?5a?5message_clien@ (0000)
00287C48 004e:
??_C@_0EO@JJCAGDLG@server?5failed?5to?5decode?5a?5messag@ (0000)
00287C98 0076:
??_C@_0HG@LNIKCCLC@server?5failed?5to?5remove?5a?5networ@ (0000)
00287D10 0075:
??_C@_0HF@KPAHGLDA@server?5failed?5to?5send?5pregame?5ga@ (0000)
00287D88 0058:
??_C@_0FI@HEMIANGD@failed?5to?5handle?5a?5message_clien@ (0000)
00287DE0 0041:
??_C@_0EB@EACNFEBF@server?5failed?5to?5decode?5a?5messag@ (0000)
00287E28 0075:
??_C@_0HF@CJBDOMOO@network_game_server_adjust_machi@ (0000)
00287EA0 0068:
??_C@_0GI@IHEHKNKB@server?5failed?5to?5send?5pregame?5ga@ (0000)
00287F08 0036:
??_C@_0DG@ECGMMKBK@server?5received?5machine?5settings@ (0000)
00287F40 005f:
??_C@_0FP@BKMGBKPC@failed?5to?5handle?5a?5message_clien@ (0000)
00287FA0 0048:
??_C@_0EI@NDLJFMCJ@server?5failed?5to?5decode?5a?5messag@ (0000)
00287FE8 006b:
??_C@_0GL@MGDAOAGD@network_game_update_player?$CI?$CJ?5fai@ (0000)
00288058 006f:
??_C@_0GP@IGEJNGEG@server?5failed?5to?5send?5pregame?5ga@ (0000)
002880C8 0028:
??_C@_0CI@NAMNDBJF@server?5received?5updated?5player?5s@ (0000)
002880F0 006a:
??_C@_0GK@PIEMGCFK@failed?5to?5handle?5a?5message_clien@ (0000)
00288160 004b:
??_C@_0EL@FGPNNAHJ@server?5failed?5to?5decode?5a?5messag@ (0000)
002881B0 0080:
??_C@_0IA@GMAELFDC@network_game_server_remove_machi@ (0000)
00288230 0072:
??_C@_0HC@JPOEIOK@server?5failed?5to?5send?5pregame?5ga@ (0000)
002882A8 0061:
??_C@_0GB@BICEKEIA@failed?5to?5handle?5a?5message_clien@ (0000)
00288310 004d:
??_C@_0EN@FBHIPCPE@server?5failed?5to?5decode?5a?5messag@ (0000)
00288360 003a:
??_C@_0DK@HGNCDCGJ@server?5received?5a?5malformed?1dama@ (0000)
002883A0 0047:
??_C@_0EH@HDCJJGCF@server?5received?5low?9level?5error?5@ (0000)
002883E8 0046:
??_C@_0EG@NGIBKKFK@server?5received?5a?5bad?5message?5ty@ (0000)
00288430 003f:
??_C@_0DP@DJCDAEKP@failed?5to?5decode?5a?5message_clien@ (0000)
00288470 003e:
??_C@_0DO@EMEMPFEN@server?5failed?5to?5advertise?5game?5@ (0000)
002884B0 002e:
??_C@_0CO@IFNMPAGP@failed?5to?5decode?5a?5message_clien@ (0000)
002884E0 0026:
??_C@_0CG@PBGOHBCL@server?5failed?5to?5handle?5a?5client@ (0000)
00288508 0042:
??_C@_0EC@OIEIALKJ@ignoring?5a?5message_client_game_u@ (0000)
00288550 0062:
??_C@_0GC@EMAKPFP@failed?5to?5handle?5a?5message_clien@ (0000)
002885B4 0035:
??_C@_0DF@NPLDDCCG@failed?5to?5decode?5a?5message_clien@ (0000)
002885F0 0046:
??_C@_0EG@DEJFBBLL@server?5received?5datagram?5with?5an@ (0000)
00288638 004c:
??_C@_0EM@NPFBANHI@server?5received?5a?5datagram?5with?5@ (0000)
00288684 003c:
??_C@_0DM@HFFMPMPG@server?5received?5a?5datagram?5with?5@ (0000)
002886C0 0081:
??_C@_0IB@OPFACLKA@server?5?$CG?$CG?5message?5?$CG?$CG?5source_addr@ (0000)
00288744 003a:
??_C@_0DK@NEANDKEL@server?5received?5a?5malformed?1dama@ (0000)
00288780 0047:
??_C@_0EH@PCKBOEPO@server?5received?5low?9level?5error?5@ (0000)
002887C8 0046:
??_C@_0EG@GPPJDFA@server?5received?5a?5bad?5message?5ty@ (0000)
00288810 003e:
??_C@_0DO@LBJNGIAJ@bad?5or?5inappropriate?5packet?5type@ (0000)
00288850 004e:
??_C@_0EO@OPDINPHL@network_game_server_handle_messa@ (0000)
002888A0 0045:
??_C@_0EF@FHPBCOMI@network_game_server_handle_messa@ (0000)
002888E8 0052:
??_C@_0FC@HBMALEKE@network_game_server_handle_messa@ (0000)
00288940 0050:
??_C@_0FA@OHGBEJHJ@network_game_server_handle_messa@ (0000)
00288990 004d:
??_C@_0EN@IOBKAAMM@network_game_server_handle_messa@ (0000)
002889E0 003a:
??_C@_0DK@DJBGFGMF@network_game_server_handle_messa@ (0000)
00288A20 0046:
??_C@_0EG@KNLLMEKN@network_game_server_handle_messa@ (0000)
00288A68 004b:
??_C@_0EL@IBNDPBLB@network_game_server_handle_messa@ (0000)
00288AB8 0044:
??_C@_0EE@KLMGADOJ@network_game_server_handle_messa@ (0000)
00288B00 0051:
??_C@_0FB@PPCOJHGP@network_game_server_handle_messa@ (0000)
00288B58 004e:
??_C@_0EO@EEEMKLCF@network_game_server_handle_messa@ (0000)
00288BA8 0045:
??_C@_0EF@FHABLMKA@network_game_server_handle_messa@ (0000)
00288BF0 0048:
??_C@_0EI@INBBOEGP@an?5un?9validated?5client?5sent?5some@ (0000)
00288C38 0044:
??_C@_0EE@EPDDKPMF@server?5received?5a?5client?5message@ (0000)
00288C7C 0032:
??_C@_0DC@DAGHEIED@server?5received?5client?5message?5w@ (0000)
00288CB0 0054:
??_C@_0FE@BPJHKGCF@server?5?$CG?$CG?5machine?5?$CG?$CG?5message?5?$CG?$CG?5@ (0000)
*/
/* ---------- headers */
#include "cseries.h"
#include "bungie_net/common/message_header.h"
#include "bungie_net/network/transport.h"
#include "bungie_net/network/transport_endpoint_winsock.h"
#include "game/game.h"
#include "game/game_engine.h"
#include "game/players.h"
#include "networking/network_connection.h"
#include "networking/network_game_globals.h"
#include "networking/network_game_manager.h"
#include "networking/network_game_protocol.h"
#include "networking/network_messages.h"
#include "networking/network_server_manager_internal.h"
#include "networking/network_server_message_handler.h"
#include "text/unicode.h"
#ifdef HALO_LINUX
/* system_milliseconds(), for the settings update interval */
#include "cseries/cseries_windows.h"
#endif
/* ---------- constants */
enum
{
#ifdef HALO_LINUX
/* the native builds' session limits and protocol
(port/linux/include/halo_port_limits.h) */
MAXIMUM_NETWORK_MACHINE_COUNT = HALO_PORT_MAXIMUM_NETWORK_MACHINES,
NETWORK_MESSAGE_BUFFER_SIZE = HALO_PORT_MAXIMUM_NETWORK_MESSAGE_SIZE,
NETWORK_GAME_MESSAGE_VERSION = HALO_PORT_NETWORK_GAME_MESSAGE_VERSION,
#else
MAXIMUM_NETWORK_MACHINE_COUNT = 4,
NETWORK_MESSAGE_BUFFER_SIZE = 0x600,
NETWORK_GAME_MESSAGE_VERSION = 1,
#endif
MAXIMUM_MACHINE_NAME_LENGTH = 32,
NETWORK_GAME_MAP_NAME_LENGTH = 0x100,
JOIN_GAME_TOKEN_LENGTH = 16,
MAXIMUM_HOSTS_FILE_LINE_LENGTH = 32,
TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH = 0x80,
REMOVE_PLAYER_INGAME_GAME_TIME_DELAY = 33,
TRANSPORT_NONCE_LENGTH = 8,
NETWORK_GAME_NAME_LENGTH = 16,
#ifdef HALO_LINUX
MAXIMUM_NUMBER_OF_PLAYERS = HALO_PORT_MAXIMUM_NETWORK_PLAYERS,
#else
MAXIMUM_NUMBER_OF_PLAYERS = 16,
#endif
};
enum
{
_game_advertisement_open_bit = 1,
_game_advertisement_has_teams_bit,
_game_advertisement_oddball_variant_bit,
};
#define MINIMUM_TRANSPORT_ERROR_MESSAGE_SIZE (sizeof(word) + TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH + sizeof(byte))
enum
{
_message_type_error = 1,
_message_type_data = 2,
};
enum network_game_server_state
{
_network_game_server_state_pregame = 0,
_network_game_server_state_ingame,
_network_game_server_state_postgame,
};
enum network_game_packet_class
{
_network_game_packet_class_client_search = 0,
_network_game_packet_class_client_pregame = 3,
_network_game_packet_class_client_ingame = 5,
_network_game_packet_class_client_postgame = 7,
};
enum network_game_server_rejection_reason
{
_network_game_server_rejection_reason_bad_join_token = 2,
_network_game_server_rejection_reason_game_not_open = 5,
_network_game_server_rejection_reason_not_in_hosts_file = 6,
};
/* ---------- macros */
#define network_machine_is_valid(machine) \
((machine) && (machine)->machine_index >= 0 && \
(machine)->machine_index < MAXIMUM_NETWORK_MACHINE_COUNT)
/* ---------- structures */
struct network_connection;
struct network_game_server;
struct network_game_server_client_machine;
struct network_machine
{
wchar_t name[MAXIMUM_MACHINE_NAME_LENGTH];
char machine_index;
byte padding41[3];
};
struct network_game_map
{
long unknown;
char name[0x80];
};
struct network_game_local_data
{
boolean game_objects_loaded;
byte padding[3];
};
struct network_game
{
wchar_t name[NETWORK_GAME_NAME_LENGTH];
struct network_game_map map;
struct game_variant variant;
byte unknown;
char minimum_player_count;
#ifdef HALO_LINUX
/* 128 does not fit a signed char */
byte maximum_player_count;
#else
char maximum_player_count;
#endif
byte team_count;
short difficulty;
short machine_count;
struct network_machine machines[MAXIMUM_NETWORK_MACHINE_COUNT];
short player_count;
struct network_player players[MAXIMUM_NUMBER_OF_PLAYERS];
word reserved_after_players;
unsigned long random_seed;
long number_of_games_played;
struct network_game_local_data local_data;
};
#ifdef HALO_LINUX
typedef char network_game_players_offset_assert[
offsetof(struct network_game, players) == HALO_PORT_NETWORK_GAME_PLAYERS_OFFSET ? 1 : -1];
typedef char network_game_size_assert[
sizeof(struct network_game) == HALO_PORT_NETWORK_GAME_SIZE ? 1 : -1];
#endif
struct network_message
{
word header;
};
struct message_client_broadcast_game_search
{
word port;
short version;
byte nonce[TRANSPORT_NONCE_LENGTH];
};
struct message_client_ping
{
long timestamp;
short port;
byte padding[2];
};
struct message_client_game_update
{
unsigned long update_number;
short unknown;
short player_count;
#ifdef HALO_LINUX
/* a machine's players, which 16 players / 4 machines only happened to give */
struct player_action actions[MAXIMUM_LOCAL_PLAYERS];
#else
struct player_action actions[MAXIMUM_NUMBER_OF_PLAYERS / MAXIMUM_NETWORK_MACHINE_COUNT];
#endif
};
struct message_server_pong
{
long timestamp;
};
struct message_server_game_advertise
{
byte client_nonce[TRANSPORT_NONCE_LENGTH];
byte nonce[TRANSPORT_NONCE_LENGTH];
XNKID key_id;
XNKEY key;
XNADDR xnaddr;
word port;
word version;
word platform;
wchar_t game_name[NETWORK_GAME_NAME_LENGTH];
byte reserved[0x1A];
struct network_game_map map;
short engine_type;
short machine_count;
short player_count;
short maximum_player_count;
short variant_setting;
word flags;
byte join_game_token[JOIN_GAME_TOKEN_LENGTH];
};
struct message_client_join_game_request
{
wchar_t machine_name[MAXIMUM_MACHINE_NAME_LENGTH];
byte join_game_token[JOIN_GAME_TOKEN_LENGTH];
};
struct message_client_settings_request
{
wchar_t machine_name[MAXIMUM_MACHINE_NAME_LENGTH];
char machine_index;
byte padding[3];
};
struct message_client_game_start_request
{
long countdown_time;
};
struct message_client_graceful_game_exit_pregame
{
long unused;
};
struct message_client_map_is_precached_pregame
{
char map_name[NETWORK_GAME_MAP_NAME_LENGTH];
};
struct message_client_loaded
{
long unused;
};
struct message_client_switch_to_pregame
{
long unused;
};
struct message_server_machine_accepted
{
long random_seed;
short machine_index;
byte padding[2];
};
struct message_server_machine_rejected
{
short reason;
};
#ifdef HALO_LINUX
/* the game settings record no longer fits one message: it goes out as
consecutive pieces, which the clients put back together */
struct message_server_game_settings_update
{
word total_size;
word offset;
word length;
word pad;
byte data[HALO_PORT_NETWORK_GAME_SETTINGS_FRAGMENT_SIZE];
};
#else
struct message_server_game_settings_update
{
struct network_game game;
};
#endif
struct message_server_remove_player_ingame
{
struct network_player player;
long game_time;
};
/* ---------- prototypes */
static boolean network_game_server_handle_message_client_broadcast_game_search(
struct network_game_server *server,
struct transport_address *source_address,
struct message_client_broadcast_game_search *client_message);
static boolean network_game_server_handle_message_client_ping(
struct network_game_server *server,
struct transport_address *source_address,
struct message_client_ping *client_message);
static boolean network_game_server_handle_message_client_join_game_request(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_add_player_request_pregame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_remove_player_request_pregame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_settings_request(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_player_settings_request(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_game_start_request(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_graceful_game_exit_pregame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_map_is_precached_pregame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_loaded(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_add_player_request_ingame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_remove_player_request_ingame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_remove_player_request_postgame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
static boolean network_game_server_handle_message_client_switch_to_pregame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size);
/* ---------- globals */
/* ---------- private code */
static boolean network_game_server_write(
struct network_connection *connection,
void *message,
word buffer_size,
struct transport_address *destination_address,
boolean reliable)
{
return network_connection_write(
connection,
message,
buffer_size,
destination_address,
reliable);
}
/* ---------- public code */
boolean network_game_server_send_message_to_machine(
struct network_game_server *server,
struct network_machine *machine,
struct network_message *message)
{
boolean result = FALSE;
struct network_connection *connection =
network_game_server_get_machine_connection(server, machine);
if (connection)
{
word message_size = GET_MESSAGE_SIZE(message->header);
result = network_game_server_write(
connection,
message,
message_size,
NULL,
1);
}
return result;
}
boolean network_game_server_send_message_to_all_machines(
struct network_game_server *server,
struct network_message *message)
{
byte message_buffer[NETWORK_MESSAGE_BUFFER_SIZE];
boolean result = TRUE;
word message_length;
long machine_index;
match_assert(
"c:\\halo\\SOURCE\\networking\\network_server_message_handler.c",
0x187,
server && message);
message_length = GET_MESSAGE_SIZE(message->header);
for (machine_index = 0; machine_index < MAXIMUM_NETWORK_MACHINE_COUNT; machine_index++)
{
struct network_game_server_client_machine *machine =
network_game_server_get_client_machine_at_index(server, machine_index);
if (network_game_server_client_machine_is_joined_to_game(server, machine))
{
struct network_connection *connection =
network_game_server_get_client_connection(machine);
if (connection && network_connection_active(connection))
{
match_assert(
"c:\\halo\\SOURCE\\networking\\network_server_message_handler.c",
0x19A,
message_length<=sizeof(message_buffer));
csmemcpy(message_buffer, message, message_length);
if (!network_game_server_write(
connection,
message_buffer,
message_length,
NULL,
1))
{
network_event(
"network_game_server_write() failed in network_game_server_send_message_to_all_machines()");
result = FALSE;
}
}
}
}
return result;
}
boolean network_game_server_send_player_joined_info_ingame(
struct network_game_server *server,
struct network_player *player)
{
struct network_player message;
void *encoded_message;
boolean result;
match_assert(
"c:\\halo\\SOURCE\\networking\\network_server_message_handler.c",
0x1B0,
server && player);
message = *player;
encoded_message = create_network_game_message(
_message_server_add_player_ingame,
&message,
sizeof(message));
if (encoded_message)
{
result = network_game_server_send_message_to_all_machines(server, encoded_message);
if (!result)
{
network_event(
"network_game_server_send_message_to_all_machines() failed in network_game_server_send_player_joined_info_ingame()");
}
return result;
}
network_event("failed to create a message_server_add_player_ingame message");
return FALSE;
}
#ifdef HALO_LINUX
/* With up to 128 machines, sending the whole settings record (13 KB) to every
machine on each lobby change would flood the network while a lobby fills, so
changes are collected and sent at most this often; the server's pregame idle
sends what is pending. */
enum
{
NETWORK_GAME_SETTINGS_UPDATE_INTERVAL = MILLISECONDS_PER_SECOND / 4,
};
static boolean network_game_settings_update_pending = FALSE;
static unsigned long network_game_settings_update_time = 0;
boolean network_game_server_send_game_settings_to_all_machines(
struct network_game_server *server,
void const *game,
long game_size)
{
struct message_server_game_settings_update message;
long offset;
boolean result = TRUE;
match_assert(
"c:\\halo\\SOURCE\\networking\\network_server_message_handler.c",
0x1C8,
server);
/* every piece goes out even if one fails for a machine: the others
would otherwise keep the old settings (a machine whose connection failed
is closed, and is skipped when the update is sent again) */
for (offset = 0; offset < game_size; offset += sizeof(message.data))
{
void *encoded_message;
message.total_size = (word)game_size;
message.offset = (word)offset;
message.length = (word)MIN((long)sizeof(message.data), game_size - offset);
message.pad = 0;
csmemset(message.data, 0, sizeof(message.data));
csmemcpy(message.data, (byte const *)game + offset, message.length);
encoded_message = create_network_game_message(
_message_server_game_settings_update,
&message,
sizeof(message));
if (encoded_message)
{
result = network_game_server_send_message_to_all_machines(server, encoded_message);
if (!result)
{
network_event(
"failed to send message_server_game_settings_update message to all machines");
}
}
else
{
network_event("failed to create a message_server_game_settings_update message");
result = FALSE;
}
}
network_game_settings_update_pending = !result;
network_game_settings_update_time = system_milliseconds();
return result;
}
boolean network_game_server_flush_game_data_pregame(
struct network_game_server *server)
{
boolean result = TRUE;
if (network_game_settings_update_pending &&
system_milliseconds() - network_game_settings_update_time >= NETWORK_GAME_SETTINGS_UPDATE_INTERVAL)
{
struct network_game *game = network_game_server_get_game(server);
if (game)
{
result = network_game_server_send_game_settings_to_all_machines(server, game, sizeof(*game));
}
else
{
network_event(
"failed to handle a message_server_game_settings_update because their was no server game");
network_game_settings_update_pending = FALSE;
result = FALSE;
}
}
return result;
}
boolean network_game_server_send_game_data_pregame(
struct network_game_server *server)
{
network_game_settings_update_pending = TRUE;
return network_game_server_flush_game_data_pregame(server);
}
#else
boolean network_game_server_send_game_data_pregame(
struct network_game_server *server)
{
struct message_server_game_settings_update message;
struct network_game *game;
void *encoded_message;
boolean result = FALSE;
match_assert(
"c:\\halo\\SOURCE\\networking\\network_server_message_handler.c",
0x1C8,
server);
game = network_game_server_get_game(server);
if (game)
{
csmemcpy(&message, game, sizeof(message));
encoded_message = create_network_game_message(
_message_server_game_settings_update,
&message,
sizeof(message));
if (encoded_message)
{
result = network_game_server_send_message_to_all_machines(server, encoded_message);
if (!result)
{
network_event(
"failed to send message_server_game_settings_update message to all machines");
}
}
else
{
network_event("failed to create a message_server_game_settings_update message");
}
}
else
{
network_event(
"failed to handle a message_server_game_settings_update because their was no server game");
}
return result;
}
#endif
boolean network_game_server_handle_client_message(
struct network_game_server *server,
struct network_game_server_client_machine *machine,
word *message,
short message_buffer_size)
{
boolean result = TRUE;
word message_type;
byte packet_type;
match_assert(
"c:\\halo\\SOURCE\\networking\\network_server_message_handler.c",
0xCF,
server && machine && message && (message_buffer_size == GET_MESSAGE_SIZE(*message)));
message_type = (byte)GET_MESSAGE_TYPE(*message);
if (GET_MESSAGE_FLAGS(*message))
{
network_event("server received client message with invalid flags");
}
else
{
switch (message_type)
{
case _message_type_packet:
packet_type = ((byte *)message)[message_buffer_size - 1];
if (network_game_server_client_machine_is_joined_to_game(server, machine) ||
packet_type == _message_client_join_game_request)
{
switch (packet_type)
{
case _message_client_join_game_request:
result = network_game_server_handle_message_client_join_game_request(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_join_game_request() failed");
}
break;
case _message_client_add_player_request_pregame:
result = network_game_server_handle_message_client_add_player_request_pregame(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_add_player_request_pregame() failed");
}
break;
case _message_client_remove_player_request_pregame:
result = network_game_server_handle_message_client_remove_player_request_pregame(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_remove_player_request_pregame() failed");
}
break;
case _message_client_settings_request:
result = network_game_server_handle_message_client_settings_request(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_settings_request() failed");
}
break;
case _message_client_player_settings_request:
result = network_game_server_handle_message_client_player_settings_request(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_player_settings_request() failed");
}
break;
case _message_client_game_start_request:
result = network_game_server_handle_message_client_game_start_request(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_game_start_request() failed");
}
break;
case _message_client_graceful_game_exit_pregame:
result = network_game_server_handle_message_client_graceful_game_exit_pregame(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_graceful_game_exit_pregame() failed");
}
break;
case _message_client_map_is_precached_pregame:
result = network_game_server_handle_message_client_map_is_precached_pregame(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_graceful_game_exit_pregame() failed");
}
break;
case _message_client_loaded:
result = network_game_server_handle_message_client_loaded(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_loaded() failed");
}
break;
case _message_client_add_player_request_ingame:
result = network_game_server_handle_message_client_add_player_request_ingame(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_add_player_request_ingame() failed");
}
break;
case _message_client_remove_player_request_ingame:
result = network_game_server_handle_message_client_remove_player_request_ingame(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_remove_player_request_ingame() failed");
}
break;
case _message_client_remove_player_request_postgame:
result = network_game_server_handle_message_client_remove_player_request_postgame(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_remove_player_request_postgame() failed");
}
break;
case _message_client_switch_to_pregame:
result = network_game_server_handle_message_client_switch_to_pregame(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_switch_to_pregame() failed");
}
break;
case _message_client_graceful_game_exit_postgame:
result = network_game_server_handle_message_client_graceful_game_exit_pregame(
server,
machine,
message,
message_buffer_size);
if (!result)
{
network_event("network_game_server_handle_message_client_graceful_game_exit_pregame() failed");
}
break;
default:
network_event(
"bad or inappropriate packet type received from a client (#%d)",
packet_type);
break;
}
}
else
{
network_event("an un-validated client sent something other than a join request message");
}
break;
case _message_type_data:
network_event("server received a bad message type from a client (_message_type_data)");
break;
case _message_type_error:
if (message_buffer_size >= MINIMUM_TRANSPORT_ERROR_MESSAGE_SIZE)
{
byte *error_message = (byte *)(message + 1);
network_event(
"server received low-level error message from a client: error= #%d (%s)",
error_message[TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH],
error_message);
}
else
{
network_event("server received a malformed/damaged message from a client");
}
break;
default:
network_event(
"server received a client message with an unknown message type (#%d)",
message_type);
break;
}
}
return result;
}
boolean network_game_server_handle_datagram(
struct network_game_server *server,
word *message,
short datagram_size,
struct transport_address *source_address)
{
word message_type;
match_assert(
"c:\\halo\\SOURCE\\networking\\network_server_message_handler.c",
0x40,
server && message && source_address &&
(datagram_size > sizeof(message_header)) &&
(datagram_size == GET_MESSAGE_SIZE(*message)));
message_type = (byte)GET_MESSAGE_TYPE(*message);
if (GET_MESSAGE_FLAGS(*message))
{
network_event(
"server received a datagram with invalid flags; sender= '%s'",
transport_address_to_string(source_address));
}
else
{
switch (message_type)
{
case _message_type_packet:
{
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
short packet_type = ((byte *)message)[datagram_size - 1];
datagram_size -= sizeof(word);
switch (packet_type)
{
case _message_client_broadcast_game_search:
if (network_game_should_accept_remote_connections())
{
struct message_client_broadcast_game_search game_search;
if (decode_network_game_message(
&game_search,
message + 1,
&datagram_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_search))
{
if (!network_game_server_handle_message_client_broadcast_game_search(
server,
source_address,
&game_search))
{
network_event(
"server failed to advertise game to prospective client at '%s'",
transport_address_to_string(source_address));
}
}
else
{
network_event("failed to decode a message_client_broadcast_game_search packet");
}
}
break;
case _message_client_ping:
if (network_game_should_accept_remote_connections())
{
struct message_client_ping ping;
if (decode_network_game_message(
&ping,
message + 1,
&datagram_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_search))
{
if (!network_game_server_handle_message_client_ping(
server,
source_address,
&ping))
{
network_event("server failed to handle a client ping");
}
}
else
{
network_event("failed to decode a message_client_ping packet");
}
}
break;
case _message_client_game_update:
if (network_game_server_get_state(server, NULL) == _network_game_server_state_ingame)
{
struct network_game_server_client_machine *client_machine =
network_game_server_get_client_machine_at_address(
server,
source_address->address.long_words[0]);
if (client_machine)
{
struct message_client_game_update game_update;
if (decode_network_game_message(
&game_update,
message + 1,
&datagram_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_ingame))
{
network_game_server_handle_client_update_packet(
server,
client_machine,
&game_update);
}
else
{
network_event("failed to decode a message_client_game_update packet");
}
}
else
{
network_event(
"failed to handle a message_client_game_update message; this client doesn't seem to be in the game");
}
}
else
{
network_event("ignoring a message_client_game_update message; we are not in game");
}
break;
default:
network_event(
"server received datagram with an unexpected packet type; sender= '%s'",
transport_address_to_string(source_address));
break;
}
}
break;
case _message_type_data:
network_event(
"server received a bad message type (_message_type_data); sender= '%s'",
transport_address_to_string(source_address));
break;
case _message_type_error:
if (datagram_size >= MINIMUM_TRANSPORT_ERROR_MESSAGE_SIZE)
{
byte *error_message = (byte *)(message + 1);
network_event(
"server received low-level error message: error= #%d (%s); sender= '%s'",
error_message[TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH],
error_message,
transport_address_to_string(source_address));
}
else
{
network_event(
"server received a malformed/damaged message; sender= '%s'",
transport_address_to_string(source_address));
}
break;
default:
network_event(
"server received a datagram with an unknown message type (#%d); sender= '%s'",
message_type,
transport_address_to_string(source_address));
break;
}
}
return TRUE;
}
/* ---------- private code */
static boolean network_game_server_handle_message_client_broadcast_game_search(
struct network_game_server *server,
struct transport_address *source_address,
struct message_client_broadcast_game_search *client_message)
{
boolean result = TRUE;
match_assert(
"c:\\halo\\SOURCE\\networking\\network_server_message_handler.c",
0x21F,
server && source_address && client_message);
if (client_message->version == NETWORK_GAME_MESSAGE_VERSION)
{
struct network_game *game = network_game_server_get_game(server);
if (game)
{
struct message_server_game_advertise advertisement = {0};
struct transport_address address;
struct network_message *reply;
address.address_length = IPV4_ADDRESS_LENGTH;
address.address.long_words[0] = NONE;
address.port = NETWORK_GAME_CLIENT_PORT;
csmemcpy(
advertisement.client_nonce,
client_message->nonce,
sizeof(client_message->nonce));
transport_get_nonce(advertisement.nonce, TRANSPORT_NONCE_LENGTH);
advertisement.key_id = transport_get_key_id();
advertisement.key = transport_get_key();
{
XNADDR xnaddr;
advertisement.xnaddr = *transport_get_xnaddr(&xnaddr);
}
advertisement.port = NETWORK_GAME_SERVER_PORT;
advertisement.version = NETWORK_GAME_MESSAGE_VERSION;
advertisement.platform = 0;
ustrncpy(advertisement.game_name, game->name, NETWORK_GAME_NAME_LENGTH - 1);
advertisement.engine_type = (short)game->variant.game_engine_index;
csmemcpy(&advertisement.map, &game->map, sizeof(game->map));
advertisement.machine_count = game->machine_count;
advertisement.player_count = game->player_count;
advertisement.maximum_player_count = game->maximum_player_count;
advertisement.variant_setting = (short)game->variant.universal_variant.score_to_win;
advertisement.flags = 0;
if (game->variant.universal_variant.teams == TRUE)
{
advertisement.flags = FLAG(_game_advertisement_has_teams_bit);
}
if (game->variant.game_engine_index == game_engine_oddball &&
game->variant.game_engine_variant.oddball.oddball_ball_type == 2)
{
advertisement.flags |= FLAG(_game_advertisement_oddball_variant_bit);
}
if (network_game_server_game_is_open(server))
{
advertisement.flags |= FLAG(_game_advertisement_open_bit);
}
network_game_generate_join_game_token(advertisement.join_game_token);
reply = create_network_game_message(
_message_server_game_advertise,
&advertisement,
sizeof(advertisement));
if (reply)
{
word message_size = GET_MESSAGE_SIZE(reply->header);
struct network_connection *connection =
network_game_server_get_connection(server);
result = network_game_server_write(
connection,
reply,
message_size,
&address,
0);
if (!result)
{
network_event(
"network_game_server_write() failed in handle_message_client_broadcast_game_search()");
}
}
else
{
network_event("failed to create a message_server_game_advertise message");
}
}
}
return result;
}
static boolean network_game_server_handle_message_client_ping(
struct network_game_server *server,
struct transport_address *source_address,
struct message_client_ping *client_message)
{
struct message_server_pong pong;
struct network_message *reply;
boolean result = FALSE;
match_assert(
"c:\\halo\\SOURCE\\networking\\network_server_message_handler.c",
0x26A,
server && source_address && client_message);
pong.timestamp = client_message->timestamp;
reply = create_network_game_message(
_message_server_pong,
&pong,
sizeof(pong));
if (reply)
{
struct transport_address address;
address.address_length = IPV4_ADDRESS_LENGTH;
address.address.long_words[0] = source_address->address.long_words[0];
address.port = client_message->port;
result = network_game_server_write(
network_game_server_get_connection(server),
reply,
GET_MESSAGE_SIZE(reply->header),
&address,
0);
if (!result)
{
network_event(
"network_game_server_write() failed in handle_message_client_ping()");
}
}
else
{
network_event("failed to create a message_server_pong message");
}
return result;
}
static boolean network_game_server_handle_message_client_join_game_request(
struct network_game_server *server,
struct network_game_server_client_machine *server_client_machine,
word *message,
short message_size)
{
boolean result = TRUE;
if (network_game_server_get_state(server, NULL) == _network_game_server_state_pregame)
{
struct message_client_join_game_request join_game_request;
short packet_type = _message_client_join_game_request;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (network_game_server_client_machine_is_joined_to_game(server, server_client_machine))
{
network_event("ignoring redundant join request from machine");
}
else if (decode_network_game_message(
&join_game_request,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_pregame))
{
struct transport_address source_address;
network_connection_get_address(
network_game_server_get_client_connection(server_client_machine),
&source_address,
FALSE);
if (network_game_server_get_state(server, NULL) == _network_game_server_state_pregame &&
network_game_server_game_is_open(server))
{
byte join_game_token[JOIN_GAME_TOKEN_LENGTH];
network_game_generate_join_game_token(join_game_token);
if (!csmemcmp(
join_game_request.join_game_token,
join_game_token,
sizeof(join_game_token)))
{
boolean machine_is_in_hosts_file = TRUE;
FILE *hosts_file;
wide_to_ascii(
join_game_request.machine_name,
(char *)join_game_request.machine_name,
sizeof(join_game_request.machine_name));
hosts_file = fopen("d:\\hosts.txt", "r");
if (hosts_file)
{
char host_line[MAXIMUM_HOSTS_FILE_LINE_LENGTH] = "";
machine_is_in_hosts_file = FALSE;
while (fgets(host_line, sizeof(host_line), hosts_file))
{
if (!csstrncmp(
(char *)join_game_request.machine_name,
host_line,
csstrlen((char *)join_game_request.machine_name)))
{
machine_is_in_hosts_file = TRUE;
break;
}
}
fclose(hosts_file);
}
if (!machine_is_in_hosts_file)
{
struct message_server_machine_rejected rejection;
struct network_message *reply;
rejection.reason = _network_game_server_rejection_reason_not_in_hosts_file;
network_event(
"server refused client '%s' because it is not in your hosts file",
join_game_request.machine_name);
reply = create_network_game_message(
_message_server_machine_rejected,
&rejection,
sizeof(rejection));
if (reply)
{
word message_size = GET_MESSAGE_SIZE(reply->header);
struct network_connection *connection =
network_game_server_get_client_connection(server_client_machine);
network_game_server_write(
connection,
reply,
message_size,
NULL,
1);
}
result = FALSE;
}
else
{
if (network_game_server_accept_client_machine_into_game(server, server_client_machine))
{
struct message_server_machine_accepted acceptance;
struct network_message *reply;
struct network_machine *client_machine;
long machine_index = NONE;
client_machine = network_game_server_get_client_machine(
server,
server_client_machine,
&machine_index);
network_game_server_get_game(server);
match_assert(
"c:\\halo\\SOURCE\\networking\\network_server_message_handler.c",
0x2CE,
network_machine_is_valid(client_machine));
acceptance.machine_index = (short)machine_index;
acceptance.random_seed = network_game_get_random_seed();
reply = create_network_game_message(
_message_server_machine_accepted,
&acceptance,
sizeof(acceptance));
if (reply)
{
word message_size = GET_MESSAGE_SIZE(reply->header);
struct network_connection *connection =
network_game_server_get_client_connection(server_client_machine);
result = network_game_server_write(
connection,
reply,
message_size,
NULL,
1);
if (!result)
{
network_event(
"network_game_server_write() failed in network_game_server_handle_message_client_join_game_request()");
}
else
{
network_event(
"sent _message_type_server_machine_accepted message to %d",
machine_index);
}
if (result == TRUE)
{
result = network_game_server_send_game_data_pregame(server);
if (!result)
{
network_event(
"network_game_server_send_game_data_pregame() failed in network_game_server_handle_message_client_join_game_request()");
}
}
}
else
{
result = FALSE;
}
}
else
{
struct message_server_machine_rejected rejection;
struct network_message *reply;
rejection.reason = _network_game_server_rejection_reason_game_not_open;
network_event(
"server failed to accept valid client machine '%s' @%s into the game",
join_game_request.machine_name,
transport_address_to_string(&source_address));
reply = create_network_game_message(
_message_server_machine_rejected,
&rejection,
sizeof(rejection));
if (reply)
{
word message_size = GET_MESSAGE_SIZE(reply->header);
struct network_connection *connection =
network_game_server_get_client_connection(server_client_machine);
if (!network_game_server_write(
connection,
reply,
message_size,
NULL,
1))
{
network_event(
"network_game_server_write() failed while sending a rejection reply");
}
}
result = FALSE;
}
}
}
else
{
struct message_server_machine_rejected rejection;
struct network_message *reply;
rejection.reason = _network_game_server_rejection_reason_bad_join_token;
network_event(
"client machine '%s' @%s tried to join game with a bad join token",
join_game_request.machine_name,
transport_address_to_string(&source_address));
reply = create_network_game_message(
_message_server_machine_rejected,
&rejection,
sizeof(rejection));
if (reply)
{
word message_size = GET_MESSAGE_SIZE(reply->header);
struct network_connection *connection =
network_game_server_get_client_connection(server_client_machine);
if (!network_game_server_write(
connection,
reply,
message_size,
NULL,
1))
{
network_event(
"network_game_server_write() failed while sending a rejection reply");
}
}
else
{
network_event("failed to create a message_server_machine_rejected message");
}
result = FALSE;
}
}
else
{
struct message_server_machine_rejected rejection;
struct network_message *reply;
rejection.reason = _network_game_server_rejection_reason_game_not_open;
network_event(
"client machine '%s' @%s tried to join game when they should not be",
join_game_request.machine_name,
transport_address_to_string(&source_address));
reply = create_network_game_message(
_message_server_machine_rejected,
&rejection,
sizeof(rejection));
if (reply)
{
word message_size = GET_MESSAGE_SIZE(reply->header);
struct network_connection *connection =
network_game_server_get_client_connection(server_client_machine);
if (!network_game_server_write(
connection,
reply,
message_size,
NULL,
1))
{
network_event(
"network_game_server_write() failed while sending a rejection reply");
}
}
else
{
network_event("failed to create a message_server_machine_rejected message");
}
result = FALSE;
}
}
else
{
network_event("server failed to decode a message_client_join_game_request packet");
result = FALSE;
}
}
return result;
}
static boolean network_game_server_handle_message_client_add_player_request_pregame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
if (network_game_server_get_state(server, NULL) == _network_game_server_state_pregame)
{
struct network_player player;
short packet_type = _message_client_add_player_request_pregame;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&player,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_pregame))
{
if (network_game_server_add_player_to_game(server, client_machine, &player))
{
if (!network_game_server_send_game_data_pregame(server))
{
network_event(
"server failed to send pregame game data in network_game_server_handle_message_client_add_player_request_pregame()");
}
}
else
{
network_event(
"server failed to add a network player in network_game_server_handle_message_client_add_player_request_pregame()");
}
}
else
{
network_event("server failed to decode a message_client_add_player_request_pregame packet");
}
}
else
{
network_event(
"failed to handle a message_client_add_player_request_pregame because the server is not in pregame");
}
return TRUE;
}
static boolean network_game_server_handle_message_client_remove_player_request_pregame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
if (network_game_server_get_state(server, NULL) == _network_game_server_state_pregame)
{
struct network_player player;
short packet_type = _message_client_remove_player_request_pregame;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&player,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_pregame))
{
if (network_game_server_remove_player_from_game(server, client_machine, &player))
{
if (!network_game_server_send_game_data_pregame(server))
{
network_event(
"server failed to send pregame game data in network_game_server_handle_message_client_remove_player_request_pregame()");
}
}
else
{
network_event(
"server failed to remove a network player in network_game_server_handle_message_client_remove_player_request_pregame()");
}
}
else
{
network_event("server failed to decode a message_client_remove_player_request_pregame packet");
}
}
else
{
network_event(
"failed to handle a message_client_remove_player_request_pregame because the server is not in pregame");
}
return TRUE;
}
static boolean network_game_server_handle_message_client_settings_request(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
if (network_game_server_get_state(server, NULL) == _network_game_server_state_pregame)
{
struct network_machine machine_settings;
short packet_type = _message_client_settings_request;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&machine_settings,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_pregame))
{
if (network_game_server_adjust_machine_settings(server, client_machine, &machine_settings))
{
network_event(
"server received machine settings for machine #%d/'%s'",
machine_settings.machine_index,
wide_to_ascii(
machine_settings.name,
(char *)machine_settings.name,
sizeof(machine_settings.name)));
if (!network_game_server_send_game_data_pregame(server))
{
network_event(
"server failed to send pregame game data in network_game_server_handle_message_client_settings_request()");
}
}
else
{
network_event(
"network_game_server_adjust_machine_settings() failed in network_game_server_handle_message_client_settings_request()");
}
}
else
{
network_event("server failed to decode a message_client_settings_request packet");
}
}
else
{
network_event(
"failed to handle a message_client_settings_request because the server is not in pregame");
}
return TRUE;
}
static boolean network_game_server_handle_message_client_player_settings_request(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
if (network_game_server_get_state(server, NULL) == _network_game_server_state_pregame)
{
struct network_player player;
short packet_type = _message_client_player_settings_request;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&player,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_pregame))
{
if (network_game_update_player(network_game_server_get_game(server), &player))
{
network_event("server received updated player settings");
if (!network_game_server_send_game_data_pregame(server))
{
network_event(
"server failed to send pregame game data in network_game_server_handle_message_client_player_settings_request()");
}
}
else
{
network_event(
"network_game_update_player() failed in network_game_server_handle_message_client_player_settings_request()");
}
}
else
{
network_event("server failed to decode a message_client_player_settings_request packet");
}
}
else
{
network_event(
"failed to handle a message_client_player_settings_request because the server is not in pregame");
}
return TRUE;
}
static boolean network_game_server_handle_message_client_game_start_request(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
if (network_game_server_get_state(server, NULL) == _network_game_server_state_pregame)
{
struct message_client_game_start_request game_start_request;
short packet_type = _message_client_player_settings_request;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&game_start_request,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_pregame))
{
network_game_server_update_countdown(server, game_start_request.countdown_time);
}
else
{
network_event("server failed to decode a message_client_game_start_request packet");
}
}
else
{
network_event(
"failed to handle a message_client_game_start_request because the server is not in pregame");
}
return TRUE;
}
static boolean network_game_server_handle_message_client_graceful_game_exit_pregame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
if (network_game_server_get_state(server, NULL) == _network_game_server_state_pregame)
{
struct message_client_graceful_game_exit_pregame graceful_game_exit;
short packet_type = _message_client_graceful_game_exit_pregame;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&graceful_game_exit,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_pregame))
{
if (network_game_server_remove_machine_from_game(
server,
network_game_server_get_client_machine(server, client_machine, NULL)))
{
if (!network_game_server_send_game_data_pregame(server))
{
network_event(
"server failed to send pregame game data in network_game_server_handle_message_client_graceful_game_exit_pregame()");
}
}
else
{
network_event(
"network_game_server_remove_machine_from_game() failed in network_game_server_handle_message_client_graceful_game_exit_pregame()");
}
}
else
{
network_event("server failed to decode a message_client_graceful_game_exit_pregame packet");
}
}
else
{
network_event(
"failed to handle a message_client_graceful_game_exit_pregame message because the server is not in pregame");
}
return TRUE;
}
static boolean network_game_server_handle_message_client_map_is_precached_pregame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
if (network_game_server_get_state(server, NULL) == _network_game_server_state_pregame)
{
struct message_client_map_is_precached_pregame map_is_precached;
short packet_type = _message_client_map_is_precached_pregame;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&map_is_precached,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_pregame))
{
network_game_server_client_machine_is_precached(
server,
client_machine,
map_is_precached.map_name);
}
else
{
network_event("server failed to decode a message_type_client_map_is_precached_pregame packet");
}
}
else
{
network_event(
"failed to handle a message_type_client_map_is_precached_pregame because the server is not in pregame");
}
return TRUE;
}
static boolean network_game_server_handle_message_client_loaded(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
boolean result = TRUE;
if (network_game_server_get_state(server, NULL) == _network_game_server_state_pregame)
{
struct message_client_loaded loaded;
short packet_type = _message_client_loaded;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&loaded,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_ingame))
{
network_game_server_client_machine_game_loading_complete(server, client_machine);
}
else
{
network_event("server failed to decode a message_client_loaded packet");
result = FALSE;
}
}
else
{
network_event(
"failed to handle a message_client_loaded message because the server is not in pregame");
result = FALSE;
}
return result;
}
static boolean network_game_server_handle_message_client_add_player_request_ingame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
if (network_game_server_get_state(server, NULL) == _network_game_server_state_ingame)
{
struct network_player player;
short packet_type = _message_client_add_player_request_ingame;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&player,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_ingame))
{
network_game_server_queue_player_for_addition(server, &player);
}
else
{
network_event("server failed to decode a message_client_add_player_request_ingame packet");
}
}
else
{
network_event(
"failed to handle a message_client_add_player_request_ingame because the server is not in game");
}
return TRUE;
}
static boolean network_game_server_handle_message_client_remove_player_request_ingame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
boolean result = TRUE;
if (network_game_server_get_state(server, NULL) == _network_game_server_state_ingame)
{
struct network_player player;
short packet_type = _message_client_add_player_request_ingame;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&player,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_ingame))
{
struct network_game *game = network_game_server_get_game(server);
if (network_game_remove_player(game, &player))
{
struct message_server_remove_player_ingame remove_player;
void *encoded_message;
remove_player.player = player;
remove_player.game_time = game_time_get() + REMOVE_PLAYER_INGAME_GAME_TIME_DELAY;
encoded_message = create_network_game_message(
_message_server_remove_player_ingame,
&remove_player,
sizeof(remove_player));
if (encoded_message)
{
result = network_game_server_send_message_to_all_machines(server, encoded_message);
if (!result)
{
network_event(
"network_game_server_send_message_to_all_machines() failed in network_game_server_handle_message_client_remove_player_request_ingame()");
}
return result;
}
}
}
else
{
network_event("server failed to decode a message_client_remove_player_request_ingame packet");
}
}
else
{
network_event(
"failed to handle a message_client_remove_player_request_ingame because the server is not in game");
}
return result;
}
static boolean network_game_server_handle_message_client_remove_player_request_postgame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
if (network_game_server_get_state(server, NULL) == _network_game_server_state_postgame)
{
struct network_player player;
short packet_type = _message_client_remove_player_request_postgame;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&player,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_postgame))
{
if (!network_game_server_remove_player_from_game(server, client_machine, &player))
{
network_event("server failed to remove a network player post-game");
}
}
else
{
network_event("server failed to decode a message_client_remove_player_request_postgame packet");
}
}
else
{
network_event(
"failed to handle a message_client_remove_player_request_postgame because the server is not in post-game");
}
return TRUE;
}
static boolean network_game_server_handle_message_client_switch_to_pregame(
struct network_game_server *server,
struct network_game_server_client_machine *client_machine,
word *message,
short message_size)
{
boolean result = TRUE;
if (network_game_server_get_state(server, NULL) == _network_game_server_state_postgame)
{
struct message_client_switch_to_pregame switch_to_pregame;
short packet_type = _message_client_switch_to_pregame;
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
message_size -= sizeof(word);
if (decode_network_game_message(
&switch_to_pregame,
message + 1,
&message_size,
&packet_type,
&packet_version,
_network_game_packet_class_client_postgame))
{
result = network_game_server_switch_machine_from_postgame_to_pregame(server, client_machine);
if (!result)
{
network_event("network_game_server_switch_machine_from_postgame_to_pregame() failed");
}
}
else
{
network_event("server failed to decode a message_client_remove_player_request_postgame packet");
}
}
else
{
network_event(
"failed to handle a message_client_switch_to_pregame because the server is not in post-game");
}
return result;
}