X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fnetserv.c;h=636fbf236c484edfee5c5a86f8eb83216d7e4679;hp=551772a00c883b5053ddfe00b2925f6bf8ee2b5d;hb=HEAD;hpb=45c910a978cabc8e8dd40fac47b17b7d402c91aa diff --git a/src/netserv.c b/src/netserv.c index 551772a0..636fbf23 100644 --- a/src/netserv.c +++ b/src/netserv.c @@ -4,7 +4,7 @@ // (c) 1995-2014 by Artsoft Entertainment // Holger Schemel // info@artsoft.org -// http://www.artsoft.org/ +// https://www.artsoft.org/ // ---------------------------------------------------------------------------- // netserv.c // ============================================================================ @@ -40,10 +40,10 @@ static struct NetworkServerPlayerInfo *first_player = NULL; #define NEXT(player) ((player)->next ? (player)->next : first_player) -/* TODO: peer address */ -static TCPsocket lfd; /* listening TCP socket */ -static UDPsocket udp; /* listening UDP socket */ -static SDLNet_SocketSet fds; /* socket set */ +// TODO: peer address +static TCPsocket lfd; // listening TCP socket +static UDPsocket udp; // listening UDP socket +static SDLNet_SocketSet fds; // socket set static struct NetworkBuffer *read_buffer = NULL; static struct NetworkBuffer *write_buffer = NULL; @@ -107,7 +107,7 @@ int putNetworkString(byte *ptr, char *s) return strlen(s) + 1; } -struct NetworkBuffer *newNetworkBuffer() +struct NetworkBuffer *newNetworkBuffer(void) { struct NetworkBuffer *new = checked_calloc(sizeof(struct NetworkBuffer)); @@ -140,7 +140,7 @@ void initNetworkBufferForReading(struct NetworkBuffer *nb) { resetNetworkBufferForReading(nb); - /* skip message length header */ + // skip message length header getNetworkBuffer32BitInteger(nb); } @@ -149,7 +149,7 @@ void initNetworkBufferForWriting(struct NetworkBuffer *nb, int message_type, { resetNetworkBufferForWriting(nb); - /* will be replaced with message length before sending */ + // will be replaced with message length before sending putNetworkBuffer32BitInteger(nb, 0); putNetworkBuffer8BitInteger(nb, message_type); @@ -164,7 +164,7 @@ static void copyNetworkBufferForWriting(struct NetworkBuffer *nb_from, int message_type = getNetworkBuffer8BitInteger(nb_from); - /* skip player number */ + // skip player number getNetworkBuffer8BitInteger(nb_from); initNetworkBufferForWriting(nb_to, message_type, player_nr); @@ -179,7 +179,7 @@ static void copyNetworkBufferForWriting(struct NetworkBuffer *nb_from, static void increaseNetworkBuffer(struct NetworkBuffer *nb, int additional_size) { - /* add some more buffer size than is really required this time */ + // add some more buffer size than is really required this time nb->max_size += additional_size + MAX_BUFFER_SIZE; nb->buffer = checked_realloc(nb->buffer, nb->max_size); } @@ -187,6 +187,14 @@ static void increaseNetworkBuffer(struct NetworkBuffer *nb, int additional_size) int receiveNetworkBufferBytes(struct NetworkBuffer *nb, TCPsocket socket, int num_bytes) { + if (num_bytes > MAX_PACKET_SIZE) + { + Debug("network:server", "protocol error: invalid packet size %d", + num_bytes); + + return -1; + } + if (nb->pos + num_bytes > nb->max_size) increaseNetworkBuffer(nb, num_bytes); @@ -312,19 +320,99 @@ void putNetworkBufferString(struct NetworkBuffer *nb, char *s) nb->size = nb->pos; } +int getNetworkBufferFile(struct NetworkBuffer *nb, char *filename) +{ + FILE *file; + int num_bytes = getNetworkBuffer32BitInteger(nb); + int i; + + if (!(file = fopen(filename, MODE_WRITE))) + { + Warn("cannot write file '%s' from network buffer", filename); + + return 0; + } + + for (i = 0; i < num_bytes; i++) + { + int b = getNetworkBuffer8BitInteger(nb); + + putFile8Bit(file, b); + } + + fclose(file); + + return num_bytes; +} + +int putNetworkBufferFile(struct NetworkBuffer *nb, char *filename) +{ + File *file; + int filesize_pos = nb->pos; + int num_bytes = 0; + + // will be replaced with file size + putNetworkBuffer32BitInteger(nb, 0); + + if (!(file = openFile(filename, MODE_READ))) + { + Warn("cannot read file '%s' to network buffer", filename); + + return 0; + } + + while (1) + { + int b = getFile8Bit(file); + + if (checkEndOfFile(file)) + break; + + putNetworkBuffer8BitInteger(nb, b); + + num_bytes++; + } + + closeFile(file); + + // set file size + putNetwork32BitInteger(&nb->buffer[filesize_pos], num_bytes); + + return num_bytes; +} + +void dumpNetworkBuffer(struct NetworkBuffer *nb) +{ + int i; + + Debug("network:buffer", "network buffer maximum size: %d\n", nb->max_size); + Debug("network:buffer", "network buffer size: %d\n", nb->size); + Debug("network:buffer", "network buffer position : %d\n", nb->pos); + + for (i = 0; i < nb->size; i++) + { + if ((i % 16) == 0) + DebugContinued("network:buffer", "\n"); + + DebugContinued("", "%02x ", nb->buffer[i]); + } + + DebugContinued("network:buffer", "\n"); +} + static void SendNetworkBufferToAllButOne(struct NetworkBuffer *nb, struct NetworkServerPlayerInfo *except) { struct NetworkServerPlayerInfo *player; - /* set message length header */ + // set message length header putNetwork32BitInteger(nb->buffer, nb->size - 4); for (player = first_player; player != NULL; player = player->next) { if (player != except && player->introduced) { - /* directly send the buffer to the network client */ + // directly send the buffer to the network client SDLNet_TCP_Send(player->fd, nb->buffer, nb->size); } } @@ -338,18 +426,17 @@ static void SendNetworkBufferToAll(struct NetworkBuffer *nb) static void SendNetworkBufferToClient(struct NetworkBuffer *nb, struct NetworkServerPlayerInfo *player) { - /* set message length header */ + // set message length header putNetwork32BitInteger(nb->buffer, nb->size - 4); - /* directly send the buffer to the network client */ + // directly send the buffer to the network client SDLNet_TCP_Send(player->fd, nb->buffer, nb->size); } static void RemovePlayer(struct NetworkServerPlayerInfo *player) { - if (options.verbose) - Error(ERR_NETWORK_SERVER, "dropping client %d (%s)", - player->number, player->player_name); + Debug("network:server", "dropping client %d (%s)", + player->number, player->player_name); SDLNet_TCP_DelSocket(fds, player->fd); SDLNet_TCP_Close(player->fd); @@ -384,14 +471,11 @@ static void RemovePlayer(struct NetworkServerPlayerInfo *player) free(player); num_clients--; -#if 0 /* do not terminate network server if last player disconnected */ +#if 0 // do not terminate network server if last player disconnected if (run_server_only_once && num_clients == 0) { - if (options.verbose) - { - Error(ERR_NETWORK_SERVER, "no clients left"); - Error(ERR_NETWORK_SERVER, "aborting"); - } + Debug("network:server", "no clients left"); + Debug("network:server", "aborting"); exit(0); } @@ -457,13 +541,12 @@ static void Handle_OP_PROTOCOL_VERSION(struct NetworkServerPlayerInfo *player) if (protocol_version_major != PROTOCOL_VERSION_MAJOR || protocol_version_minor != PROTOCOL_VERSION_MINOR) { - if (options.verbose) - Error(ERR_NETWORK_SERVER, - "client %d (%s) has wrong protocol version %d.%d.%d", - player->number, player->player_name, - protocol_version_major, - protocol_version_minor, - protocol_version_patch); + Debug("network:server", + "client %d (%s) has wrong protocol version %d.%d.%d", + player->number, player->player_name, + protocol_version_major, + protocol_version_minor, + protocol_version_patch); initNetworkBufferForWriting(write_buffer, OP_BAD_PROTOCOL_VERSION, 0); @@ -477,13 +560,12 @@ static void Handle_OP_PROTOCOL_VERSION(struct NetworkServerPlayerInfo *player) } else { - if (options.verbose) - Error(ERR_NETWORK_SERVER, - "client %d (%s) uses protocol version %d.%d.%d", - player->number, player->player_name, - protocol_version_major, - protocol_version_minor, - protocol_version_patch); + Debug("network:server", + "client %d (%s) uses protocol version %d.%d.%d", + player->number, player->player_name, + protocol_version_major, + protocol_version_minor, + protocol_version_patch); } } @@ -494,9 +576,8 @@ static void Handle_OP_NUMBER_WANTED(struct NetworkServerPlayerInfo *player) boolean nr_is_free = TRUE; struct NetworkServerPlayerInfo *p; - if (options.verbose) - Error(ERR_NETWORK_SERVER, "client %d (%s) wants to switch to # %d", - player->number, player->player_name, nr_wanted); + Debug("network:server", "client %d (%s) wants to switch to # %d", + player->number, player->player_name, nr_wanted); for (p = first_player; p != NULL; p = p->next) { @@ -508,19 +589,16 @@ static void Handle_OP_NUMBER_WANTED(struct NetworkServerPlayerInfo *player) } } - if (options.verbose) - { - if (nr_is_free) - Error(ERR_NETWORK_SERVER, "client %d (%s) switches to # %d", - player->number, player->player_name, nr_wanted); - else if (player->number == nr_wanted) - Error(ERR_NETWORK_SERVER, "client %d (%s) already has # %d", - player->number, player->player_name, nr_wanted); - else - Error(ERR_NETWORK_SERVER, - "client %d (%s) cannot switch (client %d already exists)", - player->number, player->player_name, nr_wanted); - } + if (nr_is_free) + Debug("network:server", "client %d (%s) switches to # %d", + player->number, player->player_name, nr_wanted); + else if (player->number == nr_wanted) + Debug("network:server", "client %d (%s) already has # %d", + player->number, player->player_name, nr_wanted); + else + Debug("network:server", + "client %d (%s) cannot switch (client %d already exists)", + player->number, player->player_name, nr_wanted); if (nr_is_free) player->number = nr_wanted; @@ -561,9 +639,8 @@ static void Handle_OP_PLAYER_NAME(struct NetworkServerPlayerInfo *player) SendNetworkBufferToAllButOne(write_buffer, player); } - if (options.verbose) - Error(ERR_NETWORK_SERVER, "client %d calls itself \"%s\"", - player->number, player->player_name); + Debug("network:server", "client %d calls itself \"%s\"", + player->number, player->player_name); copyNetworkBufferForWriting(read_buffer, write_buffer, player->number); @@ -599,20 +676,19 @@ static void Handle_OP_START_PLAYING(struct NetworkServerPlayerInfo *player) char *new_leveldir_identifier = getNetworkBufferString(read_buffer); int level_nr = getNetworkBuffer16BitInteger(read_buffer); - if (options.verbose) - Error(ERR_NETWORK_SERVER, - "client %d (%s) starts game [level %d from level set '%s']", - player->number, player->player_name, level_nr, - new_leveldir_identifier); + Debug("network:server", + "client %d (%s) starts game [level %d from level set '%s']", + player->number, player->player_name, level_nr, + new_leveldir_identifier); struct NetworkServerPlayerInfo *p; - /* reset frame counter */ + // reset frame counter ServerFrameCounter = 0; - Error(ERR_NETWORK_SERVER, "resetting ServerFrameCounter to 0"); + Debug("network:server", "resetting ServerFrameCounter to 0"); - /* reset player actions */ + // reset player actions for (p = first_player; p != NULL; p = p->next) { p->action = 0; @@ -629,9 +705,8 @@ static void Handle_OP_START_PLAYING(struct NetworkServerPlayerInfo *player) static void Handle_OP_PAUSE_PLAYING(struct NetworkServerPlayerInfo *player) { - if (options.verbose) - Error(ERR_NETWORK_SERVER, "client %d (%s) pauses game", - player->number, player->player_name); + Debug("network:server", "client %d (%s) pauses game", + player->number, player->player_name); copyNetworkBufferForWriting(read_buffer, write_buffer, player->number); @@ -640,9 +715,8 @@ static void Handle_OP_PAUSE_PLAYING(struct NetworkServerPlayerInfo *player) static void Handle_OP_CONTINUE_PLAYING(struct NetworkServerPlayerInfo *player) { - if (options.verbose) - Error(ERR_NETWORK_SERVER, "client %d (%s) continues game", - player->number, player->player_name); + Debug("network:server", "client %d (%s) continues game", + player->number, player->player_name); copyNetworkBufferForWriting(read_buffer, write_buffer, player->number); @@ -653,9 +727,8 @@ static void Handle_OP_STOP_PLAYING(struct NetworkServerPlayerInfo *player) { int cause_for_stopping = getNetworkBuffer8BitInteger(read_buffer); - if (options.verbose) - Error(ERR_NETWORK_SERVER, "client %d (%s) stops game [%d]", - player->number, player->player_name, cause_for_stopping); + Debug("network:server", "client %d (%s) stops game [%d]", + player->number, player->player_name, cause_for_stopping); copyNetworkBufferForWriting(read_buffer, write_buffer, player->number); @@ -669,7 +742,7 @@ static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player) struct NetworkServerPlayerInfo *p; int i; - /* store player action */ + // store player action for (p = first_player; p != NULL; p = p->next) { if (p->number == player->number) @@ -679,7 +752,7 @@ static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player) } } - /* check if server received action from each player */ + // check if server received action from each player for (p = first_player; p != NULL; p = p->next) { if (!p->action_received) @@ -691,11 +764,11 @@ static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player) int player_action_all[last_client_nr]; - /* initialize all player actions to zero */ + // initialize all player actions to zero for (i = 0; i < last_client_nr; i++) player_action_all[i] = 0; - /* broadcast actions of all players to all players */ + // broadcast actions of all players to all players for (p = first_player; p != NULL; p = p->next) { player_action_all[p->number - 1] = p->action; @@ -720,29 +793,37 @@ static void Handle_OP_BROADCAST_MESSAGE(struct NetworkServerPlayerInfo *player) { char *message = getNetworkBufferString(read_buffer); - if (options.verbose) - Error(ERR_NETWORK_SERVER, "client %d (%s) sends message: %s", - player->number, player->player_name, message); + Debug("network:server", "client %d (%s) sends message: %s", + player->number, player->player_name, message); copyNetworkBufferForWriting(read_buffer, write_buffer, player->number); SendNetworkBufferToAllButOne(write_buffer, player); } -void ExitNetworkServer(int exit_value) +static void Handle_OP_LEVEL_FILE(struct NetworkServerPlayerInfo *player) { - Error(ERR_NETWORK_SERVER, "exiting network server"); + copyNetworkBufferForWriting(read_buffer, write_buffer, player->number); + + SendNetworkBufferToAllButOne(write_buffer, player); +} + +static void ExitNetworkServer(int exit_value) +{ + Debug("network:server", "exiting network server"); exit(exit_value); } -/* the following is not used for a standalone server; - the pointer points to an integer containing the port-number */ +// the following is not used for a standalone server; +// the pointer points to an integer containing the port-number int NetworkServerThread(void *ptr) { + network.is_server_thread = TRUE; + NetworkServer(*((int *) ptr), 0); - /* should never be reached */ + // should never be reached return 0; } @@ -783,37 +864,28 @@ void NetworkServer(int port, int serveronly) #endif if (SDLNet_ResolveHost(&ip, NULL, port) == -1) - Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_ResolveHost() failed: %s", - SDLNet_GetError()); + Fail("SDLNet_ResolveHost() failed: %s", SDLNet_GetError()); if ((fds = SDLNet_AllocSocketSet(MAX_PLAYERS + 1 + 1)) == NULL) - Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_AllocSocketSet() failed: %s"), - SDLNet_GetError(); + Fail("SDLNet_AllocSocketSet() failed: %s"), SDLNet_GetError(); if ((lfd = SDLNet_TCP_Open(&ip)) == NULL) - Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_Open() failed: %s"), - SDLNet_GetError(); + Fail("SDLNet_TCP_Open() failed: %s"), SDLNet_GetError(); if (SDLNet_TCP_AddSocket(fds, lfd) == -1) - Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"), - SDLNet_GetError(); + Fail("SDLNet_TCP_AddSocket() failed: %s"), SDLNet_GetError(); if ((udp = SDLNet_UDP_Open(port)) == NULL) - Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_UDP_Open() failed: %s", - SDLNet_GetError()); + Fail("SDLNet_UDP_Open() failed: %s", SDLNet_GetError()); if (SDLNet_UDP_AddSocket(fds, udp) == -1) - Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"), - SDLNet_GetError(); + Fail("SDLNet_TCP_AddSocket() failed: %s"), SDLNet_GetError(); - if (options.verbose) - { - Error(ERR_NETWORK_SERVER, "started up, listening on port %d", port); - Error(ERR_NETWORK_SERVER, "using protocol version %d.%d.%d", - PROTOCOL_VERSION_MAJOR, - PROTOCOL_VERSION_MINOR, - PROTOCOL_VERSION_PATCH); - } + Debug("network:server", "started up, listening on port %d", port); + Debug("network:server", "using protocol version %d.%d.%d", + PROTOCOL_VERSION_MAJOR, + PROTOCOL_VERSION_MINOR, + PROTOCOL_VERSION_PATCH); while (1) { @@ -821,10 +893,10 @@ void NetworkServer(int port, int serveronly) if (SDLNet_CheckSockets(fds, 100) < 1) continue; - /* accept incoming TCP connections */ + // accept incoming TCP connections if (SDLNet_SocketReady(lfd)) { - Error(ERR_DEBUG, "got TCP packet"); + Debug("network:server", "got TCP packet"); TCPsocket newsock; @@ -834,10 +906,10 @@ void NetworkServer(int port, int serveronly) AddPlayer(newsock); } - /* accept incoming UDP packets */ + // accept incoming UDP packets if (SDLNet_SocketReady(udp)) { - Error(ERR_DEBUG, "got UDP packet"); + Debug("network:server", "got UDP packet"); static UDPpacket packet; @@ -861,9 +933,8 @@ void NetworkServer(int port, int serveronly) if (num_bytes <= 0) { - if (options.verbose) - Error(ERR_NETWORK_SERVER, "EOF from client %d (%s)", - player->number, player->player_name); + Debug("network:server", "EOF from client %d (%s)", + player->number, player->player_name); RemovePlayer(player); @@ -874,15 +945,14 @@ void NetworkServer(int port, int serveronly) int message_type = getNetworkBuffer8BitInteger(read_buffer); - /* skip player number */ + // skip player number getNetworkBuffer8BitInteger(read_buffer); if (!player->introduced && message_type != OP_PLAYER_NAME && message_type != OP_PROTOCOL_VERSION) { - if (options.verbose) - Error(ERR_NETWORK_SERVER, "got opcode %d for client %d which is not introduced yet (expected OP_PLAYER_NAME or OP_PROTOCOL_VERSION)", message_type, player->number); + Debug("network:server", "got opcode %d for client %d which is not introduced yet (expected OP_PLAYER_NAME or OP_PROTOCOL_VERSION)", message_type, player->number); RemovePlayer(player); @@ -927,11 +997,13 @@ void NetworkServer(int port, int serveronly) Handle_OP_BROADCAST_MESSAGE(player); break; + case OP_LEVEL_FILE: + Handle_OP_LEVEL_FILE(player); + break; + default: - if (options.verbose) - Error(ERR_NETWORK_SERVER, - "unknown opcode %d from client %d (%s)", - message_type, player->number, player->player_name); + Debug("network:server", "unknown opcode %d from client %d (%s)", + message_type, player->number, player->player_name); } } }