Merge pull request #943 from fragglet/sdl2-branch

Introduce a network protocol versioning scheme.

This will allow backwards-compatible protocol changes in future,
and also allow forks to remain compatible with Chocolate Doom.
This commit is contained in:
Simon Howard 2017-10-01 02:19:15 -04:00 committed by GitHub
commit 78206090eb
10 changed files with 349 additions and 245 deletions

View file

@ -426,6 +426,41 @@ void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic)
NET_CL_SendTics(starttic, endtic);
}
// Parse a SYN packet received back from the server indicating a successful
// connection attempt.
static void NET_CL_ParseSYN(net_packet_t *packet)
{
net_protocol_t protocol;
char *server_version;
server_version = NET_ReadSafeString(packet);
if (server_version == NULL)
{
return;
}
protocol = NET_ReadProtocol(packet);
if (protocol == NET_PROTOCOL_UNKNOWN)
{
return;
}
// We are now successfully connected.
client_connection.state = NET_CONN_STATE_CONNECTED;
client_connection.protocol = protocol;
// Even though we have negotiated a compatible protocol, the game may still
// desync. Chocolate Doom's philosophy makes this unlikely, but if we're
// playing with a forked version, or even against a different version that
// fixes a compatibility issue, we may still have problems.
if (strcmp(server_version, PACKAGE_STRING) != 0)
{
fprintf(stderr, "NET_CL_ParseSYN: This is '%s', but the server is "
"'%s'. It is possible that this mismatch may cause the game "
"to desync.\n", PACKAGE_STRING, server_version);
}
}
// data received while we are waiting for the game to start
static void NET_CL_ParseWaitingData(net_packet_t *packet)
@ -795,16 +830,14 @@ static void NET_CL_ParseConsoleMessage(net_packet_t *packet)
{
char *msg;
msg = NET_ReadString(packet);
msg = NET_ReadSafeString(packet);
if (msg == NULL)
{
return;
}
printf("Message from server: ");
NET_SafePuts(msg);
printf("Message from server:\n%s\n", msg);
}
// parse a received packet
@ -826,6 +859,10 @@ static void NET_CL_ParsePacket(net_packet_t *packet)
{
switch (packet_type)
{
case NET_PACKET_TYPE_SYN:
NET_CL_ParseSYN(packet);
break;
case NET_PACKET_TYPE_WAITING_DATA:
NET_CL_ParseWaitingData(packet);
break;
@ -921,14 +958,14 @@ static void NET_CL_SendSYN(net_connect_data_t *data)
NET_WriteInt16(packet, NET_PACKET_TYPE_SYN);
NET_WriteInt32(packet, NET_MAGIC_NUMBER);
NET_WriteString(packet, PACKAGE_STRING);
NET_WriteProtocolList(packet);
NET_WriteConnectData(packet, data);
NET_WriteString(packet, net_player_name);
NET_Conn_SendPacket(&client_connection, packet);
NET_FreePacket(packet);
}
// connect to a server
// Connect to a server
boolean NET_CL_Connect(net_addr_t *addr, net_connect_data_t *data)
{
int start_time;
@ -959,7 +996,7 @@ boolean NET_CL_Connect(net_addr_t *addr, net_connect_data_t *data)
// Initialize connection
NET_Conn_InitClient(&client_connection, addr);
NET_Conn_InitClient(&client_connection, addr, NET_PROTOCOL_UNKNOWN);
// try to connect

View file

@ -19,6 +19,7 @@
#include "doomtype.h"
#include "d_mode.h"
#include "i_system.h"
#include "i_timer.h"
#include "net_common.h"
@ -34,9 +35,19 @@
#define KEEPALIVE_PERIOD 1
// String names for the enum values in net_protocol_t, which are what is
// sent over the wire. Every enum value must have an entry in this list.
static struct
{
net_protocol_t protocol;
const char *name;
} protocol_names[] = {
{NET_PROTOCOL_CHOCOLATE_DOOM_0, "CHOCOLATE_DOOM_0"},
};
// reliable packet that is guaranteed to reach its destination
struct net_reliable_packet_s
struct net_reliable_packet_s
{
net_packet_t *packet;
int last_send_time;
@ -44,11 +55,13 @@ struct net_reliable_packet_s
net_reliable_packet_t *next;
};
static void NET_Conn_Init(net_connection_t *conn, net_addr_t *addr)
static void NET_Conn_Init(net_connection_t *conn, net_addr_t *addr,
net_protocol_t protocol)
{
conn->last_send_time = -1;
conn->num_retries = 0;
conn->addr = addr;
conn->protocol = protocol;
conn->reliable_packets = NULL;
conn->reliable_send_seq = 0;
conn->reliable_recv_seq = 0;
@ -56,18 +69,20 @@ static void NET_Conn_Init(net_connection_t *conn, net_addr_t *addr)
// Initialize as a client connection
void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr)
void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr,
net_protocol_t protocol)
{
NET_Conn_Init(conn, addr);
NET_Conn_Init(conn, addr, protocol);
conn->state = NET_CONN_STATE_CONNECTING;
}
// Initialize as a server connection
void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr)
void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr,
net_protocol_t protocol)
{
NET_Conn_Init(conn, addr);
conn->state = NET_CONN_STATE_WAITING_ACK;
NET_Conn_Init(conn, addr, protocol);
conn->state = NET_CONN_STATE_CONNECTED;
}
// Send a packet to a connection
@ -80,38 +95,6 @@ void NET_Conn_SendPacket(net_connection_t *conn, net_packet_t *packet)
NET_SendPacket(conn->addr, packet);
}
// parse an ACK packet from a client
static void NET_Conn_ParseACK(net_connection_t *conn, net_packet_t *packet)
{
net_packet_t *reply;
if (conn->state == NET_CONN_STATE_CONNECTING)
{
// We are a client
// received a response from the server to our SYN
conn->state = NET_CONN_STATE_CONNECTED;
// We must send an ACK reply to the server's ACK
reply = NET_NewPacket(10);
NET_WriteInt16(reply, NET_PACKET_TYPE_ACK);
NET_Conn_SendPacket(conn, reply);
NET_FreePacket(reply);
}
if (conn->state == NET_CONN_STATE_WAITING_ACK)
{
// We are a server
// Client is connected
conn->state = NET_CONN_STATE_CONNECTED;
}
}
static void NET_Conn_ParseDisconnect(net_connection_t *conn, net_packet_t *packet)
{
net_packet_t *reply;
@ -151,7 +134,7 @@ static void NET_Conn_ParseReject(net_connection_t *conn, net_packet_t *packet)
{
char *msg;
msg = NET_ReadString(packet);
msg = NET_ReadSafeString(packet);
if (msg == NULL)
{
@ -165,8 +148,7 @@ static void NET_Conn_ParseReject(net_connection_t *conn, net_packet_t *packet)
conn->state = NET_CONN_STATE_DISCONNECTED;
conn->disconnect_reason = NET_DISCONNECT_REMOTE;
printf("Rejected by server: ");
NET_SafePuts(msg);
printf("Rejected by server: %s\n", msg);
}
}
@ -282,9 +264,6 @@ boolean NET_Conn_Packet(net_connection_t *conn, net_packet_t *packet,
switch (*packet_type)
{
case NET_PACKET_TYPE_ACK:
NET_Conn_ParseACK(conn, packet);
break;
case NET_PACKET_TYPE_DISCONNECT:
NET_Conn_ParseDisconnect(conn, packet);
break;
@ -370,35 +349,6 @@ void NET_Conn_Run(net_connection_t *conn)
conn->reliable_packets->last_send_time = nowtime;
}
}
else if (conn->state == NET_CONN_STATE_WAITING_ACK)
{
if (conn->last_send_time < 0
|| nowtime - conn->last_send_time > 1000)
{
// it has been a second since the last ACK was sent, and
// still no reply.
if (conn->num_retries < MAX_RETRIES)
{
// send another ACK
packet = NET_NewPacket(10);
NET_WriteInt16(packet, NET_PACKET_TYPE_ACK);
NET_Conn_SendPacket(conn, packet);
NET_FreePacket(packet);
conn->last_send_time = nowtime;
++conn->num_retries;
}
else
{
// no more retries allowed.
conn->state = NET_CONN_STATE_DISCONNECTED;
conn->disconnect_reason = NET_DISCONNECT_TIMEOUT;
}
}
}
else if (conn->state == NET_CONN_STATE_DISCONNECTING)
{
// Waiting for a reply to our DISCONNECT request.
@ -532,3 +482,106 @@ boolean NET_ValidGameSettings(GameMode_t mode, GameMission_t mission,
return true;
}
static net_protocol_t ParseProtocolName(const char *name)
{
int i;
for (i = 0; i < arrlen(protocol_names); ++i)
{
if (!strcmp(protocol_names[i].name, name))
{
return protocol_names[i].protocol;
}
}
return NET_PROTOCOL_UNKNOWN;
}
// NET_ReadProtocol reads a single string-format protocol name from the given
// packet, returning NET_PROTOCOL_UNKNOWN if the string describes an unknown
// protocol.
net_protocol_t NET_ReadProtocol(net_packet_t *packet)
{
const char *name;
name = NET_ReadString(packet);
if (name == NULL)
{
return NET_PROTOCOL_UNKNOWN;
}
return ParseProtocolName(name);
}
// NET_WriteProtocol writes a single string-format protocol name to a packet.
void NET_WriteProtocol(net_packet_t *packet, net_protocol_t protocol)
{
int i;
for (i = 0; i < arrlen(protocol_names); ++i)
{
if (protocol_names[i].protocol == protocol)
{
NET_WriteString(packet, protocol_names[i].name);
return;
}
}
// If you add an entry to the net_protocol_t enum, a corresponding entry
// must be added to the protocol_names list.
I_Error("NET_WriteProtocol: protocol %d missing from protocol_names "
"list; please add it.", protocol);
}
// NET_ReadProtocolList reads a list of string-format protocol names from
// the given packet, returning a single protocol number. The protocol that is
// returned is the last protocol in the list that is a supported protocol. If
// no recognized protocols are read, NET_PROTOCOL_UNKNOWN is returned.
net_protocol_t NET_ReadProtocolList(net_packet_t *packet)
{
net_protocol_t result;
unsigned int num_protocols;
int i;
if (!NET_ReadInt8(packet, &num_protocols))
{
return NET_PROTOCOL_UNKNOWN;
}
result = NET_PROTOCOL_UNKNOWN;
for (i = 0; i < num_protocols; ++i)
{
net_protocol_t p;
const char *name;
name = NET_ReadString(packet);
if (name == NULL)
{
return NET_PROTOCOL_UNKNOWN;
}
p = ParseProtocolName(name);
if (p != NET_PROTOCOL_UNKNOWN)
{
result = p;
}
}
return result;
}
// NET_WriteProtocolList writes a list of string-format protocol names into
// the given packet, all the supported protocols in the net_protocol_t enum.
void NET_WriteProtocolList(net_packet_t *packet)
{
int i;
NET_WriteInt8(packet, NET_NUM_PROTOCOLS);
for (i = 0; i < NET_NUM_PROTOCOLS; ++i)
{
NET_WriteProtocol(packet, i);
}
}

View file

@ -21,28 +21,18 @@
#include "net_defs.h"
#include "net_packet.h"
typedef enum
typedef enum
{
// sending syn packets, waiting for an ACK reply
// (client side)
// Client has sent a SYN, is waiting for a SYN in response.
NET_CONN_STATE_CONNECTING,
// received a syn, sent an ack, waiting for an ack reply
// (server side)
NET_CONN_STATE_WAITING_ACK,
// successfully connected
// Successfully connected.
NET_CONN_STATE_CONNECTED,
// sent a DISCONNECT packet, waiting for a DISCONNECT_ACK reply
// Sent a DISCONNECT packet, waiting for a DISCONNECT_ACK reply
NET_CONN_STATE_DISCONNECTING,
// client successfully disconnected
// Client successfully disconnected
NET_CONN_STATE_DISCONNECTED,
// We are disconnected, but in a sleep state, waiting for several
@ -50,7 +40,6 @@ typedef enum
// to arrive, and we need to send another one. We keep this as
// a valid connection for a few seconds until we are sure that
// the other end has successfully disconnected as well.
NET_CONN_STATE_DISCONNECTED_SLEEP,
} net_connstate_t;
@ -82,6 +71,7 @@ typedef struct
net_connstate_t state;
net_disconnect_reason_t disconnect_reason;
net_addr_t *addr;
net_protocol_t protocol;
int last_send_time;
int num_retries;
int keepalive_send_time;
@ -93,18 +83,25 @@ typedef struct
void NET_Conn_SendPacket(net_connection_t *conn, net_packet_t *packet);
void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr);
void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr);
void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr,
net_protocol_t protocol);
void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr,
net_protocol_t protocol);
boolean NET_Conn_Packet(net_connection_t *conn, net_packet_t *packet,
unsigned int *packet_type);
void NET_Conn_Disconnect(net_connection_t *conn);
void NET_Conn_Run(net_connection_t *conn);
net_packet_t *NET_Conn_NewReliable(net_connection_t *conn, int packet_type);
// Other miscellaneous common functions
// Protocol list exchange.
net_protocol_t NET_ReadProtocol(net_packet_t *packet);
void NET_WriteProtocol(net_packet_t *packet, net_protocol_t protocol);
net_protocol_t NET_ReadProtocolList(net_packet_t *packet);
void NET_WriteProtocolList(net_packet_t *packet);
// Other miscellaneous common functions
unsigned int NET_ExpandTicNum(unsigned int relative, unsigned int b);
boolean NET_ValidGameSettings(GameMode_t mode, GameMission_t mission,
boolean NET_ValidGameSettings(GameMode_t mode, GameMission_t mission,
net_gamesettings_t *settings);
#endif /* #ifndef NET_COMMON_H */

View file

@ -98,20 +98,43 @@ struct _net_addr_s
void *handle;
};
// magic number sent when connecting to check this is a valid client
// Magic number sent when connecting to check this is a valid client
#define NET_MAGIC_NUMBER 1454104972U
#define NET_MAGIC_NUMBER 3436803284U
// Old magic number used by Chocolate Doom versions before v3.0:
#define NET_OLD_MAGIC_NUMBER 3436803284U
// header field value indicating that the packet is a reliable packet
#define NET_RELIABLE_PACKET (1 << 15)
// Supported protocols. If you're developing a fork of Chocolate
// Doom, you can add your own entry to this list while maintaining
// compatibility with Chocolate Doom servers. Higher-numbered enum values
// will be preferred when negotiating a protocol for the client and server
// to use, so the order matters.
// NOTE: The values in this enum do not have any special value outside of
// the program they're compiled in. What matters is the string representation.
typedef enum
{
// Protocol introduced with Chocolate Doom v3.0. Each compatibility-
// breaking change to the network protocol will produce a new protocol
// number in this enum.
NET_PROTOCOL_CHOCOLATE_DOOM_0,
// Add your own protocol here; be sure to add a name for it to the list
// in net_common.c too.
NET_NUM_PROTOCOLS,
NET_PROTOCOL_UNKNOWN,
} net_protocol_t;
// packet types
typedef enum
{
NET_PACKET_TYPE_SYN,
NET_PACKET_TYPE_ACK,
NET_PACKET_TYPE_ACK, // deprecated
NET_PACKET_TYPE_REJECTED,
NET_PACKET_TYPE_KEEPALIVE,
NET_PACKET_TYPE_WAITING_DATA,

View file

@ -15,6 +15,7 @@
// Network packet manipulation (net_packet_t)
//
#include <ctype.h>
#include <string.h>
#include "m_misc.h"
#include "net_packet.h"
@ -202,6 +203,37 @@ char *NET_ReadString(net_packet_t *packet)
return start;
}
// Read a string from the packet, but (potentially) modify it to strip
// out any unprintable characters which could be malicious control codes.
// Note that this may modify the original packet contents.
char *NET_ReadSafeString(net_packet_t *packet)
{
char *r, *w, *result;
result = NET_ReadString(packet);
if (result == NULL)
{
return NULL;
}
// w is always <= r, so we never produce a longer string than the original.
w = result;
for (r = result; *r != '\0'; ++r)
{
// TODO: This is a very naive way of producing a safe string; only
// ASCII characters are allowed. Probably this should really support
// UTF-8 characters as well.
if (isprint(*r) || *r == '\n')
{
*w = *r;
++w;
}
}
*w = '\0';
return result;
}
// Dynamically increases the size of a packet
static void NET_IncreasePacket(net_packet_t *packet)
@ -270,7 +302,7 @@ void NET_WriteInt32(net_packet_t *packet, unsigned int i)
packet->len += 4;
}
void NET_WriteString(net_packet_t *packet, char *string)
void NET_WriteString(net_packet_t *packet, const char *string)
{
byte *p;
size_t string_size;

View file

@ -33,12 +33,13 @@ boolean NET_ReadSInt16(net_packet_t *packet, signed int *data);
boolean NET_ReadSInt32(net_packet_t *packet, signed int *data);
char *NET_ReadString(net_packet_t *packet);
char *NET_ReadSafeString(net_packet_t *packet);
void NET_WriteInt8(net_packet_t *packet, unsigned int i);
void NET_WriteInt16(net_packet_t *packet, unsigned int i);
void NET_WriteInt32(net_packet_t *packet, unsigned int i);
void NET_WriteString(net_packet_t *packet, char *string);
void NET_WriteString(net_packet_t *packet, const char *string);
#endif /* #ifndef NET_PACKET_H */

View file

@ -738,7 +738,7 @@ static void NET_QueryPrintCallback(net_addr_t *addr,
printf("(game running) ");
}
NET_SafePuts(data->description);
printf("%s\n", data->description);
}
void NET_LANQuery(void)

View file

@ -213,7 +213,7 @@ static void NET_SV_BroadcastMessage(char *s, ...)
va_start(args, s);
M_vsnprintf(buf, sizeof(buf), s, args);
va_end(args);
for (i=0; i<MAXNETNODES; ++i)
{
if (ClientConnected(&clients[i]))
@ -222,7 +222,7 @@ static void NET_SV_BroadcastMessage(char *s, ...)
}
}
NET_SafePuts(buf);
printf("%s\n", buf);
}
@ -555,16 +555,14 @@ static void NET_SV_SendReject(net_addr_t *addr, char *msg)
NET_FreePacket(packet);
}
static void NET_SV_InitNewClient(net_client_t *client,
net_addr_t *addr,
char *player_name)
static void NET_SV_InitNewClient(net_client_t *client, net_addr_t *addr,
net_protocol_t protocol)
{
client->active = true;
client->connect_time = I_GetTimeMS();
NET_Conn_InitServer(&client->connection, addr);
NET_Conn_InitServer(&client->connection, addr, protocol);
client->addr = addr;
client->last_send_time = -1;
client->name = M_StringDuplicate(player_name);
// init the ticcmd send queue
@ -580,99 +578,121 @@ static void NET_SV_InitNewClient(net_client_t *client,
// parse a SYN from a client(initiating a connection)
static void NET_SV_ParseSYN(net_packet_t *packet,
net_client_t *client,
static void NET_SV_ParseSYN(net_packet_t *packet, net_client_t *client,
net_addr_t *addr)
{
unsigned int magic;
net_connect_data_t data;
net_packet_t *reply;
net_protocol_t protocol;
char *player_name;
char *client_version;
int num_players;
int i;
// read the magic number
// Read the magic number and check it is the expected one.
if (!NET_ReadInt32(packet, &magic))
{
return;
}
if (magic != NET_MAGIC_NUMBER)
switch (magic)
{
// invalid magic number
case NET_MAGIC_NUMBER:
break;
return;
case NET_OLD_MAGIC_NUMBER:
NET_SV_SendReject(addr,
"You are using an old client version that is not supported by "
"this server. This server is running " PACKAGE_STRING ".");
return;
default:
return;
}
// Check the client version is the same as the server
// Read the client version string. We actually now only use this when
// sending a reject message, as we only reject if we can't negotiate a
// common protocol (below).
client_version = NET_ReadString(packet);
if (client_version == NULL)
{
return;
}
if (strcmp(client_version, PACKAGE_STRING) != 0)
// Read the client's list of accepted protocols. Net play between forks
// of Chocolate Doom is accepted provided that they can negotiate a
// common accepted protocol.
protocol = NET_ReadProtocolList(packet);
if (protocol == NET_PROTOCOL_UNKNOWN)
{
//!
// @category net
//
// When running a netgame server, ignore version mismatches between
// the server and the client. Using this option may cause game
// desyncs to occur, or differences in protocol may mean the netgame
// will simply not function at all.
//
char reject_msg[256];
if (M_CheckParm("-ignoreversion") == 0)
{
NET_SV_SendReject(addr,
"Different " PACKAGE_NAME " versions cannot play a net game!\n"
"Version mismatch: server version is: " PACKAGE_STRING);
return;
}
M_snprintf(reject_msg, sizeof(reject_msg),
"Version mismatch: server version is: " PACKAGE_STRING "; "
"client is: %s. No common compatible protocol could be "
"negotiated.", client_version);
NET_SV_SendReject(addr, reject_msg);
return;
}
// read the game mode and mission
if (!NET_ReadConnectData(packet, &data))
// Read connect data, and check that the game mode/mission are valid
// and the max_players value is in a sensible range.
if (!NET_ReadConnectData(packet, &data)
|| !D_ValidGameMode(data.gamemission, data.gamemode)
|| data.max_players > NET_MAXPLAYERS)
{
return;
}
if (!D_ValidGameMode(data.gamemission, data.gamemode))
{
return;
}
// Check max_players value. This must be in a sensible range.
if (data.max_players > NET_MAXPLAYERS)
{
return;
}
// read the player's name
// Read the player's name
player_name = NET_ReadString(packet);
if (player_name == NULL)
{
return;
}
// received a valid SYN
// not accepting new connections?
// At this point we have received a valid SYN.
// Not accepting new connections?
if (server_state != SERVER_WAITING_LAUNCH)
{
NET_SV_SendReject(addr, "Server is not currently accepting connections");
NET_SV_SendReject(addr,
"Server is not currently accepting connections");
return;
}
// allocate a client slot if there isn't one already
// Before accepting a new client, check that there is a slot free.
NET_SV_AssignPlayers();
num_players = NET_SV_NumPlayers();
if ((!data.drone && num_players >= NET_SV_MaxPlayers())
|| NET_SV_NumClients() >= MAXNETNODES)
{
NET_SV_SendReject(addr, "Server is full!");
return;
}
// TODO: Add server option to allow rejecting clients which set
// lowres_turn. This is potentially desirable as the presence of such
// clients affects turning resolution.
// Adopt the game mode and mission of the first connecting client:
if (num_players == 0 && !data.drone)
{
sv_gamemode = data.gamemode;
sv_gamemission = data.gamemission;
}
// Check the connecting client is playing the same game as all
// the other clients
if (data.gamemode != sv_gamemode || data.gamemission != sv_gamemission)
{
NET_SV_SendReject(addr, "You are playing the wrong game!");
return;
}
// Allocate a client slot if there isn't one already
if (client == NULL)
{
// find a slot, or return if none found
@ -702,67 +722,30 @@ static void NET_SV_ParseSYN(net_packet_t *packet,
}
}
// New client?
if (!client->active)
// Client already connected?
if (client->active)
{
int num_players;
// Before accepting a new client, check that there is a slot
// free
NET_SV_AssignPlayers();
num_players = NET_SV_NumPlayers();
if ((!data.drone && num_players >= NET_SV_MaxPlayers())
|| NET_SV_NumClients() >= MAXNETNODES)
{
NET_SV_SendReject(addr, "Server is full!");
return;
}
// TODO: Add server option to allow rejecting clients which
// set lowres_turn. This is potentially desirable as the
// presence of such clients affects turning resolution.
// Adopt the game mode and mission of the first connecting client
if (num_players == 0 && !data.drone)
{
sv_gamemode = data.gamemode;
sv_gamemission = data.gamemission;
}
// Save the SHA1 checksums
memcpy(client->wad_sha1sum, data.wad_sha1sum, sizeof(sha1_digest_t));
memcpy(client->deh_sha1sum, data.deh_sha1sum, sizeof(sha1_digest_t));
client->is_freedoom = data.is_freedoom;
client->max_players = data.max_players;
// Check the connecting client is playing the same game as all
// the other clients
if (data.gamemode != sv_gamemode || data.gamemission != sv_gamemission)
{
NET_SV_SendReject(addr, "You are playing the wrong game!");
return;
}
// Activate, initialize connection
NET_SV_InitNewClient(client, addr, player_name);
client->recording_lowres = data.lowres_turn;
client->drone = data.drone;
client->player_class = data.player_class;
return;
}
if (client->connection.state == NET_CONN_STATE_WAITING_ACK)
{
// force an acknowledgement
client->connection.last_send_time = -1;
}
// Activate, initialize connection
NET_SV_InitNewClient(client, addr, protocol);
// Save the SHA1 checksums and other details.
memcpy(client->wad_sha1sum, data.wad_sha1sum, sizeof(sha1_digest_t));
memcpy(client->deh_sha1sum, data.deh_sha1sum, sizeof(sha1_digest_t));
client->is_freedoom = data.is_freedoom;
client->max_players = data.max_players;
client->name = M_StringDuplicate(player_name);
client->recording_lowres = data.lowres_turn;
client->drone = data.drone;
client->player_class = data.player_class;
// Send a reply back to the client, indicating a successful connection
// and specifying the protocol that will be used for communications.
reply = NET_Conn_NewReliable(&client->connection, NET_PACKET_TYPE_SYN);
NET_WriteString(reply, PACKAGE_STRING);
NET_WriteProtocol(reply, protocol);
}
// Parse a launch packet. This is sent by the key player when the "start"

View file

@ -17,7 +17,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "doomtype.h"
#include "m_misc.h"
@ -122,7 +121,7 @@ boolean NET_ReadQueryData(net_packet_t *packet, net_querydata_t *query)
{
boolean result;
query->version = NET_ReadString(packet);
query->version = NET_ReadSafeString(packet);
result = query->version != NULL
&& NET_ReadInt8(packet, (unsigned int *) &query->server_state)
@ -133,7 +132,7 @@ boolean NET_ReadQueryData(net_packet_t *packet, net_querydata_t *query)
if (result)
{
query->description = NET_ReadString(packet);
query->description = NET_ReadSafeString(packet);
return query->description != NULL;
}
@ -551,22 +550,3 @@ void NET_WritePRNGSeed(net_packet_t *packet, prng_seed_t seed)
NET_WriteBlob(packet, seed, sizeof(prng_seed_t));
}
// "Safe" version of puts, for displaying messages received from the
// network.
void NET_SafePuts(char *s)
{
char *p;
// Do not do a straight "puts" of the string, as this could be
// dangerous (sending control codes to terminals can do all
// kinds of things)
for (p=s; *p; ++p)
{
if (isprint(*p) || *p == '\n')
putchar(*p);
}
putchar('\n');
}

View file

@ -43,8 +43,6 @@ void NET_WriteSHA1Sum(net_packet_t *packet, sha1_digest_t digest);
void NET_WriteWaitData(net_packet_t *packet, net_waitdata_t *data);
boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data);
void NET_SafePuts(char *msg);
boolean NET_ReadPRNGSeed(net_packet_t *packet, prng_seed_t seed);
void NET_WritePRNGSeed(net_packet_t *packet, prng_seed_t seed);