diff options
Diffstat (limited to 'src/net_server.c')
-rw-r--r-- | src/net_server.c | 128 |
1 files changed, 104 insertions, 24 deletions
diff --git a/src/net_server.c b/src/net_server.c index 904d932e..ae46be4a 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -41,10 +41,15 @@ #include "net_io.h" #include "net_loop.h" #include "net_packet.h" +#include "net_query.h" #include "net_server.h" #include "net_sdl.h" #include "net_structrw.h" +// How often to refresh our registration with the master server. + +#define MASTER_REFRESH_PERIOD 20 * 60 /* 20 minutes */ + typedef enum { // waiting for the game to start @@ -65,6 +70,11 @@ typedef struct int last_send_time; char *name; + // Time that this client connected to the server. + // This is used to determine the controller (oldest client). + + unsigned int connect_time; + // Last time new gamedata was received from this client int last_gamedata_time; @@ -128,6 +138,11 @@ static unsigned int sv_gamemode; static unsigned int sv_gamemission; static net_gamesettings_t sv_settings; +// For registration with master server: + +static net_addr_t *master_server = NULL; +static unsigned int master_refresh_time; + // receive window static unsigned int recvwindow_start; @@ -372,19 +387,29 @@ static void NET_SV_AdvanceWindow(void) static net_client_t *NET_SV_Controller(void) { + net_client_t *best; int i; - // first client in the list is the controller + // Find the oldest client (first to connect). + + best = NULL; for (i=0; i<MAXNETNODES; ++i) { - if (ClientConnected(&clients[i]) && !clients[i].drone) + // Can't be controller? + + if (!ClientConnected(&clients[i]) || clients[i].drone) { - return &clients[i]; + continue; + } + + if (best == NULL || clients[i].connect_time < best->connect_time) + { + best = &clients[i]; } } - return NULL; + return best; } // Given an address, find the corresponding client @@ -424,6 +449,7 @@ static void NET_SV_InitNewClient(net_client_t *client, char *player_name) { client->active = true; + client->connect_time = I_GetTimeMS(); NET_Conn_InitServer(&client->connection, addr); client->addr = addr; client->last_send_time = -1; @@ -447,10 +473,8 @@ static void NET_SV_ParseSYN(net_packet_t *packet, net_addr_t *addr) { unsigned int magic; - unsigned int cl_gamemode, cl_gamemission; - unsigned int cl_recording_lowres; - unsigned int cl_drone; unsigned int is_freedoom; + net_connect_data_t data; md5_digest_t deh_md5sum, wad_md5sum; char *player_name; char *client_version; @@ -501,10 +525,7 @@ static void NET_SV_ParseSYN(net_packet_t *packet, // read the game mode and mission - if (!NET_ReadInt16(packet, &cl_gamemode) - || !NET_ReadInt16(packet, &cl_gamemission) - || !NET_ReadInt8(packet, &cl_recording_lowres) - || !NET_ReadInt8(packet, &cl_drone) + if (!NET_ReadConnectData(packet, &data) || !NET_ReadMD5Sum(packet, wad_md5sum) || !NET_ReadMD5Sum(packet, deh_md5sum) || !NET_ReadInt8(packet, &is_freedoom)) @@ -512,7 +533,7 @@ static void NET_SV_ParseSYN(net_packet_t *packet, return; } - if (!D_ValidGameMode(cl_gamemission, cl_gamemode)) + if (!D_ValidGameMode(data.gamemission, data.gamemode)) { return; } @@ -579,7 +600,7 @@ static void NET_SV_ParseSYN(net_packet_t *packet, NET_SV_AssignPlayers(); num_players = NET_SV_NumPlayers(); - if ((!cl_drone && num_players >= MAXPLAYERS) + if ((!data.drone && num_players >= MAXPLAYERS) || NET_SV_NumClients() >= MAXNETNODES) { NET_SV_SendReject(addr, "Server is full!"); @@ -592,10 +613,10 @@ static void NET_SV_ParseSYN(net_packet_t *packet, // Adopt the game mode and mission of the first connecting client - if (num_players == 0 && !cl_drone) + if (num_players == 0 && !data.drone) { - sv_gamemode = cl_gamemode; - sv_gamemission = cl_gamemission; + sv_gamemode = data.gamemode; + sv_gamemission = data.gamemission; } // Save the MD5 checksums @@ -607,7 +628,7 @@ static void NET_SV_ParseSYN(net_packet_t *packet, // Check the connecting client is playing the same game as all // the other clients - if (cl_gamemode != sv_gamemode || cl_gamemission != sv_gamemission) + if (data.gamemode != sv_gamemode || data.gamemission != sv_gamemission) { NET_SV_SendReject(addr, "You are playing the wrong game!"); return; @@ -617,8 +638,8 @@ static void NET_SV_ParseSYN(net_packet_t *packet, NET_SV_InitNewClient(client, addr, player_name); - client->recording_lowres = cl_recording_lowres; - client->drone = cl_drone; + client->recording_lowres = data.lowres_turn; + client->drone = data.drone; } if (client->connection.state == NET_CONN_STATE_WAITING_ACK) @@ -681,6 +702,8 @@ static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client) } } + settings.num_players = NET_SV_NumPlayers(); + nowtime = I_GetTimeMS(); // Send start packets to each connected node @@ -695,8 +718,8 @@ static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client) startpacket = NET_Conn_NewReliable(&clients[i].connection, NET_PACKET_TYPE_GAMESTART); - NET_WriteInt8(startpacket, NET_SV_NumPlayers()); - NET_WriteInt8(startpacket, clients[i].player_number); + settings.consoleplayer = clients[i].player_number; + NET_WriteSettings(startpacket, &settings); } @@ -1070,6 +1093,7 @@ void NET_SV_SendQueryResponse(net_addr_t *addr) { net_packet_t *reply; net_querydata_t querydata; + int p; // Version @@ -1089,9 +1113,22 @@ void NET_SV_SendQueryResponse(net_addr_t *addr) querydata.gamemode = sv_gamemode; querydata.gamemission = sv_gamemission; - // Server description. This is currently hard-coded. + //! + // @arg <name> + // + // When starting a network server, specify a name for the server. + // + + p = M_CheckParmWithArgs("-servername", 1); - querydata.description = "Chocolate Doom server"; + if (p > 0) + { + querydata.description = myargv[p + 1]; + } + else + { + querydata.description = "Unnamed server"; + } // Send it and we're done. @@ -1109,6 +1146,14 @@ static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr) net_client_t *client; unsigned int packet_type; + // Response from master server? + + if (addr != NULL && addr == master_server) + { + NET_Query_MasterResponse(packet); + return; + } + // Find which client this packet came from client = NET_SV_FindClient(addr); @@ -1514,6 +1559,32 @@ void NET_SV_Init(void) server_initialized = true; } +void NET_SV_RegisterWithMaster(void) +{ + //! + // When running a server, don't register with the global master server. + // + // @category net + // + + if (!M_CheckParm("-privateserver")) + { + master_server = NET_Query_ResolveMaster(server_context); + } + else + { + master_server = NULL; + } + + // Send request. + + if (master_server != NULL) + { + NET_Query_AddToMaster(master_server); + master_refresh_time = I_GetTimeMS(); + } +} + // Run server code to check for new packets/send packets as the server // requires @@ -1528,12 +1599,21 @@ void NET_SV_Run(void) return; } - while (NET_RecvPacket(server_context, &addr, &packet)) + while (NET_RecvPacket(server_context, &addr, &packet)) { NET_SV_Packet(packet, addr); NET_FreePacket(packet); } + // Possibly refresh our registration with the master server. + + if (master_server != NULL + && I_GetTimeMS() - master_refresh_time > MASTER_REFRESH_PERIOD * 1000) + { + NET_Query_AddToMaster(master_server); + master_refresh_time = I_GetTimeMS(); + } + // "Run" any clients that may have things to do, independent of responses // to received packets |