00001
00002
00003 #ifdef ENABLE_NETWORK
00004
00005 #include "../stdafx.h"
00006 #include "../openttd.h"
00007 #include "../debug.h"
00008 #include "../strings_func.h"
00009 #include "network_data.h"
00010 #include "core/tcp.h"
00011 #include "../vehicle_base.h"
00012 #include "../vehicle_func.h"
00013 #include "../date_func.h"
00014 #include "network_server.h"
00015 #include "network_udp.h"
00016 #include "../console.h"
00017 #include "../command_func.h"
00018 #include "../saveload.h"
00019 #include "../station.h"
00020 #include "../variables.h"
00021 #include "../genworld.h"
00022 #include "../core/alloc_func.hpp"
00023 #include "../fileio.h"
00024 #include "../string_func.h"
00025 #include "../player_base.h"
00026 #include "../player_func.h"
00027 #include "../player_gui.h"
00028 #include "../settings_type.h"
00029
00030 #include "table/strings.h"
00031
00032
00033
00034 static void NetworkHandleCommandQueue(NetworkTCPSocketHandler* cs);
00035
00036
00037
00038
00039
00040
00041 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CLIENT_INFO)(NetworkTCPSocketHandler *cs, NetworkClientInfo *ci)
00042 {
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 if (ci->client_index != NETWORK_EMPTY_INDEX) {
00053 Packet *p = NetworkSend_Init(PACKET_SERVER_CLIENT_INFO);
00054 p->Send_uint16(ci->client_index);
00055 p->Send_uint8 (ci->client_playas);
00056 p->Send_string(ci->client_name);
00057
00058 cs->Send_Packet(p);
00059 }
00060 }
00061
00062 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)
00063 {
00064
00065
00066
00067
00068
00069
00070 int i;
00071
00072 Player *player;
00073 Packet *p;
00074
00075 byte active = ActivePlayerCount();
00076
00077 if (active == 0) {
00078 p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
00079
00080 p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00081 p->Send_uint8 (active);
00082
00083 cs->Send_Packet(p);
00084 return;
00085 }
00086
00087 NetworkPopulateCompanyInfo();
00088
00089 FOR_ALL_PLAYERS(player) {
00090 if (!player->is_active) continue;
00091
00092 p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
00093
00094 p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00095 p->Send_uint8 (active);
00096 p->Send_uint8 (player->index);
00097
00098 p->Send_string(_network_player_info[player->index].company_name);
00099 p->Send_uint32(_network_player_info[player->index].inaugurated_year);
00100 p->Send_uint64(_network_player_info[player->index].company_value);
00101 p->Send_uint64(_network_player_info[player->index].money);
00102 p->Send_uint64(_network_player_info[player->index].income);
00103 p->Send_uint16(_network_player_info[player->index].performance);
00104
00105
00106 p->Send_bool(!StrEmpty(_network_player_info[player->index].password));
00107
00108 for (i = 0; i < NETWORK_VEHICLE_TYPES; i++) {
00109 p->Send_uint16(_network_player_info[player->index].num_vehicle[i]);
00110 }
00111
00112 for (i = 0; i < NETWORK_STATION_TYPES; i++) {
00113 p->Send_uint16(_network_player_info[player->index].num_station[i]);
00114 }
00115
00116 if (_network_player_info[player->index].players[0] == '\0') {
00117 p->Send_string("<none>");
00118 } else {
00119 p->Send_string(_network_player_info[player->index].players);
00120 }
00121
00122 cs->Send_Packet(p);
00123 }
00124
00125 p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
00126
00127 p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00128 p->Send_uint8 (0);
00129
00130 cs->Send_Packet(p);
00131 }
00132
00133 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkTCPSocketHandler *cs, NetworkErrorCode error)
00134 {
00135
00136
00137
00138
00139
00140
00141
00142 char str[100];
00143 Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR);
00144
00145 p->Send_uint8(error);
00146 cs->Send_Packet(p);
00147
00148 GetNetworkErrorMsg(str, error, lastof(str));
00149
00150
00151 if (cs->status > STATUS_AUTH) {
00152 NetworkTCPSocketHandler *new_cs;
00153 char client_name[NETWORK_CLIENT_NAME_LENGTH];
00154
00155 NetworkGetClientName(client_name, sizeof(client_name), cs);
00156
00157 DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
00158
00159 NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
00160
00161 FOR_ALL_CLIENTS(new_cs) {
00162 if (new_cs->status > STATUS_AUTH && new_cs != cs) {
00163
00164
00165 if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION)
00166 error = NETWORK_ERROR_ILLEGAL_PACKET;
00167
00168 SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, error);
00169 }
00170 }
00171 } else {
00172 DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", cs->index, str);
00173 }
00174
00175 cs->has_quit = true;
00176
00177
00178 cs->Send_Packets();
00179
00180
00181 NetworkCloseClient(cs);
00182 }
00183
00184 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHECK_NEWGRFS)(NetworkTCPSocketHandler *cs)
00185 {
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 Packet *p = NetworkSend_Init(PACKET_SERVER_CHECK_NEWGRFS);
00197 const GRFConfig *c;
00198 uint grf_count = 0;
00199
00200 for (c = _grfconfig; c != NULL; c = c->next) {
00201 if (!HasBit(c->flags, GCF_STATIC)) grf_count++;
00202 }
00203
00204 p->Send_uint8 (grf_count);
00205 for (c = _grfconfig; c != NULL; c = c->next) {
00206 if (!HasBit(c->flags, GCF_STATIC)) cs->Send_GRFIdentifier(p, c);
00207 }
00208
00209 cs->Send_Packet(p);
00210 }
00211
00212 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkTCPSocketHandler *cs, NetworkPasswordType type)
00213 {
00214
00215
00216
00217
00218
00219
00220
00221
00222 if (cs->status >= STATUS_AUTH) return;
00223
00224 cs->status = STATUS_AUTHORIZING;
00225
00226 Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
00227 p->Send_uint8(type);
00228 p->Send_uint32(_patches.generation_seed);
00229 p->Send_string(_network_unique_id);
00230 cs->Send_Packet(p);
00231 }
00232
00233 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WELCOME)
00234 {
00235
00236
00237
00238
00239
00240
00241
00242 Packet *p;
00243 NetworkTCPSocketHandler *new_cs;
00244
00245
00246 if (cs->status >= STATUS_AUTH) return;
00247
00248 cs->status = STATUS_AUTH;
00249 _network_game_info.clients_on++;
00250
00251 p = NetworkSend_Init(PACKET_SERVER_WELCOME);
00252 p->Send_uint16(cs->index);
00253 p->Send_uint32(_patches.generation_seed);
00254 p->Send_string(_network_unique_id);
00255 cs->Send_Packet(p);
00256
00257
00258 FOR_ALL_CLIENTS(new_cs) {
00259 if (new_cs != cs && new_cs->status > STATUS_AUTH)
00260 SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, DEREF_CLIENT_INFO(new_cs));
00261 }
00262
00263 SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX));
00264 }
00265
00266 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WAIT)
00267 {
00268
00269
00270
00271
00272
00273
00274
00275 int waiting = 0;
00276 NetworkTCPSocketHandler *new_cs;
00277 Packet *p;
00278
00279
00280 FOR_ALL_CLIENTS(new_cs) {
00281 if (new_cs->status == STATUS_MAP_WAIT) waiting++;
00282 }
00283
00284 p = NetworkSend_Init(PACKET_SERVER_WAIT);
00285 p->Send_uint8(waiting);
00286 cs->Send_Packet(p);
00287 }
00288
00289
00290 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
00291 {
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 static FILE *file_pointer;
00309 static uint sent_packets;
00310
00311 if (cs->status < STATUS_AUTH) {
00312
00313 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
00314 return;
00315 }
00316
00317 if (cs->status == STATUS_AUTH) {
00318 const char *filename = "network_server.tmp";
00319 Packet *p;
00320
00321
00322 if (SaveOrLoad(filename, SL_SAVE, AUTOSAVE_DIR) != SL_OK) error("network savedump failed");
00323
00324 file_pointer = FioFOpenFile(filename, "rb", AUTOSAVE_DIR);
00325 fseek(file_pointer, 0, SEEK_END);
00326
00327 if (ftell(file_pointer) == 0) error("network savedump failed - zero sized savegame?");
00328
00329
00330 p = NetworkSend_Init(PACKET_SERVER_MAP);
00331 p->Send_uint8 (MAP_PACKET_START);
00332 p->Send_uint32(_frame_counter);
00333 p->Send_uint32(ftell(file_pointer));
00334 cs->Send_Packet(p);
00335
00336 fseek(file_pointer, 0, SEEK_SET);
00337
00338 sent_packets = 4;
00339
00340 cs->status = STATUS_MAP;
00341
00342 cs->last_frame = _frame_counter;
00343 cs->last_frame_server = _frame_counter;
00344 }
00345
00346 if (cs->status == STATUS_MAP) {
00347 uint i;
00348 int res;
00349 for (i = 0; i < sent_packets; i++) {
00350 Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
00351 p->Send_uint8(MAP_PACKET_NORMAL);
00352 res = (int)fread(p->buffer + p->size, 1, SEND_MTU - p->size, file_pointer);
00353
00354 if (ferror(file_pointer)) error("Error reading temporary network savegame!");
00355
00356 p->size += res;
00357 cs->Send_Packet(p);
00358 if (feof(file_pointer)) {
00359
00360 Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
00361 p->Send_uint8(MAP_PACKET_END);
00362 cs->Send_Packet(p);
00363
00364
00365
00366 cs->status = STATUS_DONE_MAP;
00367 fclose(file_pointer);
00368
00369 {
00370 NetworkTCPSocketHandler *new_cs;
00371 bool new_map_client = false;
00372
00373
00374 FOR_ALL_CLIENTS(new_cs) {
00375 if (new_cs->status == STATUS_MAP_WAIT) {
00376
00377 if (!new_map_client) {
00378
00379 new_cs->status = STATUS_AUTH;
00380 new_map_client = true;
00381 SEND_COMMAND(PACKET_SERVER_MAP)(new_cs);
00382 } else {
00383
00384 SEND_COMMAND(PACKET_SERVER_WAIT)(new_cs);
00385 }
00386 }
00387 }
00388 }
00389
00390
00391 break;
00392 }
00393 }
00394
00395
00396 cs->Send_Packets();
00397 if (cs->IsPacketQueueEmpty()) {
00398
00399 sent_packets *= 2;
00400 } else {
00401
00402 if (sent_packets > 1) sent_packets /= 2;
00403 }
00404 }
00405 }
00406
00407 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_JOIN)(NetworkTCPSocketHandler *cs, uint16 client_index)
00408 {
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 Packet *p = NetworkSend_Init(PACKET_SERVER_JOIN);
00419
00420 p->Send_uint16(client_index);
00421
00422 cs->Send_Packet(p);
00423 }
00424
00425
00426 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_FRAME)
00427 {
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 Packet *p = NetworkSend_Init(PACKET_SERVER_FRAME);
00440 p->Send_uint32(_frame_counter);
00441 p->Send_uint32(_frame_counter_max);
00442 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
00443 p->Send_uint32(_sync_seed_1);
00444 #ifdef NETWORK_SEND_DOUBLE_SEED
00445 p->Send_uint32(_sync_seed_2);
00446 #endif
00447 #endif
00448 cs->Send_Packet(p);
00449 }
00450
00451 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SYNC)
00452 {
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 Packet *p = NetworkSend_Init(PACKET_SERVER_SYNC);
00464 p->Send_uint32(_frame_counter);
00465 p->Send_uint32(_sync_seed_1);
00466
00467 #ifdef NETWORK_SEND_DOUBLE_SEED
00468 p->Send_uint32(_sync_seed_2);
00469 #endif
00470 cs->Send_Packet(p);
00471 }
00472
00473 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_COMMAND)(NetworkTCPSocketHandler *cs, CommandPacket *cp)
00474 {
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 Packet *p = NetworkSend_Init(PACKET_SERVER_COMMAND);
00490
00491 p->Send_uint8 (cp->player);
00492 p->Send_uint32(cp->cmd);
00493 p->Send_uint32(cp->p1);
00494 p->Send_uint32(cp->p2);
00495 p->Send_uint32(cp->tile);
00496 p->Send_string(cp->text);
00497 p->Send_uint8 (cp->callback);
00498 p->Send_uint32(cp->frame);
00499 p->Send_bool (cp->my_cmd);
00500
00501 cs->Send_Packet(p);
00502 }
00503
00504 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(NetworkTCPSocketHandler *cs, NetworkAction action, uint16 client_index, bool self_send, const char *msg)
00505 {
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 Packet *p = NetworkSend_Init(PACKET_SERVER_CHAT);
00516
00517 p->Send_uint8 (action);
00518 p->Send_uint16(client_index);
00519 p->Send_bool (self_send);
00520 p->Send_string(msg);
00521
00522 cs->Send_Packet(p);
00523 }
00524
00525 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkTCPSocketHandler *cs, uint16 client_index, NetworkErrorCode errorno)
00526 {
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR_QUIT);
00537
00538 p->Send_uint16(client_index);
00539 p->Send_uint8 (errorno);
00540
00541 cs->Send_Packet(p);
00542 }
00543
00544 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_QUIT)(NetworkTCPSocketHandler *cs, uint16 client_index, const char *leavemsg)
00545 {
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 Packet *p = NetworkSend_Init(PACKET_SERVER_QUIT);
00556
00557 p->Send_uint16(client_index);
00558 p->Send_string(leavemsg);
00559
00560 cs->Send_Packet(p);
00561 }
00562
00563 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN)
00564 {
00565
00566
00567
00568
00569
00570
00571
00572 Packet *p = NetworkSend_Init(PACKET_SERVER_SHUTDOWN);
00573 cs->Send_Packet(p);
00574 }
00575
00576 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME)
00577 {
00578
00579
00580
00581
00582
00583
00584
00585 Packet *p = NetworkSend_Init(PACKET_SERVER_NEWGAME);
00586 cs->Send_Packet(p);
00587 }
00588
00589 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkTCPSocketHandler *cs, uint16 color, const char *command)
00590 {
00591 Packet *p = NetworkSend_Init(PACKET_SERVER_RCON);
00592
00593 p->Send_uint16(color);
00594 p->Send_string(command);
00595 cs->Send_Packet(p);
00596 }
00597
00598
00599
00600
00601
00602
00603 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO)
00604 {
00605 SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(cs);
00606 }
00607
00608 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
00609 {
00610 if (cs->status != STATUS_INACTIVE) {
00611
00612 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00613 return;
00614 }
00615
00616 NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
00617
00618
00619 if (_network_game_info.use_password) {
00620 SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_GAME_PASSWORD);
00621 } else {
00622 if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
00623 SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
00624 } else {
00625 SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
00626 }
00627 }
00628 }
00629
00630 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
00631 {
00632 if (cs->status != STATUS_INACTIVE) {
00633
00634 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00635 return;
00636 }
00637
00638 char name[NETWORK_CLIENT_NAME_LENGTH];
00639 char unique_id[NETWORK_UNIQUE_ID_LENGTH];
00640 NetworkClientInfo *ci;
00641 PlayerID playas;
00642 NetworkLanguage client_lang;
00643 char client_revision[NETWORK_REVISION_LENGTH];
00644
00645 p->Recv_string(client_revision, sizeof(client_revision));
00646
00647
00648 if (!IsNetworkCompatibleVersion(client_revision)) {
00649
00650 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_REVISION);
00651 return;
00652 }
00653
00654 p->Recv_string(name, sizeof(name));
00655 playas = (Owner)p->Recv_uint8();
00656 client_lang = (NetworkLanguage)p->Recv_uint8();
00657 p->Recv_string(unique_id, sizeof(unique_id));
00658
00659 if (cs->has_quit) return;
00660
00661
00662 switch (playas) {
00663 case PLAYER_NEW_COMPANY:
00664 if (ActivePlayerCount() >= _network_game_info.companies_max) {
00665 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
00666 return;
00667 }
00668 break;
00669 case PLAYER_SPECTATOR:
00670 if (NetworkSpectatorCount() >= _network_game_info.spectators_max) {
00671 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
00672 return;
00673 }
00674 break;
00675 default:
00676 if (!IsValidPlayer(playas)) {
00677 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
00678 return;
00679 }
00680 break;
00681 }
00682
00683
00684 if (*name == '\0') ttd_strlcpy(name, "Player", sizeof(name));
00685
00686 if (!NetworkFindName(name)) {
00687
00688 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NAME_IN_USE);
00689 return;
00690 }
00691
00692 ci = DEREF_CLIENT_INFO(cs);
00693
00694 ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
00695 ttd_strlcpy(ci->unique_id, unique_id, sizeof(ci->unique_id));
00696 ci->client_playas = playas;
00697 ci->client_lang = client_lang;
00698
00699
00700 if (IsValidPlayer(playas)) _network_player_info[playas].months_empty = 0;
00701
00702 if (_grfconfig == NULL) {
00703 RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)(cs, NULL);
00704 } else {
00705 SEND_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)(cs);
00706 }
00707 }
00708
00709 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
00710 {
00711 NetworkPasswordType type;
00712 char password[NETWORK_PASSWORD_LENGTH];
00713 const NetworkClientInfo *ci;
00714
00715 type = (NetworkPasswordType)p->Recv_uint8();
00716 p->Recv_string(password, sizeof(password));
00717
00718 if (cs->status == STATUS_AUTHORIZING && type == NETWORK_GAME_PASSWORD) {
00719
00720 if (strcmp(password, _network_game_info.server_password) != 0) {
00721
00722 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
00723 return;
00724 }
00725
00726 ci = DEREF_CLIENT_INFO(cs);
00727
00728 if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
00729 SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
00730 return;
00731 }
00732
00733
00734 SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
00735 return;
00736 } else if (cs->status == STATUS_AUTHORIZING && type == NETWORK_COMPANY_PASSWORD) {
00737 ci = DEREF_CLIENT_INFO(cs);
00738
00739 if (strcmp(password, _network_player_info[ci->client_playas].password) != 0) {
00740
00741 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
00742 return;
00743 }
00744
00745 SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
00746 return;
00747 }
00748
00749
00750 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00751 return;
00752 }
00753
00754 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
00755 {
00756 NetworkTCPSocketHandler *new_cs;
00757
00758
00759
00760 if (cs->status < STATUS_AUTH || cs->has_quit) {
00761 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
00762 return;
00763 }
00764
00765
00766 FOR_ALL_CLIENTS(new_cs) {
00767 if (new_cs->status == STATUS_MAP) {
00768
00769 cs->status = STATUS_MAP_WAIT;
00770 SEND_COMMAND(PACKET_SERVER_WAIT)(cs);
00771 return;
00772 }
00773 }
00774
00775
00776 SEND_COMMAND(PACKET_SERVER_MAP)(cs);
00777 }
00778
00779 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
00780 {
00781
00782 if (cs->status == STATUS_DONE_MAP && !cs->has_quit) {
00783 char client_name[NETWORK_CLIENT_NAME_LENGTH];
00784 NetworkTCPSocketHandler *new_cs;
00785
00786 NetworkGetClientName(client_name, sizeof(client_name), cs);
00787
00788 NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, client_name, "");
00789
00790
00791
00792 cs->status = STATUS_PRE_ACTIVE;
00793 NetworkHandleCommandQueue(cs);
00794 SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
00795 SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
00796
00797
00798
00799 cs->last_frame = _frame_counter;
00800 cs->last_frame_server = _frame_counter;
00801
00802 FOR_ALL_CLIENTS(new_cs) {
00803 if (new_cs->status > STATUS_AUTH) {
00804 SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, DEREF_CLIENT_INFO(cs));
00805 SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->index);
00806 }
00807 }
00808
00809 if (_network_pause_on_join) {
00810
00811 DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
00812
00813 NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (incoming client)", NETWORK_SERVER_INDEX);
00814 }
00815 } else {
00816
00817 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00818 }
00819 }
00820
00826 static bool CheckCommandFlags(const CommandPacket *cp, const NetworkClientInfo *ci)
00827 {
00828 byte flags = GetCommandFlags(cp->cmd);
00829
00830 if (flags & CMD_SERVER && ci->client_index != NETWORK_SERVER_INDEX) {
00831 IConsolePrintF(_icolour_err, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
00832 return false;
00833 }
00834
00835 if (flags & CMD_OFFLINE) {
00836 IConsolePrintF(_icolour_err, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
00837 return false;
00838 }
00839
00840 if (cp->cmd != CMD_PLAYER_CTRL && !IsValidPlayer(cp->player) && ci->client_index != NETWORK_SERVER_INDEX) {
00841 IConsolePrintF(_icolour_err, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
00842 return false;
00843 }
00844
00845 return true;
00846 }
00847
00852 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
00853 {
00854 NetworkTCPSocketHandler *new_cs;
00855 const NetworkClientInfo *ci;
00856 byte callback;
00857
00858
00859
00860 if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
00861 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00862 return;
00863 }
00864
00865 CommandPacket *cp = MallocT<CommandPacket>(1);
00866 cp->player = (Owner)p->Recv_uint8();
00867 cp->cmd = p->Recv_uint32();
00868 cp->p1 = p->Recv_uint32();
00869 cp->p2 = p->Recv_uint32();
00870 cp->tile = p->Recv_uint32();
00871 p->Recv_string(cp->text, lengthof(cp->text));
00872
00873 callback = p->Recv_uint8();
00874
00875 if (cs->has_quit) {
00876 free(cp);
00877 return;
00878 }
00879
00880 ci = DEREF_CLIENT_INFO(cs);
00881
00882
00883 if (!IsValidCommand(cp->cmd)) {
00884 IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci));
00885 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
00886 free(cp);
00887 return;
00888 }
00889
00890 if (!CheckCommandFlags(cp, ci)) {
00891 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED);
00892 free(cp);
00893 return;
00894 }
00895
00900 if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0 && ci->client_playas == PLAYER_NEW_COMPANY) && ci->client_playas != cp->player) {
00901 IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...",
00902 ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1);
00903 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
00904 free(cp);
00905 return;
00906 }
00907
00913 if (cp->cmd == CMD_PLAYER_CTRL) {
00914 if (cp->p1 != 0) {
00915 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER);
00916 free(cp);
00917 return;
00918 }
00919
00920
00921
00922
00923 cp->player = OWNER_BEGIN;
00924 cp->p2 = cs - _clients;
00925 }
00926
00927
00928
00929 cp->frame = _frame_counter_max + 1;
00930 cp->next = NULL;
00931
00932
00933
00934 FOR_ALL_CLIENTS(new_cs) {
00935 if (new_cs->status >= STATUS_MAP) {
00936
00937
00938 cp->callback = (new_cs != cs) ? 0 : callback;
00939 cp->my_cmd = (new_cs == cs);
00940 NetworkAddCommandQueue(new_cs, cp);
00941 }
00942 }
00943
00944 cp->callback = 0;
00945 cp->my_cmd = false;
00946
00947 if (_local_command_queue == NULL) {
00948 _local_command_queue = cp;
00949 } else {
00950
00951 CommandPacket *c = _local_command_queue;
00952 while (c->next != NULL) c = c->next;
00953 c->next = cp;
00954 }
00955 }
00956
00957 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
00958 {
00959
00960
00961 NetworkTCPSocketHandler *new_cs;
00962 char str[100];
00963 char client_name[NETWORK_CLIENT_NAME_LENGTH];
00964 NetworkErrorCode errorno = (NetworkErrorCode)p->Recv_uint8();
00965
00966
00967 if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
00968 cs->has_quit = true;
00969 return;
00970 }
00971
00972 NetworkGetClientName(client_name, sizeof(client_name), cs);
00973
00974 GetNetworkErrorMsg(str, errorno, lastof(str));
00975
00976 DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
00977
00978 NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
00979
00980 FOR_ALL_CLIENTS(new_cs) {
00981 if (new_cs->status > STATUS_AUTH) {
00982 SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
00983 }
00984 }
00985
00986 cs->has_quit = true;
00987 }
00988
00989 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
00990 {
00991
00992
00993 NetworkTCPSocketHandler *new_cs;
00994 char str[100];
00995 char client_name[NETWORK_CLIENT_NAME_LENGTH];
00996
00997
00998 if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
00999 cs->has_quit = true;
01000 return;
01001 }
01002
01003 p->Recv_string(str, lengthof(str));
01004
01005 NetworkGetClientName(client_name, sizeof(client_name), cs);
01006
01007 NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
01008
01009 FOR_ALL_CLIENTS(new_cs) {
01010 if (new_cs->status > STATUS_AUTH) {
01011 SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->index, str);
01012 }
01013 }
01014
01015 cs->has_quit = true;
01016 }
01017
01018 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
01019 {
01020 if (cs->status < STATUS_AUTH) {
01021
01022 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
01023 return;
01024 }
01025
01026 uint32 frame = p->Recv_uint32();
01027
01028
01029 if (cs->status == STATUS_PRE_ACTIVE) {
01030
01031 if (frame + DAY_TICKS < _frame_counter) return;
01032
01033
01034 cs->status = STATUS_ACTIVE;
01035
01036 if (_network_pause_on_join) {
01037 DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
01038 NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (client connected)", NETWORK_SERVER_INDEX);
01039 }
01040
01041 CheckMinPlayers();
01042
01043
01044 IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
01045 }
01046
01047
01048 cs->last_frame = frame;
01049
01050 cs->last_frame_server = _frame_counter;
01051 }
01052
01053
01054
01055 void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
01056 {
01057 NetworkTCPSocketHandler *cs;
01058 const NetworkClientInfo *ci, *ci_own, *ci_to;
01059
01060 switch (desttype) {
01061 case DESTTYPE_CLIENT:
01062
01063 if (dest == NETWORK_SERVER_INDEX) {
01064 ci = NetworkFindClientInfoFromIndex(from_index);
01065
01066 if (ci != NULL)
01067 NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
01068 } else {
01069
01070 FOR_ALL_CLIENTS(cs) {
01071 if (cs->index == dest) {
01072 SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
01073 break;
01074 }
01075 }
01076 }
01077
01078
01079 if (from_index != dest) {
01080 if (from_index == NETWORK_SERVER_INDEX) {
01081 ci = NetworkFindClientInfoFromIndex(from_index);
01082 ci_to = NetworkFindClientInfoFromIndex(dest);
01083 if (ci != NULL && ci_to != NULL)
01084 NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), true, ci_to->client_name, "%s", msg);
01085 } else {
01086 FOR_ALL_CLIENTS(cs) {
01087 if (cs->index == from_index) {
01088 SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, dest, true, msg);
01089 break;
01090 }
01091 }
01092 }
01093 }
01094 break;
01095 case DESTTYPE_TEAM: {
01096 bool show_local = true;
01097
01098
01099 ci_to = NULL;
01100 FOR_ALL_CLIENTS(cs) {
01101 ci = DEREF_CLIENT_INFO(cs);
01102 if (ci->client_playas == dest) {
01103 SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
01104 if (cs->index == from_index) show_local = false;
01105 ci_to = ci;
01106 }
01107 }
01108
01109 ci = NetworkFindClientInfoFromIndex(from_index);
01110 ci_own = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
01111 if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
01112 NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
01113 if (from_index == NETWORK_SERVER_INDEX) show_local = false;
01114 ci_to = ci_own;
01115 }
01116
01117
01118 if (ci_to == NULL) break;
01119
01120
01121 if (ci != NULL && show_local) {
01122 if (from_index == NETWORK_SERVER_INDEX) {
01123 char name[NETWORK_NAME_LENGTH];
01124 StringID str = IsValidPlayer(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
01125 SetDParam(0, ci_to->client_playas);
01126 GetString(name, str, lastof(name));
01127 NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg);
01128 } else {
01129 FOR_ALL_CLIENTS(cs) {
01130 if (cs->index == from_index) {
01131 SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, ci_to->client_index, true, msg);
01132 }
01133 }
01134 }
01135 }
01136 }
01137 break;
01138 default:
01139 DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
01140
01141 case DESTTYPE_BROADCAST:
01142 FOR_ALL_CLIENTS(cs) {
01143 SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
01144 }
01145 ci = NetworkFindClientInfoFromIndex(from_index);
01146 if (ci != NULL)
01147 NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
01148 break;
01149 }
01150 }
01151
01152 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT)
01153 {
01154 if (cs->status < STATUS_AUTH) {
01155
01156 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
01157 return;
01158 }
01159
01160 NetworkAction action = (NetworkAction)p->Recv_uint8();
01161 DestType desttype = (DestType)p->Recv_uint8();
01162 int dest = p->Recv_uint16();
01163 char msg[MAX_TEXT_MSG_LEN];
01164
01165 p->Recv_string(msg, MAX_TEXT_MSG_LEN);
01166
01167 const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
01168 switch (action) {
01169 case NETWORK_ACTION_GIVE_MONEY:
01170 if (!IsValidPlayer(ci->client_playas)) break;
01171
01172 case NETWORK_ACTION_CHAT:
01173 case NETWORK_ACTION_CHAT_CLIENT:
01174 case NETWORK_ACTION_CHAT_COMPANY:
01175 NetworkServer_HandleChat(action, desttype, dest, msg, cs->index);
01176 break;
01177 default:
01178 IConsolePrintF(_icolour_err, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci));
01179 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
01180 break;
01181 }
01182 }
01183
01184 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
01185 {
01186 if (cs->status != STATUS_ACTIVE) {
01187
01188 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
01189 return;
01190 }
01191
01192 char password[NETWORK_PASSWORD_LENGTH];
01193 const NetworkClientInfo *ci;
01194
01195 p->Recv_string(password, sizeof(password));
01196 ci = DEREF_CLIENT_INFO(cs);
01197
01198 if (IsValidPlayer(ci->client_playas)) {
01199 ttd_strlcpy(_network_player_info[ci->client_playas].password, password, sizeof(_network_player_info[0].password));
01200 }
01201 }
01202
01203 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME)
01204 {
01205 if (cs->status != STATUS_ACTIVE) {
01206
01207 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
01208 return;
01209 }
01210
01211 char client_name[NETWORK_CLIENT_NAME_LENGTH];
01212 NetworkClientInfo *ci;
01213
01214 p->Recv_string(client_name, sizeof(client_name));
01215 ci = DEREF_CLIENT_INFO(cs);
01216
01217 if (cs->has_quit) return;
01218
01219 if (ci != NULL) {
01220
01221 if (NetworkFindName(client_name)) {
01222 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", client_name);
01223 ttd_strlcpy(ci->client_name, client_name, sizeof(ci->client_name));
01224 NetworkUpdateClientInfo(ci->client_index);
01225 }
01226 }
01227 }
01228
01229 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_RCON)
01230 {
01231 char pass[NETWORK_PASSWORD_LENGTH];
01232 char command[NETWORK_RCONCOMMAND_LENGTH];
01233
01234 if (_network_game_info.rcon_password[0] == '\0') return;
01235
01236 p->Recv_string(pass, sizeof(pass));
01237 p->Recv_string(command, sizeof(command));
01238
01239 if (strcmp(pass, _network_game_info.rcon_password) != 0) {
01240 DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->index);
01241 return;
01242 }
01243
01244 DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", cs->index, command);
01245
01246 _redirect_console_to_client = cs->index;
01247 IConsoleCmdExec(command);
01248 _redirect_console_to_client = 0;
01249 return;
01250 }
01251
01252
01253 typedef void NetworkServerPacket(NetworkTCPSocketHandler *cs, Packet *p);
01254
01255
01256
01257
01258
01259
01260 static NetworkServerPacket* const _network_server_packet[] = {
01261 NULL,
01262 NULL,
01263 RECEIVE_COMMAND(PACKET_CLIENT_JOIN),
01264 NULL,
01265 RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO),
01266 NULL,
01267 NULL,
01268 NULL,
01269 RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD),
01270 NULL,
01271 RECEIVE_COMMAND(PACKET_CLIENT_GETMAP),
01272 NULL,
01273 NULL,
01274 RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK),
01275 NULL,
01276 NULL,
01277 NULL,
01278 RECEIVE_COMMAND(PACKET_CLIENT_ACK),
01279 RECEIVE_COMMAND(PACKET_CLIENT_COMMAND),
01280 NULL,
01281 RECEIVE_COMMAND(PACKET_CLIENT_CHAT),
01282 NULL,
01283 RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD),
01284 RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME),
01285 RECEIVE_COMMAND(PACKET_CLIENT_QUIT),
01286 RECEIVE_COMMAND(PACKET_CLIENT_ERROR),
01287 NULL,
01288 NULL,
01289 NULL,
01290 NULL,
01291 NULL,
01292 RECEIVE_COMMAND(PACKET_CLIENT_RCON),
01293 NULL,
01294 RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED),
01295 };
01296
01297
01298 assert_compile(lengthof(_network_server_packet) == PACKET_END);
01299
01300
01301 void NetworkPopulateCompanyInfo()
01302 {
01303 char password[NETWORK_PASSWORD_LENGTH];
01304 const Player *p;
01305 const Vehicle *v;
01306 const Station *s;
01307 NetworkTCPSocketHandler *cs;
01308 const NetworkClientInfo *ci;
01309 uint i;
01310 uint16 months_empty;
01311
01312 FOR_ALL_PLAYERS(p) {
01313 if (!p->is_active) {
01314 memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo));
01315 continue;
01316 }
01317
01318
01319 ttd_strlcpy(password, _network_player_info[p->index].password, sizeof(password));
01320 months_empty = _network_player_info[p->index].months_empty;
01321 memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo));
01322 _network_player_info[p->index].months_empty = months_empty;
01323 ttd_strlcpy(_network_player_info[p->index].password, password, sizeof(_network_player_info[p->index].password));
01324
01325
01326 SetDParam(0, p->index);
01327 GetString(_network_player_info[p->index].company_name, STR_COMPANY_NAME, lastof(_network_player_info[p->index].company_name));
01328
01329
01330 if (_cur_year - 1 == p->inaugurated_year) {
01331
01332 for (i = 0; i < lengthof(p->yearly_expenses[2]); i++) {
01333 _network_player_info[p->index].income -= p->yearly_expenses[2][i];
01334 }
01335 } else {
01336 for (i = 0; i < lengthof(p->yearly_expenses[1]); i++) {
01337 _network_player_info[p->index].income -= p->yearly_expenses[1][i];
01338 }
01339 }
01340
01341
01342 _network_player_info[p->index].inaugurated_year = p->inaugurated_year;
01343 _network_player_info[p->index].company_value = p->old_economy[0].company_value;
01344 _network_player_info[p->index].money = p->player_money;
01345 _network_player_info[p->index].performance = p->old_economy[0].performance_history;
01346 }
01347
01348
01349 FOR_ALL_VEHICLES(v) {
01350 if (!IsValidPlayer(v->owner) || !v->IsPrimaryVehicle()) continue;
01351 byte type = 0;
01352 switch (v->type) {
01353 case VEH_TRAIN: type = 0; break;
01354 case VEH_ROAD: type = (v->cargo_type != CT_PASSENGERS) ? 1 : 2; break;
01355 case VEH_AIRCRAFT: type = 3; break;
01356 case VEH_SHIP: type = 4; break;
01357 default: continue;
01358 }
01359 _network_player_info[v->owner].num_vehicle[type]++;
01360 }
01361
01362
01363 FOR_ALL_STATIONS(s) {
01364 if (IsValidPlayer(s->owner)) {
01365 NetworkPlayerInfo *npi = &_network_player_info[s->owner];
01366
01367 if (s->facilities & FACIL_TRAIN) npi->num_station[0]++;
01368 if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[1]++;
01369 if (s->facilities & FACIL_BUS_STOP) npi->num_station[2]++;
01370 if (s->facilities & FACIL_AIRPORT) npi->num_station[3]++;
01371 if (s->facilities & FACIL_DOCK) npi->num_station[4]++;
01372 }
01373 }
01374
01375 ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
01376
01377 if (ci != NULL && IsValidPlayer(ci->client_playas))
01378 ttd_strlcpy(_network_player_info[ci->client_playas].players, ci->client_name, sizeof(_network_player_info[0].players));
01379
01380 FOR_ALL_CLIENTS(cs) {
01381 char client_name[NETWORK_CLIENT_NAME_LENGTH];
01382
01383 NetworkGetClientName(client_name, sizeof(client_name), cs);
01384
01385 ci = DEREF_CLIENT_INFO(cs);
01386 if (ci != NULL && IsValidPlayer(ci->client_playas)) {
01387 if (!StrEmpty(_network_player_info[ci->client_playas].players)) {
01388 ttd_strlcat(_network_player_info[ci->client_playas].players, ", ", lengthof(_network_player_info[0].players));
01389 }
01390
01391 ttd_strlcat(_network_player_info[ci->client_playas].players, client_name, lengthof(_network_player_info[0].players));
01392 }
01393 }
01394 }
01395
01396
01397 void NetworkUpdateClientInfo(uint16 client_index)
01398 {
01399 NetworkTCPSocketHandler *cs;
01400 NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(client_index);
01401
01402 if (ci == NULL) return;
01403
01404 FOR_ALL_CLIENTS(cs) {
01405 SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, ci);
01406 }
01407 }
01408
01409
01410 static void NetworkCheckRestartMap()
01411 {
01412 if (_network_restart_game_year != 0 && _cur_year >= _network_restart_game_year) {
01413 DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
01414
01415 StartNewGameWithoutGUI(GENERATE_NEW_SEED);
01416 }
01417 }
01418
01419
01420
01421
01422
01423
01424 static void NetworkAutoCleanCompanies()
01425 {
01426 NetworkTCPSocketHandler *cs;
01427 const NetworkClientInfo *ci;
01428 const Player *p;
01429 bool clients_in_company[MAX_PLAYERS];
01430
01431 if (!_network_autoclean_companies) return;
01432
01433 memset(clients_in_company, 0, sizeof(clients_in_company));
01434
01435
01436 FOR_ALL_CLIENTS(cs) {
01437 ci = DEREF_CLIENT_INFO(cs);
01438 if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
01439 }
01440
01441 if (!_network_dedicated) {
01442 ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
01443 if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
01444 }
01445
01446
01447 FOR_ALL_PLAYERS(p) {
01448
01449 if (!p->is_active || p->is_ai) continue;
01450
01451 if (!clients_in_company[p->index]) {
01452
01453 _network_player_info[p->index].months_empty++;
01454
01455
01456 if (_network_player_info[p->index].months_empty > _network_autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') {
01457
01458 DoCommandP(0, 2, p->index, NULL, CMD_PLAYER_CTRL);
01459 IConsolePrintF(_icolour_def, "Auto-cleaned company #%d", p->index + 1);
01460 }
01461
01462 if (_network_player_info[p->index].months_empty > _network_autoclean_protected && _network_player_info[p->index].password[0] != '\0') {
01463
01464 _network_player_info[p->index].password[0] = '\0';
01465 IConsolePrintF(_icolour_def, "Auto-removed protection from company #%d", p->index+1);
01466 _network_player_info[p->index].months_empty = 0;
01467 }
01468 } else {
01469
01470 _network_player_info[p->index].months_empty = 0;
01471 }
01472 }
01473 }
01474
01475
01476
01477 bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
01478 {
01479 NetworkTCPSocketHandler *new_cs;
01480 bool found_name = false;
01481 byte number = 0;
01482 char original_name[NETWORK_CLIENT_NAME_LENGTH];
01483
01484
01485 ttd_strlcpy(original_name, new_name, NETWORK_CLIENT_NAME_LENGTH);
01486
01487 while (!found_name) {
01488 const NetworkClientInfo *ci;
01489
01490 found_name = true;
01491 FOR_ALL_CLIENTS(new_cs) {
01492 ci = DEREF_CLIENT_INFO(new_cs);
01493 if (strcmp(ci->client_name, new_name) == 0) {
01494
01495 found_name = false;
01496 break;
01497 }
01498 }
01499
01500 ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
01501 if (ci != NULL) {
01502 if (strcmp(ci->client_name, new_name) == 0) found_name = false;
01503 }
01504
01505 if (!found_name) {
01506
01507
01508
01509 if (number++ > 50) break;
01510 snprintf(new_name, NETWORK_CLIENT_NAME_LENGTH, "%s #%d", original_name, number);
01511 }
01512 }
01513
01514 return found_name;
01515 }
01516
01517
01518 bool NetworkServer_ReadPackets(NetworkTCPSocketHandler *cs)
01519 {
01520 Packet *p;
01521 NetworkRecvStatus res;
01522 while ((p = cs->Recv_Packet(&res)) != NULL) {
01523 byte type = p->Recv_uint8();
01524 if (type < PACKET_END && _network_server_packet[type] != NULL && !cs->has_quit) {
01525 _network_server_packet[type](cs, p);
01526 } else {
01527 DEBUG(net, 0, "[server] received invalid packet type %d", type);
01528 }
01529 delete p;
01530 }
01531
01532 return true;
01533 }
01534
01535
01536 static void NetworkHandleCommandQueue(NetworkTCPSocketHandler* cs)
01537 {
01538 CommandPacket *cp;
01539
01540 while ( (cp = cs->command_queue) != NULL) {
01541 SEND_COMMAND(PACKET_SERVER_COMMAND)(cs, cp);
01542
01543 cs->command_queue = cp->next;
01544 free(cp);
01545 }
01546 }
01547
01548
01549 void NetworkServer_Tick(bool send_frame)
01550 {
01551 NetworkTCPSocketHandler *cs;
01552 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01553 bool send_sync = false;
01554 #endif
01555
01556 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01557 if (_frame_counter >= _last_sync_frame + _network_sync_freq) {
01558 _last_sync_frame = _frame_counter;
01559 send_sync = true;
01560 }
01561 #endif
01562
01563
01564
01565 FOR_ALL_CLIENTS(cs) {
01566
01567 if (cs->status == STATUS_ACTIVE) {
01568
01569 int lag = NetworkCalculateLag(cs) / DAY_TICKS;
01570 if (lag > 0) {
01571 if (lag > 3) {
01572
01573
01574 IConsolePrintF(_icolour_err,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->index);
01575 NetworkCloseClient(cs);
01576 continue;
01577 }
01578
01579
01580 if (cs->lag_test == 0) {
01581 IConsolePrintF(_icolour_warn,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index);
01582 cs->lag_test = 1;
01583 }
01584 } else {
01585 cs->lag_test = 0;
01586 }
01587 } else if (cs->status == STATUS_PRE_ACTIVE) {
01588 int lag = NetworkCalculateLag(cs);
01589 if (lag > _network_max_join_time) {
01590 IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
01591 NetworkCloseClient(cs);
01592 }
01593 } else if (cs->status == STATUS_INACTIVE) {
01594 int lag = NetworkCalculateLag(cs);
01595 if (lag > 4 * DAY_TICKS) {
01596 IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->index, 4 * DAY_TICKS);
01597 NetworkCloseClient(cs);
01598 }
01599 }
01600
01601 if (cs->status >= STATUS_PRE_ACTIVE) {
01602
01603 NetworkHandleCommandQueue(cs);
01604
01605
01606 if (send_frame) SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
01607
01608 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01609
01610 if (send_sync) SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
01611 #endif
01612 }
01613 }
01614
01615
01616 NetworkUDPAdvertise();
01617 }
01618
01619 void NetworkServerYearlyLoop()
01620 {
01621 NetworkCheckRestartMap();
01622 }
01623
01624 void NetworkServerMonthlyLoop()
01625 {
01626 NetworkAutoCleanCompanies();
01627 }
01628
01629 #endif