char *NET_EndSecureDemo(sha1_digest_t demo_hash) { net_packet_t *request, *response; net_addr_t *master_addr; char *signature; master_addr = NET_Query_ResolveMaster(query_context); // Construct end request and send to master server. request = NET_NewPacket(10); NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_END); NET_WriteSHA1Sum(request, demo_hash); NET_WriteString(request, securedemo_start_message); NET_SendPacket(master_addr, request); NET_FreePacket(request); // Block for response. The response packet simply contains a string // with the ASCII signature. response = BlockForPacket(master_addr, NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE, SIGNATURE_TIMEOUT_SECS * 1000); if (response == NULL) { return NULL; } signature = NET_ReadString(response); NET_FreePacket(response); return signature; }
static void NET_SV_ParseHolePunch(net_packet_t *packet) { const char *addr_string; net_packet_t *sendpacket; net_addr_t *addr; addr_string = NET_ReadString(packet); if (addr_string == NULL) { NET_Log("server: error: hole punch request but no address provided"); return; } addr = NET_ResolveAddress(server_context, addr_string); if (addr == NULL) { NET_Log("server: error: failed to resolve address: %s", addr_string); return; } sendpacket = NET_NewPacket(16); NET_WriteInt16(sendpacket, NET_PACKET_TYPE_NAT_HOLE_PUNCH); NET_SendPacket(addr, sendpacket); NET_FreePacket(sendpacket); NET_ReleaseAddress(addr); NET_Log("server: sent hole punch to %s", addr_string); }
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 net_packet_t *BlockForPacket(net_addr_t *addr, unsigned int packet_type, unsigned int timeout_ms) { net_packet_t *packet; net_addr_t *packet_src; unsigned int read_packet_type; unsigned int start_time; start_time = I_GetTimeMS(); while (I_GetTimeMS() < start_time + timeout_ms) { if (!NET_RecvPacket(query_context, &packet_src, &packet)) { I_Sleep(20); continue; } if (packet_src == addr && NET_ReadInt16(packet, &read_packet_type) && packet_type == read_packet_type) { return packet; } NET_FreePacket(packet); } // Timeout - no response. return NULL; }
static void NET_Conn_ParseReliableACK(net_connection_t *conn, net_packet_t *packet) { unsigned int seq; if (!NET_ReadInt8(packet, &seq)) { return; } if (conn->reliable_packets == NULL) { return; } // Is this an acknowledgement for the first packet in the list? if (seq == (unsigned int)((conn->reliable_packets->seq + 1) & 0xff)) { net_reliable_packet_t *rp; // Discard it, then. // Unlink from the list. rp = conn->reliable_packets; conn->reliable_packets = rp->next; NET_FreePacket(rp->packet); free(rp); } }
static void NET_CL_SendResendRequest(int start, int end) { net_packet_t *packet; unsigned int nowtime; int i; //printf("CL: Send resend %i-%i\n", start, end); packet = NET_NewPacket(64); NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND); NET_WriteInt32(packet, start); NET_WriteInt8(packet, end - start + 1); NET_Conn_SendPacket(&client_connection, packet); NET_FreePacket(packet); nowtime = I_GetTimeMS(); // Save the time we sent the resend request for (i=start; i<=end; ++i) { int index; index = i - recvwindow_start; if (index < 0 || index >= BACKUPTICS) continue; recvwindow[index].resend_time = nowtime; } }
void NET_Query_AddToMaster(net_addr_t *master_addr) { net_packet_t *packet; packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_ADD); NET_SendPacket(master_addr, packet); NET_FreePacket(packet); }
static void NET_Query_SendMasterQuery(net_addr_t *addr) { net_packet_t *packet; packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_QUERY); NET_SendPacket(addr, packet); NET_FreePacket(packet); }
boolean NET_StartSecureDemo(prng_seed_t seed) { net_packet_t *request, *response; net_addr_t *master_addr; char *signature; boolean result; NET_Query_Init(); master_addr = NET_Query_ResolveMaster(query_context); // Send request packet to master server. request = NET_NewPacket(10); NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_START); NET_SendPacket(master_addr, request); NET_FreePacket(request); // Block for response and read contents. // The signed start message will be saved for later. response = BlockForPacket(master_addr, NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE, SIGNATURE_TIMEOUT_SECS * 1000); result = false; if (response != NULL) { if (NET_ReadPRNGSeed(response, seed)) { signature = NET_ReadString(response); if (signature != NULL) { securedemo_start_message = strdup(signature); result = true; } } NET_FreePacket(response); } return result; }
static void NET_SV_SendWaitingData(net_client_t *client) { net_waitdata_t wait_data; net_packet_t *packet; net_client_t *controller; int i; NET_SV_AssignPlayers(); controller = NET_SV_Controller(); wait_data.num_players = NET_SV_NumPlayers(); wait_data.num_drones = NET_SV_NumDrones(); wait_data.ready_players = NET_SV_NumReadyPlayers(); wait_data.max_players = NET_SV_MaxPlayers(); wait_data.is_controller = (client == controller); wait_data.consoleplayer = client->player_number; // Send the WAD and dehacked checksums of the controlling client. // If no controller found (?), send the details that the client // is expecting anyway. if (controller == NULL) { controller = client; } memcpy(&wait_data.wad_sha1sum, &controller->wad_sha1sum, sizeof(sha1_digest_t)); memcpy(&wait_data.deh_sha1sum, &controller->deh_sha1sum, sizeof(sha1_digest_t)); wait_data.is_freedoom = controller->is_freedoom; // set name and address of each player: for (i = 0; i < wait_data.num_players; ++i) { M_StringCopy(wait_data.player_names[i], sv_players[i]->name, MAXPLAYERNAME); M_StringCopy(wait_data.player_addrs[i], NET_AddrToString(sv_players[i]->addr), MAXPLAYERNAME); } // Construct packet: packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_WAITING_DATA); NET_WriteWaitData(packet, &wait_data); // Send packet to client and free NET_Conn_SendPacket(&client->connection, packet); NET_FreePacket(packet); }
void NET_SV_Run(void) { net_addr_t *addr; net_packet_t *packet; int i; if (!server_initialized) { return; } while (NET_RecvPacket(server_context, &addr, &packet)) { NET_SV_Packet(packet, addr); NET_FreePacket(packet); NET_ReleaseAddress(addr); } if (master_server != NULL) { UpdateMasterServer(); } // "Run" any clients that may have things to do, independent of responses // to received packets for (i=0; i<MAXNETNODES; ++i) { if (clients[i].active) { NET_SV_RunClient(&clients[i]); } } switch (server_state) { case SERVER_WAITING_LAUNCH: break; case SERVER_WAITING_START: CheckStartGame(); break; case SERVER_IN_GAME: NET_SV_AdvanceWindow(); for (i = 0; i < NET_MAXPLAYERS; ++i) { if (sv_players[i] != NULL && ClientConnected(sv_players[i])) { NET_SV_CheckResends(sv_players[i]); } } break; } }
static void NET_SV_SendReject(net_addr_t *addr, char *msg) { net_packet_t *packet; packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_REJECTED); NET_WriteString(packet, msg); NET_SendPacket(addr, packet); NET_FreePacket(packet); }
static void NET_SV_SendReject(net_addr_t *addr, const char *msg) { net_packet_t *packet; NET_Log("server: sending reject to %s", NET_AddrToString(addr)); packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_REJECTED); NET_WriteString(packet, msg); NET_SendPacket(addr, packet); NET_FreePacket(packet); }
void NET_CL_Run(void) { net_addr_t *addr; net_packet_t *packet; if (!net_client_connected) { return; } while (NET_RecvPacket(client_context, &addr, &packet)) { // only accept packets from the server if (addr == server_addr) { NET_CL_ParsePacket(packet); } else { NET_FreeAddress(addr); } NET_FreePacket(packet); } // Run the common connection code to send any packets as needed NET_Conn_Run(&client_connection); if (client_connection.state == NET_CONN_STATE_DISCONNECTED || client_connection.state == NET_CONN_STATE_DISCONNECTED_SLEEP) { NET_CL_Disconnected(); NET_CL_Shutdown(); } net_waiting_for_launch = client_connection.state == NET_CONN_STATE_CONNECTED && client_state == CLIENT_STATE_WAITING_LAUNCH; if (client_state == CLIENT_STATE_IN_GAME) { // Possibly advance the receive window NET_CL_AdvanceWindow(); // Check if our resend requests have timed out NET_CL_CheckResends(); } }
static void NET_Query_GetResponse(net_query_callback_t callback, void *user_data) { net_addr_t *addr; net_packet_t *packet; if (NET_RecvPacket(query_context, &addr, &packet)) { NET_Query_ParsePacket(addr, packet, callback, user_data); NET_FreePacket(packet); } }
static void NET_CL_SendTics(int start, int end) { net_packet_t *packet; int i; if (!net_client_connected) { // Disconnected from server return; } if (start < 0) start = 0; // Build a new packet to send to the server packet = NET_NewPacket(512); NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA); // Write the start tic and number of tics. Send only the low byte // of start - it can be inferred by the server. NET_WriteInt8(packet, (gametic / ticdup) & 0xff); NET_WriteInt8(packet, start & 0xff); NET_WriteInt8(packet, end - start + 1); // Add the tics. for (i=start; i<=end; ++i) { net_server_send_t *sendobj; sendobj = &send_queue[i % BACKUPTICS]; NET_WriteInt16(packet, average_latency / FRACUNIT); NET_WriteTiccmdDiff(packet, &sendobj->cmd, lowres_turn); } // Send the packet NET_Conn_SendPacket(&client_connection, packet); // All done! NET_FreePacket(packet); // Acknowledgement has been sent as part of the packet need_to_acknowledge = false; }
static void NET_CL_SendSYN(net_connect_data_t *data) { net_packet_t *packet; packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_SYN); NET_WriteInt32(packet, NET_MAGIC_NUMBER); NET_WriteString(packet, PACKAGE_STRING); NET_WriteConnectData(packet, data); NET_WriteString(packet, net_player_name); NET_Conn_SendPacket(&client_connection, packet); NET_FreePacket(packet); }
void NET_SV_SendQueryResponse(net_addr_t *addr) { net_packet_t *reply; net_querydata_t querydata; int p; // Version querydata.version = PACKAGE_STRING; // Server state querydata.server_state = server_state; // Number of players/maximum players querydata.num_players = NET_SV_NumPlayers(); querydata.max_players = NET_SV_MaxPlayers(); // Game mode/mission querydata.gamemode = sv_gamemode; querydata.gamemission = sv_gamemission; //! // @category net // @arg <name> // // When starting a network server, specify a name for the server. // p = M_CheckParmWithArgs("-servername", 1); if (p > 0) { querydata.description = myargv[p + 1]; } else { querydata.description = "Unnamed server"; } // Send it and we're done. NET_Log("server: sending query response to %s", NET_AddrToString(addr)); reply = NET_NewPacket(64); NET_WriteInt16(reply, NET_PACKET_TYPE_QUERY_RESPONSE); NET_WriteQueryData(reply, &querydata); NET_SendPacket(addr, reply); NET_FreePacket(reply); }
static boolean NET_Conn_ReliablePacket(net_connection_t *conn, net_packet_t *packet) { unsigned int seq; net_packet_t *reply; boolean result; // Read the sequence number if (!NET_ReadInt8(packet, &seq)) { return true; } if (seq != (unsigned int)(conn->reliable_recv_seq & 0xff)) { // This is not the next expected packet in the sequence! // // Discard the packet. If we were smart, we would use a proper // sliding window protocol to do this, but I'm lazy. result = true; } else { // Now we can receive the next packet in the sequence. conn->reliable_recv_seq = (conn->reliable_recv_seq + 1) & 0xff; result = false; } // Send an acknowledgement // Note: this is braindead. It would be much more sensible to // include this in the next packet, rather than the overhead of // sending a complete packet just for one byte of information. reply = NET_NewPacket(10); NET_WriteInt16(reply, NET_PACKET_TYPE_RELIABLE_ACK); NET_WriteInt8(reply, conn->reliable_recv_seq & 0xff); NET_Conn_SendPacket(conn, reply); NET_FreePacket(reply); return result; }
static void NET_CL_SendGameDataACK(void) { net_packet_t *packet; packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_ACK); NET_WriteInt8(packet, (gametic / ticdup) & 0xff); NET_Conn_SendPacket(&client_connection, packet); NET_FreePacket(packet); need_to_acknowledge = false; }
static void NET_Conn_ParseDisconnect(net_connection_t *conn, net_packet_t *packet) { net_packet_t *reply; // Other end wants to disconnect // Send a DISCONNECT_ACK reply. reply = NET_NewPacket(10); NET_WriteInt16(reply, NET_PACKET_TYPE_DISCONNECT_ACK); NET_Conn_SendPacket(conn, reply); NET_FreePacket(reply); conn->last_send_time = I_GetTimeMS(); conn->state = NET_CONN_STATE_DISCONNECTED_SLEEP; conn->disconnect_reason = NET_DISCONNECT_REMOTE; }
static void NET_Query_SendQuery(net_addr_t *addr) { net_packet_t *request; request = NET_NewPacket(10); NET_WriteInt16(request, NET_PACKET_TYPE_QUERY); if (addr == NULL) { NET_SendBroadcast(query_context, request); } else { NET_SendPacket(addr, request); } NET_FreePacket(request); }
static void NET_CL_SendSYN(void) { net_packet_t *packet; packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_SYN); NET_WriteInt32(packet, NET_MAGIC_NUMBER); NET_WriteString(packet, PACKAGE_STRING); NET_WriteInt16(packet, gamemode); NET_WriteInt16(packet, gamemission); NET_WriteInt8(packet, lowres_turn); NET_WriteInt8(packet, drone); NET_WriteMD5Sum(packet, net_local_wad_md5sum); NET_WriteMD5Sum(packet, net_local_deh_md5sum); NET_WriteInt8(packet, net_local_is_freedoom); NET_WriteString(packet, net_player_name); NET_Conn_SendPacket(&client_connection, packet); NET_FreePacket(packet); }
static void NET_SV_SendResendRequest(net_client_t *client, int start, int end) { net_packet_t *packet; net_client_recv_t *recvobj; int i; unsigned int nowtime; int index; NET_Log("server: send resend to %s for tics %d-%d", NET_AddrToString(client->addr), start, end); packet = NET_NewPacket(20); NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND); NET_WriteInt32(packet, start); NET_WriteInt8(packet, end - start + 1); NET_Conn_SendPacket(&client->connection, packet); NET_FreePacket(packet); // Store the time we send the resend request nowtime = I_GetTimeMS(); for (i=start; i<=end; ++i) { index = i - recvwindow_start; if (index >= BACKUPTICS) { // Outside the range continue; } recvobj = &recvwindow[index][client->player_number]; recvobj->resend_time = nowtime; } }
static void NET_SV_SendTics(net_client_t *client, unsigned int start, unsigned int end) { net_packet_t *packet; unsigned int i; packet = NET_NewPacket(500); NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA); // Send the start tic and number of tics NET_WriteInt8(packet, start & 0xff); NET_WriteInt8(packet, end-start + 1); // Write the tics for (i=start; i<=end; ++i) { net_full_ticcmd_t *cmd; cmd = &client->sendqueue[i % BACKUPTICS]; if (i != cmd->seq) { I_Error("Wanted to send %i, but %i is in its place", i, cmd->seq); } // Add command NET_WriteFullTiccmd(packet, cmd, sv_settings.lowres_turn); } // Send packet NET_Conn_SendPacket(&client->connection, packet); NET_FreePacket(packet); }
void NET_Conn_Run(net_connection_t *conn) { net_packet_t *packet; unsigned int nowtime; nowtime = I_GetTimeMS(); if (conn->state == NET_CONN_STATE_CONNECTED) { // Check the keepalive counters if (nowtime - conn->keepalive_recv_time > CONNECTION_TIMEOUT_LEN * 1000) { // Haven't received any packets from the other end in a long // time. Assume disconnected. conn->state = NET_CONN_STATE_DISCONNECTED; conn->disconnect_reason = NET_DISCONNECT_TIMEOUT; } if (nowtime - conn->keepalive_send_time > KEEPALIVE_PERIOD * 1000) { // We have not sent anything in a long time. // Send a keepalive. packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_KEEPALIVE); NET_Conn_SendPacket(conn, packet); NET_FreePacket(packet); } // Check the reliable packet list. Has the first packet in the // list timed out? // // NB. This is braindead, we have a fixed time of one second. if (conn->reliable_packets != NULL && (conn->reliable_packets->last_send_time < 0 || nowtime - conn->reliable_packets->last_send_time > 1000)) { // Packet timed out, time to resend NET_Conn_SendPacket(conn, conn->reliable_packets->packet); 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. if (conn->last_send_time < 0 || nowtime - conn->last_send_time > 1000) { // it has been a second since the last disconnect packet // was sent, and still no reply. if (conn->num_retries < MAX_RETRIES) { // send another disconnect packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_DISCONNECT); NET_Conn_SendPacket(conn, packet); NET_FreePacket(packet); conn->last_send_time = nowtime; ++conn->num_retries; } else { // No more retries allowed. // Force disconnect. conn->state = NET_CONN_STATE_DISCONNECTED; conn->disconnect_reason = NET_DISCONNECT_LOCAL; } } } else if (conn->state == NET_CONN_STATE_DISCONNECTED_SLEEP) { // We are disconnected, waiting in case we need to send // a DISCONNECT_ACK to the server again. if (nowtime - conn->last_send_time > 5000) { // Idle for 5 seconds, switch state conn->state = NET_CONN_STATE_DISCONNECTED; conn->disconnect_reason = NET_DISCONNECT_REMOTE; } } }
static void NET_SV_SendWaitingData(net_client_t *client) { net_packet_t *packet; net_client_t *controller; int num_players; int i; NET_SV_AssignPlayers(); controller = NET_SV_Controller(); num_players = NET_SV_NumPlayers(); // time to send the client another status packet packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_WAITING_DATA); // include the number of players waiting NET_WriteInt8(packet, num_players); // send the number of drone clients NET_WriteInt8(packet, NET_SV_NumDrones()); // indicate whether the client is the controller NET_WriteInt8(packet, client == controller); // send the player number of this client NET_WriteInt8(packet, client->player_number); // send the addresses of all players for (i=0; i<num_players; ++i) { char *addr; // name NET_WriteString(packet, sv_players[i]->name); // address addr = NET_AddrToString(sv_players[i]->addr); NET_WriteString(packet, addr); } // Send the WAD and dehacked checksums of the controlling client. if (controller != NULL) { NET_WriteMD5Sum(packet, controller->wad_md5sum); NET_WriteMD5Sum(packet, controller->deh_md5sum); NET_WriteInt8(packet, controller->is_freedoom); } else { NET_WriteMD5Sum(packet, client->wad_md5sum); NET_WriteMD5Sum(packet, client->deh_md5sum); NET_WriteInt8(packet, client->is_freedoom); } // send packet to client and free NET_Conn_SendPacket(&client->connection, packet); NET_FreePacket(packet); }