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