mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-17 18:00:25 +02:00
1567 lines
45 KiB
C
1567 lines
45 KiB
C
/*
|
|
NETWORK_CLIENT_MESSAGE_HANDLER.C
|
|
|
|
symbols in this file:
|
|
00116AB0 00b0:
|
|
_network_game_client_handle_message_server_game_advertise (0000)
|
|
00116B60 0090:
|
|
_network_game_client_handle_message_server_pong (0000)
|
|
00116BF0 00a0:
|
|
_network_game_client_handle_message_server_machine_accepted (0000)
|
|
00116C90 00a0:
|
|
_network_game_client_handle_message_server_machine_rejected (0000)
|
|
00116D30 0130:
|
|
_network_game_client_handle_message_server_game_settings_update (0000)
|
|
00116E60 0100:
|
|
_network_game_client_handle_message_server_pregame_countdown (0000)
|
|
00116F60 00e0:
|
|
_network_game_client_handle_message_server_pregame_keep_alive (0000)
|
|
00117040 00e0:
|
|
_network_game_client_handle_message_server_postgame_keep_alive (0000)
|
|
00117120 00d0:
|
|
_network_game_client_handle_message_server_begin_game (0000)
|
|
001171F0 00b0:
|
|
_network_game_client_handle_message_server_graceful_game_exit_pregame (0000)
|
|
001172A0 00c0:
|
|
_network_game_client_handle_message_server_game_update (0000)
|
|
00117360 00c0:
|
|
_network_game_client_handle_message_server_add_player_ingame (0000)
|
|
00117420 00c0:
|
|
_network_game_client_handle_message_server_remove_player_ingame (0000)
|
|
001174E0 00a0:
|
|
_network_game_client_handle_message_server_game_over (0000)
|
|
00117580 00c0:
|
|
_network_game_client_handle_message_server_switch_to_pregame (0000)
|
|
00117640 00b0:
|
|
_network_game_client_handle_message_server_graceful_game_exit_postgame (0000)
|
|
001176F0 0440:
|
|
_network_game_client_handle_message (0000)
|
|
00281928 0045:
|
|
??_C@_0EF@JEKJBGGG@ignoring?5an?5advertised?5game?5beca@ (0000)
|
|
00281970 0038:
|
|
??_C@_0DI@DKMFJKNC@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
002819A8 003e:
|
|
??_C@_0DO@KGHCHMKG@ignoring?5a?5pong?5message?5because?5@ (0000)
|
|
002819E8 002e:
|
|
??_C@_0CO@MNCKPDII@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281A18 005e:
|
|
??_C@_0FO@MDHPOCDK@ignoring?5a?5message_server_machin@ (0000)
|
|
00281A78 003a:
|
|
??_C@_0DK@OHJLEEJA@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281AB8 005e:
|
|
??_C@_0FO@KFHDMLDG@ignoring?5a?5message_server_machin@ (0000)
|
|
00281B18 003a:
|
|
??_C@_0DK@NPFONKEC@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281B58 0048:
|
|
??_C@_0EI@MBCELKHN@ignoring?5a?5message_server_game_s@ (0000)
|
|
00281BA0 0055:
|
|
??_C@_0FF@MOCCMIII@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00281BF8 003e:
|
|
??_C@_0DO@CFANMJHG@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281C38 0033:
|
|
??_C@_0DD@BCJHCHJP@network_game_client_game_setting@ (0000)
|
|
00281C6C 0017:
|
|
??_C@_0BH@BJKENKMM@source_address?5?$CB?$DN?5NULL?$AA@ (0000)
|
|
00281C84 003b:
|
|
??_C@_0DL@LEGDIILJ@c?3?2halo?2SOURCE?2networking?2networ@ (0000)
|
|
00281CC0 0045:
|
|
??_C@_0EF@KFKEPLOD@ignoring?5a?5message_server_pregam@ (0000)
|
|
00281D08 0052:
|
|
??_C@_0FC@JHBFLLPP@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00281D5C 003b:
|
|
??_C@_0DL@LHJKBMIA@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281D98 0046:
|
|
??_C@_0EG@IAKPIALP@ignoring?5a?5message_server_pregam@ (0000)
|
|
00281DE0 0053:
|
|
??_C@_0FD@ECPEPJNC@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00281E34 003c:
|
|
??_C@_0DM@GMAKBHHC@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281E70 0047:
|
|
??_C@_0EH@IABGEGJI@ignoring?5a?5message_server_postga@ (0000)
|
|
00281EB8 0055:
|
|
??_C@_0FF@PKNMLFIC@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00281F10 003d:
|
|
??_C@_0DN@BIGGNOLB@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00281F50 0046:
|
|
??_C@_0EG@KGCDAEPA@ignoring?5a?5message_server_begin_@ (0000)
|
|
00281F98 004c:
|
|
??_C@_0EM@LHDJIHFO@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00281FE4 0034:
|
|
??_C@_0DE@OPOJGBIB@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282018 002e:
|
|
??_C@_0CO@IDLMDGAP@network_game_client_game_has_sta@ (0000)
|
|
00282048 0056:
|
|
??_C@_0FG@NGBIOKLC@ignoring?5a?5message_server_gracef@ (0000)
|
|
002820A0 005c:
|
|
??_C@_0FM@DIGPPEBG@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00282100 0044:
|
|
??_C@_0EE@ECCKOGDL@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282148 0047:
|
|
??_C@_0EH@MEBMJMKF@ignoring?5a?5message_server_game_u@ (0000)
|
|
00282190 004a:
|
|
??_C@_0EK@HLKFMGH@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
002821DC 0035:
|
|
??_C@_0DF@IIILBLL@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282214 0030:
|
|
??_C@_0DA@NKCCMGPH@network_game_client_handle_game_@ (0000)
|
|
00282248 004d:
|
|
??_C@_0EN@FKBHABAC@ignoring?5a?5message_server_add_pl@ (0000)
|
|
00282298 0050:
|
|
??_C@_0FA@NACEIJGI@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
002822E8 003b:
|
|
??_C@_0DL@FGDEKFMJ@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282324 0030:
|
|
??_C@_0DA@ICGCINCO@network_game_client_add_player_t@ (0000)
|
|
00282358 0050:
|
|
??_C@_0FA@IBHOBKAI@ignoring?5a?5message_server_remove@ (0000)
|
|
002823A8 0053:
|
|
??_C@_0FD@OLBMGIKB@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
002823FC 003e:
|
|
??_C@_0DO@GODOOHMN@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
0028243C 002b:
|
|
??_C@_0CL@NBDIBGCC@network_game_client_remove_playe@ (0000)
|
|
00282468 0045:
|
|
??_C@_0EF@DDKCBEG@ignoring?5a?5message_server_game_o@ (0000)
|
|
002824B0 0048:
|
|
??_C@_0EI@BGOBBEDF@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
002824F8 0043:
|
|
??_C@_0ED@LKOOJPFP@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282540 004d:
|
|
??_C@_0EN@IMILJCHD@ignoring?5a?5message_server_switch@ (0000)
|
|
00282590 0055:
|
|
??_C@_0FF@LPOEGCEN@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
002825E8 002f:
|
|
??_C@_0CP@KPJNEAOB@network_game_client_switch_to_pr@ (0000)
|
|
00282618 003b:
|
|
??_C@_0DL@DIFCCPGE@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282658 0057:
|
|
??_C@_0FH@MFCGNFNN@ignoring?5a?5message_server_gracef@ (0000)
|
|
002826B0 005f:
|
|
??_C@_0FP@KCFNLJEN@failed?5to?5handle?5a?5message_serve@ (0000)
|
|
00282710 0054:
|
|
??_C@_0FE@LHBDFEJN@failed?5to?5decode?5a?5message_serve@ (0000)
|
|
00282764 003a:
|
|
??_C@_0DK@BPCDJE@client?5received?5a?5malformed?1dama@ (0000)
|
|
002827A0 0039:
|
|
??_C@_0DJ@ILEOJBLB@client?5received?5low?9level?5error?5@ (0000)
|
|
002827DC 0038:
|
|
??_C@_0DI@MKDILEED@client?5received?5a?5bad?5message?5ty@ (0000)
|
|
00282814 0037:
|
|
??_C@_0DH@DOCAAFEI@unknown?5packet?5type?5received?5fro@ (0000)
|
|
00282850 004f:
|
|
??_C@_0EP@PCPAJAJP@network_game_client_handle_messa@ (0000)
|
|
002828A0 0045:
|
|
??_C@_0EF@GBNHBHMJ@network_game_client_handle_messa@ (0000)
|
|
002828E8 003d:
|
|
??_C@_0DN@ODDAPCAH@network_game_client_handle_messa@ (0000)
|
|
00282928 0048:
|
|
??_C@_0EI@EDFDAGJM@network_game_client_handle_messa@ (0000)
|
|
00282970 0045:
|
|
??_C@_0EF@HHBDNBDF@network_game_client_handle_messa@ (0000)
|
|
002829B8 003f:
|
|
??_C@_0DP@KPKJEOKA@network_game_client_handle_messa@ (0000)
|
|
002829F8 004e:
|
|
??_C@_0EO@BMIPGLHI@network_game_client_handle_messa@ (0000)
|
|
00282A48 003e:
|
|
??_C@_0DO@CAKHJPLK@network_game_client_handle_messa@ (0000)
|
|
00282A88 0047:
|
|
??_C@_0EH@IEIFIIEF@network_game_client_handle_messa@ (0000)
|
|
00282AD0 0046:
|
|
??_C@_0EG@NOAJAKOF@network_game_client_handle_messa@ (0000)
|
|
00282B18 0045:
|
|
??_C@_0EF@OEBFMPPP@network_game_client_handle_messa@ (0000)
|
|
00282B60 0048:
|
|
??_C@_0EI@JILEDHBD@network_game_client_handle_messa@ (0000)
|
|
00282BA8 0044:
|
|
??_C@_0EE@JFCCKCCI@network_game_client_handle_messa@ (0000)
|
|
00282BF0 0044:
|
|
??_C@_0EE@DBJLIDDD@network_game_client_handle_messa@ (0000)
|
|
00282C34 0038:
|
|
??_C@_0DI@MEGCHKLI@network_game_client_handle_messa@ (0000)
|
|
00282C70 0042:
|
|
??_C@_0EC@DCBNODDF@network_game_client_handle_messa@ (0000)
|
|
00282CB4 0037:
|
|
??_C@_0DH@OBKILCJH@client?5received?5a?5message?5with?5a@ (0000)
|
|
00282CEC 0032:
|
|
??_C@_0DC@OIBJKL@client?5received?5client?5message?5w@ (0000)
|
|
00282D20 0054:
|
|
??_C@_0FE@FDBDJMOG@client?5?$CG?$CG?5message?5?$CG?$CG?5?$CImessage_si@ (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_engine.h"
|
|
#include "game/players.h"
|
|
#include "networking/network_client_manager.h"
|
|
#include "networking/network_client_message_handler.h"
|
|
#include "networking/network_game_manager.h"
|
|
#include "networking/network_messages.h"
|
|
|
|
/* port/linux/game/network_distributed.c's */
|
|
void network_distributed_handle_message(long machine_index, word const *message, word size);
|
|
|
|
/* ---------- constants */
|
|
|
|
#define NETWORK_CLIENT_MESSAGE_HANDLER_FILE "c:\\halo\\SOURCE\\networking\\network_client_message_handler.c"
|
|
|
|
enum
|
|
{
|
|
/* the native builds' protocol and session limits
|
|
(port/linux/include/halo_port_limits.h) */
|
|
NETWORK_GAME_MESSAGE_VERSION = HALO_PORT_NETWORK_GAME_MESSAGE_VERSION,
|
|
TRANSPORT_NONCE_LENGTH = 8,
|
|
TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH = 0x80,
|
|
MAXIMUM_NETWORK_MACHINE_COUNT = HALO_PORT_MAXIMUM_NETWORK_MACHINES,
|
|
NETWORK_GAME_NAME_LENGTH = 16,
|
|
MAXIMUM_NUMBER_OF_PLAYERS = HALO_PORT_MAXIMUM_NETWORK_PLAYERS,
|
|
JOIN_GAME_TOKEN_LENGTH = 16,
|
|
};
|
|
|
|
#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_client_state
|
|
{
|
|
_network_game_client_state_searching,
|
|
_network_game_client_state_joining,
|
|
_network_game_client_state_pregame,
|
|
_network_game_client_state_ingame,
|
|
_network_game_client_state_postgame,
|
|
NUMBER_OF_NETWORK_GAME_CLIENT_STATES,
|
|
};
|
|
|
|
enum network_game_packet_class
|
|
{
|
|
_network_game_packet_class_advertisement = 1,
|
|
_network_game_packet_class_pregame = 2,
|
|
_network_game_packet_class_ingame = 4,
|
|
_network_game_packet_class_postgame = 6,
|
|
};
|
|
|
|
/* ---------- macros */
|
|
|
|
/* ---------- structures */
|
|
|
|
struct network_game_client;
|
|
|
|
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];
|
|
|
|
/* one piece of the game settings record, which no longer fits one message
|
|
(network_server_message_handler.c sends them in order) */
|
|
struct message_server_game_settings_update
|
|
{
|
|
word total_size;
|
|
word offset;
|
|
word length;
|
|
word pad;
|
|
byte data[HALO_PORT_NETWORK_GAME_SETTINGS_FRAGMENT_SIZE];
|
|
};
|
|
|
|
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_server_pong
|
|
{
|
|
long timestamp;
|
|
};
|
|
|
|
struct message_server_machine_accepted
|
|
{
|
|
long random_seed;
|
|
short machine_index;
|
|
byte padding6[2];
|
|
};
|
|
|
|
struct message_server_machine_rejected
|
|
{
|
|
short reason;
|
|
};
|
|
|
|
struct message_server_pregame_countdown
|
|
{
|
|
short seconds_remaining;
|
|
};
|
|
|
|
struct message_server_pregame_keep_alive
|
|
{
|
|
short unused;
|
|
};
|
|
|
|
struct message_server_postgame_keep_alive
|
|
{
|
|
short unused;
|
|
};
|
|
|
|
struct message_server_begin_game
|
|
{
|
|
long unused;
|
|
};
|
|
|
|
struct message_server_graceful_game_exit_pregame
|
|
{
|
|
long unused;
|
|
};
|
|
|
|
struct message_server_game_update
|
|
{
|
|
unsigned long update_number;
|
|
long random_seed;
|
|
long game_time;
|
|
byte padding0C[2];
|
|
short local_player_count;
|
|
struct player_action player_actions[MAXIMUM_NUMBER_OF_PLAYERS];
|
|
};
|
|
|
|
struct message_server_remove_player_ingame
|
|
{
|
|
struct network_player player;
|
|
long reason;
|
|
};
|
|
|
|
struct message_server_game_over
|
|
{
|
|
long unused;
|
|
};
|
|
|
|
struct message_server_switch_to_pregame
|
|
{
|
|
long unused;
|
|
};
|
|
|
|
struct message_server_graceful_game_exit_postgame
|
|
{
|
|
long unused;
|
|
};
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static boolean network_game_client_handle_message_server_game_advertise(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_pong(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_machine_accepted(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_machine_rejected(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_game_settings_update(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_pregame_countdown(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_pregame_keep_alive(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_postgame_keep_alive(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_begin_game(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_graceful_game_exit_pregame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_game_update(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_add_player_ingame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_remove_player_ingame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_game_over(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_switch_to_pregame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
static boolean network_game_client_handle_message_server_graceful_game_exit_postgame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address);
|
|
|
|
/* ---------- globals */
|
|
|
|
/* ---------- public code */
|
|
|
|
boolean network_game_client_handle_message(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = TRUE;
|
|
word message_type;
|
|
byte packet_type;
|
|
|
|
/* (a header and at least the packet type after it, of the size the
|
|
header says: else the stream is broken) */
|
|
if (message && (message_size < (short)(sizeof(message_header) + sizeof(byte)) ||
|
|
message_size != GET_MESSAGE_SIZE(*message)))
|
|
{
|
|
network_event("client received a message of a bad size (%d)", message_size);
|
|
return FALSE;
|
|
}
|
|
|
|
match_assert(
|
|
NETWORK_CLIENT_MESSAGE_HANDLER_FILE,
|
|
0x2F,
|
|
client && message && (message_size == GET_MESSAGE_SIZE(*message)) && source_address);
|
|
|
|
message_type = (byte)GET_MESSAGE_TYPE(*message);
|
|
if (GET_MESSAGE_FLAGS(*message))
|
|
{
|
|
network_event("client received client message with invalid flags");
|
|
}
|
|
/* port: the host sends every message of the game over its connection,
|
|
only its advertisement and its answer to a ping in datagrams (and the
|
|
distributed netcode's messages, _message_type_data, which are checked as
|
|
the host's below): a datagram, which anyone can send as the host, is
|
|
taken for nothing else */
|
|
else if (message_type == _message_type_packet && network_connection_last_read_was_unreliable() &&
|
|
((byte *)message)[message_size - 1] != _message_server_game_advertise &&
|
|
((byte *)message)[message_size - 1] != _message_server_pong)
|
|
{
|
|
static unsigned long last_logged_time;
|
|
static boolean logged;
|
|
unsigned long now = system_milliseconds();
|
|
|
|
if (!logged || now - last_logged_time >= 1000)
|
|
{
|
|
network_event("ignoring a game message of type %d in a datagram @ %s",
|
|
((byte *)message)[message_size - 1], transport_address_to_string(source_address));
|
|
last_logged_time = now;
|
|
logged = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (message_type)
|
|
{
|
|
case _message_type_packet:
|
|
packet_type = ((byte *)message)[message_size - 1];
|
|
switch (packet_type)
|
|
{
|
|
case _message_server_game_advertise:
|
|
result = network_game_client_handle_message_server_game_advertise(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_game_advertise() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_pong:
|
|
result = network_game_client_handle_message_server_pong(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_pong() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_machine_accepted:
|
|
result = network_game_client_handle_message_server_machine_accepted(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_machine_accepted() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_machine_rejected:
|
|
result = network_game_client_handle_message_server_machine_rejected(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_machine_rejected() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_game_settings_update:
|
|
result = network_game_client_handle_message_server_game_settings_update(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_game_settings_update() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_pregame_countdown:
|
|
result = network_game_client_handle_message_server_pregame_countdown(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_pregame_countdown() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_pregame_keep_alive:
|
|
result = network_game_client_handle_message_server_pregame_keep_alive(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_pregame_keep_alive() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_postgame_keep_alive:
|
|
result = network_game_client_handle_message_server_postgame_keep_alive(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_postgame_keep_alive() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_begin_game:
|
|
result = network_game_client_handle_message_server_begin_game(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_begin_game() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_graceful_game_exit_pregame:
|
|
result = network_game_client_handle_message_server_graceful_game_exit_pregame(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_graceful_game_exit_pregame() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_game_update:
|
|
result = network_game_client_handle_message_server_game_update(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_game_update() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_add_player_ingame:
|
|
result = network_game_client_handle_message_server_add_player_ingame(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_add_player_ingame() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_remove_player_ingame:
|
|
result = network_game_client_handle_message_server_remove_player_ingame(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_remove_player_ingame() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_game_over:
|
|
result = network_game_client_handle_message_server_game_over(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_game_over() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_switch_to_pregame:
|
|
result = network_game_client_handle_message_server_switch_to_pregame(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_switch_to_pregame() failed");
|
|
}
|
|
break;
|
|
|
|
case _message_server_graceful_game_exit_postgame:
|
|
result = network_game_client_handle_message_server_graceful_game_exit_postgame(
|
|
client,
|
|
message,
|
|
message_size,
|
|
source_address);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_message_server_graceful_game_exit_postgame() failed");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
network_event(
|
|
"unknown packet type received from system @ address: %s",
|
|
transport_address_to_string(source_address));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case _message_type_data:
|
|
/* the distributed netcode's messages (port/linux/NETCODE.md),
|
|
the host's alone: over its connection, or datagrams from its
|
|
address */
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
network_distributed_handle_message(NONE, message, message_size);
|
|
}
|
|
else
|
|
{
|
|
/* (port: once a second at most: anyone can send them,
|
|
one a tick) */
|
|
static unsigned long last_logged_time;
|
|
static boolean logged;
|
|
unsigned long now = system_milliseconds();
|
|
|
|
if (!logged || now - last_logged_time >= 1000)
|
|
{
|
|
network_event(
|
|
"ignoring a distributed message from a system that is not the host @ %s",
|
|
transport_address_to_string(source_address));
|
|
last_logged_time = now;
|
|
logged = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _message_type_error:
|
|
if (message_size >= MINIMUM_TRANSPORT_ERROR_MESSAGE_SIZE)
|
|
{
|
|
byte *error_message = (byte *)(message + 1);
|
|
|
|
/* (port: printable ASCII only, so that it forges no line
|
|
of the log) */
|
|
char text[TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH + 1];
|
|
long index;
|
|
|
|
for (index = 0; index < TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH && error_message[index]; index++)
|
|
text[index] = error_message[index] >= 0x20 && error_message[index] < 0x7F ? (char)error_message[index] : '?';
|
|
text[index] = 0;
|
|
network_event(
|
|
"client received low-level error message: error= #%d (%s)",
|
|
error_message[TRANSPORT_ERROR_MESSAGE_TEXT_LENGTH],
|
|
text);
|
|
}
|
|
else
|
|
{
|
|
network_event("client received a malformed/damaged message from a server");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
network_event("client received a message with an unknown message type");
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
static boolean network_game_client_handle_message_server_game_advertise(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_searching)
|
|
{
|
|
struct message_server_game_advertise advertisement;
|
|
short packet_type = _message_server_game_advertise;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&advertisement,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_advertisement))
|
|
{
|
|
if (transport_is_nonce(&advertisement, TRANSPORT_NONCE_LENGTH))
|
|
{
|
|
network_game_client_new_advertised_game(client, &advertisement);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_game_advertise packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* port: once a minute at most (every host on the network
|
|
advertises every few seconds, all game long) */
|
|
static unsigned long ignored_time = 0;
|
|
unsigned long now = system_milliseconds();
|
|
|
|
if (!ignored_time || now - ignored_time >= 60000)
|
|
{
|
|
ignored_time = now ? now : 1;
|
|
network_event("ignoring an advertised game because we are not looking for new games");
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_pong(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_searching)
|
|
{
|
|
struct message_server_pong pong;
|
|
short packet_type = _message_server_pong;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&pong,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_advertisement))
|
|
{
|
|
network_game_client_ponged(client, source_address, pong.timestamp);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_pong packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a pong message because we are not listening for them");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_machine_accepted(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = TRUE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address) &&
|
|
network_game_client_get_state(client, NULL) == _network_game_client_state_joining)
|
|
{
|
|
struct message_server_machine_accepted acceptance;
|
|
short packet_type = _message_server_machine_accepted;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&acceptance,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
network_game_client_accepted_into_game(client, source_address, &acceptance);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_machine_accepted packet");
|
|
result = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_machine_accepted message; either a bad machine or we aren't joining");
|
|
/* port: ignored, not failed (anyone may send a searching client a
|
|
datagram, and a failure ends its search) */
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_machine_rejected(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = TRUE;
|
|
|
|
/* (joining, or accepted into a game in progress that filled up before
|
|
its players were added: network_game_server_refuse_late_joiner) */
|
|
if (network_game_client_address_matches_server(client, source_address) &&
|
|
(network_game_client_get_state(client, NULL) == _network_game_client_state_joining ||
|
|
network_game_client_get_state(client, NULL) == _network_game_client_state_pregame))
|
|
{
|
|
struct message_server_machine_rejected rejection;
|
|
short packet_type = _message_server_machine_rejected;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&rejection,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
network_game_client_rejected_by_game(client, source_address, rejection.reason);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_machine_rejected packet");
|
|
result = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_machine_rejected message; either a bad machine or we aren't joining");
|
|
/* port: ignored, not failed (anyone may send a searching client a
|
|
datagram, and a failure ends its search) */
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* the game settings record as its pieces arrive; it is applied once the last
|
|
piece is in */
|
|
static struct network_game network_game_client_settings_staging;
|
|
static long network_game_client_settings_staging_size = 0;
|
|
|
|
static boolean network_game_client_receive_game_settings_piece(
|
|
struct network_game_client *client,
|
|
struct message_server_game_settings_update const *piece)
|
|
{
|
|
boolean result = TRUE;
|
|
|
|
if (piece->total_size != sizeof(network_game_client_settings_staging) ||
|
|
piece->length > sizeof(piece->data) ||
|
|
piece->offset + piece->length > sizeof(network_game_client_settings_staging))
|
|
{
|
|
network_event("got a message_server_game_settings_update piece for a different game layout");
|
|
network_game_client_settings_staging_size = 0;
|
|
result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* each record is sent in order from its start, over a stream */
|
|
if (piece->offset == 0)
|
|
{
|
|
network_game_client_settings_staging_size = 0;
|
|
}
|
|
if (piece->offset != network_game_client_settings_staging_size)
|
|
{
|
|
network_event("got a message_server_game_settings_update piece out of order; waiting for the next record");
|
|
network_game_client_settings_staging_size = 0;
|
|
}
|
|
else
|
|
{
|
|
csmemcpy(
|
|
(byte *)&network_game_client_settings_staging + piece->offset,
|
|
piece->data,
|
|
piece->length);
|
|
network_game_client_settings_staging_size += piece->length;
|
|
if (network_game_client_settings_staging_size == piece->total_size)
|
|
{
|
|
network_game_client_settings_staging_size = 0;
|
|
result = network_game_client_game_settings_updated(client, &network_game_client_settings_staging);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_game_settings_updated() failed");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_game_settings_update(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x169, client != NULL);
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x16A, source_address != NULL);
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_pregame)
|
|
{
|
|
struct message_server_game_settings_update piece;
|
|
short packet_type = _message_server_game_settings_update;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&piece,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
result = network_game_client_receive_game_settings_piece(client, &piece);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_game_settings_update packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_game_settings_update message; not in pregame state");
|
|
result = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_game_settings_update; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_pregame_countdown(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x19B, client != NULL);
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x19C, source_address != NULL);
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_pregame)
|
|
{
|
|
struct message_server_pregame_countdown countdown;
|
|
short packet_type = _message_server_pregame_countdown;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&countdown,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
network_game_client_countdown_timer_update(client, countdown.seconds_remaining);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_pregame_countdown packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_pregame_countdown message; not in pregame state");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_pregame_countdown; came from a bad machine");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_pregame_keep_alive(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x1C4, client != NULL);
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x1C5, source_address != NULL);
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_pregame)
|
|
{
|
|
struct message_server_pregame_keep_alive keep_alive;
|
|
short packet_type = _message_server_pregame_keep_alive;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (!decode_network_game_message(
|
|
&keep_alive,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
network_event("failed to decode a message_server_pregame_keep_alive packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_pregame_keep_alive message; not in pregame state");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_pregame_keep_alive; came from a bad machine");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_postgame_keep_alive(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x1EE, client != NULL);
|
|
match_assert(NETWORK_CLIENT_MESSAGE_HANDLER_FILE, 0x1EF, source_address != NULL);
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_postgame)
|
|
{
|
|
struct message_server_postgame_keep_alive keep_alive;
|
|
short packet_type = _message_server_postgame_keep_alive;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (!decode_network_game_message(
|
|
&keep_alive,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_postgame))
|
|
{
|
|
network_event("failed to decode a message_server_postgame_keep_alive packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_postgame_keep_alive message; not in postgame state");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_postgame_keep_alive; came from a bad machine");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_begin_game(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_pregame)
|
|
{
|
|
struct message_server_begin_game begin_game;
|
|
short packet_type = _message_server_begin_game;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
/* (it decodes 16 bits of its long: the rest zero) */
|
|
csmemset(&begin_game, 0, sizeof(begin_game));
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&begin_game,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
/* (a game in progress: the host's time, network_client_manager.c;
|
|
the message carries 16 bits of it: the rest from the first
|
|
game update, network_game_client_handle_game_update) */
|
|
network_game_client_late_join_time = (long)((unsigned long)begin_game.unused & 0xFFFF);
|
|
result = network_game_client_game_has_started(client);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_game_has_started() failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_begin_game packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_begin_game message; we are not in pregame");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_begin_game message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_graceful_game_exit_pregame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_pregame)
|
|
{
|
|
struct message_server_graceful_game_exit_pregame game_exit;
|
|
short packet_type = _message_server_graceful_game_exit_pregame;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&game_exit,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_pregame))
|
|
{
|
|
network_game_client_game_shutdown(client);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_graceful_game_exit_pregame packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_graceful_game_exit_pregame message; we are not in pregame");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_graceful_game_exit_pregame message; came from a bad machine");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_game_update(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_ingame)
|
|
{
|
|
struct message_server_game_update game_update;
|
|
short packet_type = _message_server_game_update;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&game_update,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_ingame))
|
|
{
|
|
result = network_game_client_handle_game_update(client, &game_update);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_handle_game_update() failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_game_update packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_game_update message; we are not in game");
|
|
result = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_game_update message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_add_player_ingame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_ingame)
|
|
{
|
|
struct network_player player;
|
|
short packet_type = _message_server_add_player_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_ingame))
|
|
{
|
|
/* (the distributed netcode: a player this machine cannot add
|
|
does not end its game) */
|
|
if (!network_game_client_add_player_to_game(client, &player))
|
|
{
|
|
network_event("network_game_client_add_player_to_game() failed");
|
|
}
|
|
result = TRUE;
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_add_player_ingame packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_add_player_ingame message; we are not in game");
|
|
result = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_add_player_ingame message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_remove_player_ingame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_ingame)
|
|
{
|
|
struct message_server_remove_player_ingame removal;
|
|
short packet_type = _message_server_remove_player_ingame;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (decode_network_game_message(
|
|
&removal,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_ingame))
|
|
{
|
|
/* (nor one it cannot remove) */
|
|
if (!network_game_client_remove_player(client, &removal.player, removal.reason))
|
|
{
|
|
network_event("network_game_client_remove_player() failed");
|
|
}
|
|
result = TRUE;
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to decode a message_server_remove_player_ingame packet");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_remove_player_ingame message; we are not in game");
|
|
result = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_remove_player_ingame message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_game_over(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_ingame)
|
|
{
|
|
struct message_server_game_over game_over;
|
|
short packet_type = _message_server_game_over;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (!decode_network_game_message(
|
|
&game_over,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_ingame))
|
|
{
|
|
network_event("failed to decode a message_server_game_over message (not critical)");
|
|
}
|
|
|
|
network_game_client_switch_to_postgame(client);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_game_over message; we are not in game");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_game_over message; came from a bad machine");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_switch_to_pregame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_postgame)
|
|
{
|
|
struct message_server_switch_to_pregame switch_to_pregame;
|
|
short packet_type = _message_server_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_postgame))
|
|
{
|
|
network_event("failed to decode a message_server_switch_to_pregame packet");
|
|
}
|
|
|
|
result = network_game_client_switch_to_pregame(client);
|
|
if (!result)
|
|
{
|
|
network_event("network_game_client_switch_to_pregame() failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_switch_to_pregame message; we are not in post-game");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_switch_to_pregame message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static boolean network_game_client_handle_message_server_graceful_game_exit_postgame(
|
|
struct network_game_client *client,
|
|
word *message,
|
|
short message_size,
|
|
struct transport_address *source_address)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
if (network_game_client_address_matches_server(client, source_address))
|
|
{
|
|
if (network_game_client_get_state(client, NULL) == _network_game_client_state_postgame)
|
|
{
|
|
struct message_server_graceful_game_exit_postgame game_exit;
|
|
short packet_type = _message_server_graceful_game_exit_postgame;
|
|
short packet_version = NETWORK_GAME_MESSAGE_VERSION;
|
|
|
|
message_size -= sizeof(word);
|
|
if (!decode_network_game_message(
|
|
&game_exit,
|
|
message + 1,
|
|
&message_size,
|
|
&packet_type,
|
|
&packet_version,
|
|
_network_game_packet_class_postgame))
|
|
{
|
|
network_event("failed to decode a message_server_graceful_game_exit_postgame packet (not critical)");
|
|
}
|
|
|
|
network_game_client_game_shutdown(client);
|
|
}
|
|
else
|
|
{
|
|
network_event("failed to handle a message_server_graceful_game_exit_postgame message; we are not in post-game");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
network_event("ignoring a message_server_graceful_game_exit_postgame message; came from a bad machine");
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|