Mercurial > hg > openttd
comparison src/network/network.cpp @ 10475:e8c75aac31ac draft
(svn r14730) -Codechange: remove the need for networkclientsockets and networkclientinfo structs to be in a contiguous piece of memory and put them in a pool.
-Note: 255 should really be enough for now... making it any more means network protocol bumps.
author | rubidium <rubidium@openttd.org> |
---|---|
date | Tue, 23 Dec 2008 20:52:27 +0000 |
parents | ff9458bb1120 |
children | 407e5dfa32ad |
comparison
equal
deleted
inserted
replaced
10474:67e76a023edd | 10475:e8c75aac31ac |
---|---|
40 #ifdef DEBUG_DUMP_COMMANDS | 40 #ifdef DEBUG_DUMP_COMMANDS |
41 #include "../fileio_func.h" | 41 #include "../fileio_func.h" |
42 #endif /* DEBUG_DUMP_COMMANDS */ | 42 #endif /* DEBUG_DUMP_COMMANDS */ |
43 #include "table/strings.h" | 43 #include "table/strings.h" |
44 #include "../company_base.h" | 44 #include "../company_base.h" |
45 #include "../oldpool_func.h" | |
45 | 46 |
46 DECLARE_POSTFIX_INCREMENT(ClientID); | 47 DECLARE_POSTFIX_INCREMENT(ClientID); |
48 | |
49 typedef ClientIndex NetworkClientInfoID; | |
50 DEFINE_OLD_POOL_GENERIC(NetworkClientInfo, NetworkClientInfo); | |
47 | 51 |
48 bool _network_server; ///< network-server is active | 52 bool _network_server; ///< network-server is active |
49 bool _network_available; ///< is network mode available? | 53 bool _network_available; ///< is network mode available? |
50 bool _network_dedicated; ///< are we a dedicated server? | 54 bool _network_dedicated; ///< are we a dedicated server? |
51 bool _is_network_server; ///< Does this client wants to be a network-server? | 55 bool _is_network_server; ///< Does this client wants to be a network-server? |
52 NetworkServerGameInfo _network_game_info; | 56 NetworkServerGameInfo _network_game_info; |
53 NetworkClientInfo _network_client_info[MAX_CLIENT_SLOTS]; | |
54 NetworkCompanyState *_network_company_states = NULL; | 57 NetworkCompanyState *_network_company_states = NULL; |
55 ClientID _network_own_client_id; | 58 ClientID _network_own_client_id; |
56 ClientID _redirect_console_to_client; | 59 ClientID _redirect_console_to_client; |
57 bool _network_need_advertise; | 60 bool _network_need_advertise; |
58 uint32 _network_last_advertise_frame; | 61 uint32 _network_last_advertise_frame; |
80 CommandPacket *_local_command_queue; | 83 CommandPacket *_local_command_queue; |
81 | 84 |
82 extern NetworkUDPSocketHandler *_udp_client_socket; ///< udp client socket | 85 extern NetworkUDPSocketHandler *_udp_client_socket; ///< udp client socket |
83 extern NetworkUDPSocketHandler *_udp_server_socket; ///< udp server socket | 86 extern NetworkUDPSocketHandler *_udp_server_socket; ///< udp server socket |
84 extern NetworkUDPSocketHandler *_udp_master_socket; ///< udp master socket | 87 extern NetworkUDPSocketHandler *_udp_master_socket; ///< udp master socket |
85 | |
86 // Here we keep track of the clients | |
87 // (and the client uses [0] for his own communication) | |
88 NetworkClientSocket _clients[MAX_CLIENTS]; | |
89 | |
90 | |
91 | 88 |
92 // The listen socket for the server | 89 // The listen socket for the server |
93 static SOCKET _listensocket; | 90 static SOCKET _listensocket; |
94 | 91 |
95 // The amount of clients connected | 92 // The amount of clients connected |
314 } | 311 } |
315 // This means we fucked up and the server closed the connection | 312 // This means we fucked up and the server closed the connection |
316 if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL && | 313 if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL && |
317 res != NETWORK_RECV_STATUS_SERVER_BANNED) { | 314 res != NETWORK_RECV_STATUS_SERVER_BANNED) { |
318 SEND_COMMAND(PACKET_CLIENT_ERROR)(errorno); | 315 SEND_COMMAND(PACKET_CLIENT_ERROR)(errorno); |
319 | |
320 // Dequeue all commands before closing the socket | |
321 GetNetworkClientSocket(0)->Send_Packets(); | |
322 } | 316 } |
323 | 317 |
324 _switch_mode = SM_MENU; | 318 _switch_mode = SM_MENU; |
325 NetworkCloseClient(cs); | 319 NetworkCloseClient(cs); |
326 _networking = false; | 320 _networking = false; |
417 | 411 |
418 // Creates a new client from a socket | 412 // Creates a new client from a socket |
419 // Used both by the server and the client | 413 // Used both by the server and the client |
420 static NetworkClientSocket *NetworkAllocClient(SOCKET s) | 414 static NetworkClientSocket *NetworkAllocClient(SOCKET s) |
421 { | 415 { |
422 NetworkClientSocket *cs; | |
423 byte client_no = 0; | |
424 | |
425 if (_network_server) { | 416 if (_network_server) { |
426 // Can we handle a new client? | 417 // Can we handle a new client? |
427 if (_network_clients_connected >= MAX_CLIENTS) return NULL; | 418 if (_network_clients_connected >= MAX_CLIENTS) return NULL; |
428 if (_network_game_info.clients_on >= _settings_client.network.max_clients) return NULL; | 419 if (_network_game_info.clients_on >= _settings_client.network.max_clients) return NULL; |
429 | 420 |
430 // Register the login | 421 // Register the login |
431 client_no = _network_clients_connected++; | 422 _network_clients_connected++; |
432 } | 423 } |
433 | 424 |
434 cs = GetNetworkClientSocket(client_no); | 425 NetworkClientSocket *cs = new NetworkClientSocket(INVALID_CLIENT_ID); |
435 cs->Initialize(); | |
436 cs->sock = s; | 426 cs->sock = s; |
437 cs->last_frame = _frame_counter; | 427 cs->last_frame = _frame_counter; |
438 cs->last_frame_server = _frame_counter; | 428 cs->last_frame_server = _frame_counter; |
439 | 429 |
440 if (_network_server) { | 430 if (_network_server) { |
441 NetworkClientInfo *ci = cs->GetInfo(); | |
442 memset(ci, 0, sizeof(*ci)); | |
443 | |
444 cs->client_id = _network_client_id++; | 431 cs->client_id = _network_client_id++; |
445 ci->client_id = cs->client_id; | 432 NetworkClientInfo *ci = new NetworkClientInfo(cs->client_id); |
433 cs->SetInfo(ci); | |
446 ci->client_playas = COMPANY_INACTIVE_CLIENT; | 434 ci->client_playas = COMPANY_INACTIVE_CLIENT; |
447 ci->join_date = _date; | 435 ci->join_date = _date; |
448 | 436 |
449 InvalidateWindow(WC_CLIENT_LIST, 0); | 437 InvalidateWindow(WC_CLIENT_LIST, 0); |
450 } | 438 } |
453 } | 441 } |
454 | 442 |
455 // Close a connection | 443 // Close a connection |
456 void NetworkCloseClient(NetworkClientSocket *cs) | 444 void NetworkCloseClient(NetworkClientSocket *cs) |
457 { | 445 { |
458 NetworkClientInfo *ci; | 446 assert(cs->sock != INVALID_SOCKET); |
459 // Socket is already dead | |
460 if (cs->sock == INVALID_SOCKET) { | |
461 cs->has_quit = true; | |
462 return; | |
463 } | |
464 | 447 |
465 DEBUG(net, 1, "Closed client connection %d", cs->client_id); | 448 DEBUG(net, 1, "Closed client connection %d", cs->client_id); |
466 | 449 |
467 if (!cs->has_quit && _network_server && cs->status > STATUS_INACTIVE) { | 450 if (!cs->has_quit && _network_server && cs->status > STATUS_INACTIVE) { |
468 // We did not receive a leave message from this client... | 451 // We did not receive a leave message from this client... |
489 if (cs->status == STATUS_PRE_ACTIVE && _settings_client.network.pause_on_join) { | 472 if (cs->status == STATUS_PRE_ACTIVE && _settings_client.network.pause_on_join) { |
490 DoCommandP(0, 0, 0, NULL, CMD_PAUSE); | 473 DoCommandP(0, 0, 0, NULL, CMD_PAUSE); |
491 NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", CLIENT_ID_SERVER); | 474 NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", CLIENT_ID_SERVER); |
492 } | 475 } |
493 | 476 |
494 cs->Destroy(); | |
495 | |
496 // Close the gap in the client-list | |
497 ci = cs->GetInfo(); | |
498 | |
499 if (_network_server) { | 477 if (_network_server) { |
500 // We just lost one client :( | 478 // We just lost one client :( |
501 if (cs->status >= STATUS_AUTH) _network_game_info.clients_on--; | 479 if (cs->status >= STATUS_AUTH) _network_game_info.clients_on--; |
502 _network_clients_connected--; | 480 _network_clients_connected--; |
503 | 481 |
504 while ((cs + 1) != GetNetworkClientSocket(MAX_CLIENTS) && (cs + 1)->sock != INVALID_SOCKET) { | |
505 *cs = *(cs + 1); | |
506 *ci = *(ci + 1); | |
507 cs++; | |
508 ci++; | |
509 } | |
510 | |
511 InvalidateWindow(WC_CLIENT_LIST, 0); | 482 InvalidateWindow(WC_CLIENT_LIST, 0); |
512 } | 483 } |
513 | 484 |
514 // Reset the status of the last socket | 485 delete cs->GetInfo(); |
515 cs->sock = INVALID_SOCKET; | 486 delete cs; |
516 cs->status = STATUS_INACTIVE; | |
517 cs->client_id = INVALID_CLIENT_ID; | |
518 ci->client_id = INVALID_CLIENT_ID; | |
519 | 487 |
520 CheckMinActiveClients(); | 488 CheckMinActiveClients(); |
521 } | 489 } |
522 | 490 |
523 // A client wants to connect to a server | 491 // A client wants to connect to a server |
695 _networking = false; | 663 _networking = false; |
696 _network_server = false; | 664 _network_server = false; |
697 | 665 |
698 free(_network_company_states); | 666 free(_network_company_states); |
699 _network_company_states = NULL; | 667 _network_company_states = NULL; |
668 | |
669 _NetworkClientSocket_pool.CleanPool(); | |
670 _NetworkClientInfo_pool.CleanPool(); | |
700 } | 671 } |
701 | 672 |
702 // Inits the network (cleans sockets and stuff) | 673 // Inits the network (cleans sockets and stuff) |
703 static void NetworkInitialize() | 674 static void NetworkInitialize() |
704 { | 675 { |
705 NetworkClientSocket *cs; | |
706 | |
707 _local_command_queue = NULL; | 676 _local_command_queue = NULL; |
708 | 677 |
709 // Clean all client-sockets | 678 _NetworkClientSocket_pool.CleanPool(); |
710 for (cs = _clients; cs != &_clients[MAX_CLIENTS]; cs++) { | 679 _NetworkClientSocket_pool.AddBlockToPool(); |
711 cs->Initialize(); | 680 _NetworkClientInfo_pool.CleanPool(); |
712 } | 681 _NetworkClientInfo_pool.AddBlockToPool(); |
713 | |
714 // Clean the client_info memory | |
715 memset(&_network_client_info, 0, sizeof(_network_client_info)); | |
716 | 682 |
717 _sync_frame = 0; | 683 _sync_frame = 0; |
718 _network_first_time = true; | 684 _network_first_time = true; |
719 | 685 |
720 _network_reconnect = 0; | 686 _network_reconnect = 0; |
815 return _networking; | 781 return _networking; |
816 } | 782 } |
817 | 783 |
818 static void NetworkInitGameInfo() | 784 static void NetworkInitGameInfo() |
819 { | 785 { |
820 NetworkClientInfo *ci; | |
821 | |
822 if (StrEmpty(_settings_client.network.server_name)) { | 786 if (StrEmpty(_settings_client.network.server_name)) { |
823 snprintf(_settings_client.network.server_name, sizeof(_settings_client.network.server_name), "Unnamed Server"); | 787 snprintf(_settings_client.network.server_name, sizeof(_settings_client.network.server_name), "Unnamed Server"); |
824 } | 788 } |
825 | 789 |
826 /* The server is a client too */ | 790 /* The server is a client too */ |
827 _network_game_info.clients_on = _network_dedicated ? 0 : 1; | 791 _network_game_info.clients_on = _network_dedicated ? 0 : 1; |
828 _network_game_info.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1); | 792 _network_game_info.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1); |
829 | 793 |
830 // We use _network_client_info[MAX_CLIENT_SLOTS - 1] to store the server-data in it | 794 NetworkClientInfo *ci = new NetworkClientInfo(CLIENT_ID_SERVER); |
831 // The client identifier is CLIENT_ID_SERVER ( = 1) | |
832 ci = &_network_client_info[MAX_CLIENT_SLOTS - 1]; | |
833 memset(ci, 0, sizeof(*ci)); | |
834 | |
835 ci->client_id = CLIENT_ID_SERVER; | |
836 ci->client_playas = _network_dedicated ? COMPANY_SPECTATOR : _local_company; | 795 ci->client_playas = _network_dedicated ? COMPANY_SPECTATOR : _local_company; |
837 | 796 |
838 strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name)); | 797 strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name)); |
839 strecpy(ci->unique_id, _settings_client.network.network_id, lastof(ci->unique_id)); | 798 strecpy(ci->unique_id, _settings_client.network.network_id, lastof(ci->unique_id)); |
840 } | 799 } |