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 }