00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifdef ENABLE_NETWORK
00013
00014 #include "../stdafx.h"
00015 #include "../strings_func.h"
00016 #include "../date_func.h"
00017 #include "network_admin.h"
00018 #include "network_server.h"
00019 #include "network_udp.h"
00020 #include "network_base.h"
00021 #include "../console_func.h"
00022 #include "../company_base.h"
00023 #include "../command_func.h"
00024 #include "../saveload/saveload.h"
00025 #include "../saveload/saveload_filter.h"
00026 #include "../station_base.h"
00027 #include "../genworld.h"
00028 #include "../company_func.h"
00029 #include "../company_gui.h"
00030 #include "../window_func.h"
00031 #include "../roadveh.h"
00032 #include "../order_backup.h"
00033 #include "../core/pool_func.hpp"
00034 #include "../core/random_func.hpp"
00035 #include "../rev.h"
00036
00037
00038
00039
00040 DECLARE_POSTFIX_INCREMENT(ClientID)
00042 static ClientID _network_client_id = CLIENT_ID_FIRST;
00043
00045 assert_compile(MAX_CLIENT_SLOTS > MAX_CLIENTS);
00046 assert_compile(NetworkClientSocketPool::MAX_SIZE == MAX_CLIENT_SLOTS);
00047
00048 NetworkClientSocketPool _networkclientsocket_pool("NetworkClientSocket");
00049 INSTANTIATE_POOL_METHODS(NetworkClientSocket)
00050
00052 template SocketList TCPListenHandler<ServerNetworkGameSocketHandler, PACKET_SERVER_FULL, PACKET_SERVER_BANNED>::sockets;
00053
00055 struct PacketWriter : SaveFilter {
00056 ServerNetworkGameSocketHandler *cs;
00057 Packet *current;
00058 size_t total_size;
00059
00064 PacketWriter(ServerNetworkGameSocketHandler *cs) : SaveFilter(NULL), cs(cs), current(NULL), total_size(0)
00065 {
00066 this->cs->savegame_mutex = ThreadMutex::New();
00067 }
00068
00070 ~PacketWriter()
00071 {
00072
00073 if (this->cs != NULL) {
00074 if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical();
00075 this->cs->savegame = NULL;
00076 if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical();
00077
00078 delete this->cs->savegame_mutex;
00079 this->cs->savegame_mutex = NULL;
00080 }
00081
00082 delete this->current;
00083 }
00084
00086 void AppendQueue()
00087 {
00088 if (this->current == NULL) return;
00089
00090 Packet **p = &this->cs->savegame_packets;
00091 while (*p != NULL) {
00092 p = &(*p)->next;
00093 }
00094 *p = this->current;
00095
00096 this->current = NULL;
00097 }
00098
00099 void Write(byte *buf, size_t size)
00100 {
00101
00102 if (this->cs == NULL) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
00103
00104 if (this->current == NULL) this->current = new Packet(PACKET_SERVER_MAP_DATA);
00105
00106 if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical();
00107
00108 byte *bufe = buf + size;
00109 while (buf != bufe) {
00110 size_t to_write = min(SEND_MTU - this->current->size, bufe - buf);
00111 memcpy(this->current->buffer + this->current->size, buf, to_write);
00112 this->current->size += (PacketSize)to_write;
00113 buf += to_write;
00114
00115 if (this->current->size == SEND_MTU) {
00116 this->AppendQueue();
00117 if (buf != bufe) this->current = new Packet(PACKET_SERVER_MAP_DATA);
00118 }
00119 }
00120
00121 if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical();
00122
00123 this->total_size += size;
00124 }
00125
00126 void Finish()
00127 {
00128
00129 if (this->cs == NULL) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
00130
00131 if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical();
00132
00133
00134 this->AppendQueue();
00135
00136
00137 this->current = new Packet(PACKET_SERVER_MAP_DONE);
00138 this->AppendQueue();
00139
00140
00141 Packet *p = new Packet(PACKET_SERVER_MAP_SIZE);
00142 p->Send_uint32((uint32)this->total_size);
00143 this->cs->NetworkTCPSocketHandler::SendPacket(p);
00144
00145 if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical();
00146 }
00147 };
00148
00149
00154 ServerNetworkGameSocketHandler::ServerNetworkGameSocketHandler(SOCKET s) : NetworkGameSocketHandler(s)
00155 {
00156 this->status = STATUS_INACTIVE;
00157 this->client_id = _network_client_id++;
00158 this->receive_limit = _settings_client.network.bytes_per_frame_burst;
00159
00160
00161
00162
00163 assert_compile(NetworkClientSocketPool::MAX_SIZE == NetworkClientInfoPool::MAX_SIZE);
00164 assert(NetworkClientInfo::CanAllocateItem());
00165
00166 NetworkClientInfo *ci = new NetworkClientInfo(this->client_id);
00167 this->SetInfo(ci);
00168 ci->client_playas = COMPANY_INACTIVE_CLIENT;
00169 ci->join_date = _date;
00170 }
00171
00175 ServerNetworkGameSocketHandler::~ServerNetworkGameSocketHandler()
00176 {
00177 if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID;
00178 OrderBackup::ResetUser(this->client_id);
00179
00180 if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical();
00181 if (this->savegame != NULL) this->savegame->cs = NULL;
00182 if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical();
00183
00184
00185
00186
00187
00188 WaitTillSaved();
00189 ProcessAsyncSaveFinish();
00190
00191 while (this->savegame_packets != NULL) {
00192 Packet *p = this->savegame_packets->next;
00193 delete this->savegame_packets;
00194 this->savegame_packets = p;
00195 }
00196
00197 delete this->savegame_mutex;
00198 }
00199
00200 Packet *ServerNetworkGameSocketHandler::ReceivePacket()
00201 {
00202
00203
00204 if (this->receive_limit <= 0) return NULL;
00205
00206
00207
00208 Packet *p = this->NetworkTCPSocketHandler::ReceivePacket();
00209 if (p != NULL) this->receive_limit -= p->size;
00210 return p;
00211 }
00212
00213 void ServerNetworkGameSocketHandler::SendPacket(Packet *packet)
00214 {
00215 if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical();
00216 this->NetworkTCPSocketHandler::SendPacket(packet);
00217 if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical();
00218 }
00219
00220 NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvStatus status)
00221 {
00222 assert(status != NETWORK_RECV_STATUS_OKAY);
00223
00224
00225
00226
00227
00228
00229
00230 if (this->sock == INVALID_SOCKET) return status;
00231
00232 if (status != NETWORK_RECV_STATUS_CONN_LOST && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) {
00233
00234 char client_name[NETWORK_CLIENT_NAME_LENGTH];
00235 NetworkClientSocket *new_cs;
00236
00237 this->GetClientName(client_name, sizeof(client_name));
00238
00239 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST);
00240
00241
00242 FOR_ALL_CLIENT_SOCKETS(new_cs) {
00243 if (new_cs->status > STATUS_AUTHORIZED && this != new_cs) {
00244 new_cs->SendErrorQuit(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
00245 }
00246 }
00247 }
00248
00249 DEBUG(net, 1, "Closed client connection %d", this->client_id);
00250
00251
00252 if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
00253 extern byte _network_clients_connected;
00254 _network_clients_connected--;
00255
00256 SetWindowDirty(WC_CLIENT_LIST, 0);
00257
00258 this->SendPackets(true);
00259
00260 delete this->GetInfo();
00261 delete this;
00262
00263 return status;
00264 }
00265
00270 bool ServerNetworkGameSocketHandler::AllowConnection()
00271 {
00272 extern byte _network_clients_connected;
00273 bool accept = _network_clients_connected < MAX_CLIENTS && _network_game_info.clients_on < _settings_client.network.max_clients;
00274
00275
00276
00277 assert_compile(NetworkClientSocketPool::MAX_SIZE == MAX_CLIENTS + 1);
00278 assert(ServerNetworkGameSocketHandler::CanAllocateItem());
00279 return accept;
00280 }
00281
00283 void ServerNetworkGameSocketHandler::Send()
00284 {
00285 NetworkClientSocket *cs;
00286 FOR_ALL_CLIENT_SOCKETS(cs) {
00287 if (cs->writable) {
00288 if (cs->SendPackets() != SPS_CLOSED && cs->status == STATUS_MAP) {
00289
00290 cs->SendMap();
00291 }
00292 }
00293 }
00294 }
00295
00296 static void NetworkHandleCommandQueue(NetworkClientSocket *cs);
00297
00298
00299
00300
00301
00302
00303 NetworkRecvStatus ServerNetworkGameSocketHandler::SendClientInfo(NetworkClientInfo *ci)
00304 {
00305 if (ci->client_id != INVALID_CLIENT_ID) {
00306 Packet *p = new Packet(PACKET_SERVER_CLIENT_INFO);
00307 p->Send_uint32(ci->client_id);
00308 p->Send_uint8 (ci->client_playas);
00309 p->Send_string(ci->client_name);
00310
00311 this->SendPacket(p);
00312 }
00313 return NETWORK_RECV_STATUS_OKAY;
00314 }
00315
00316 NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo()
00317 {
00318
00319 NetworkCompanyStats company_stats[MAX_COMPANIES];
00320 NetworkPopulateCompanyStats(company_stats);
00321
00322
00323 char clients[MAX_COMPANIES][NETWORK_CLIENTS_LENGTH];
00324 NetworkClientSocket *csi;
00325 memset(clients, 0, sizeof(clients));
00326
00327
00328 const NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER);
00329 if (ci != NULL && Company::IsValidID(ci->client_playas)) {
00330 strecpy(clients[ci->client_playas], ci->client_name, lastof(clients[ci->client_playas]));
00331 }
00332
00333 FOR_ALL_CLIENT_SOCKETS(csi) {
00334 char client_name[NETWORK_CLIENT_NAME_LENGTH];
00335
00336 ((ServerNetworkGameSocketHandler*)csi)->GetClientName(client_name, sizeof(client_name));
00337
00338 ci = csi->GetInfo();
00339 if (ci != NULL && Company::IsValidID(ci->client_playas)) {
00340 if (!StrEmpty(clients[ci->client_playas])) {
00341 strecat(clients[ci->client_playas], ", ", lastof(clients[ci->client_playas]));
00342 }
00343
00344 strecat(clients[ci->client_playas], client_name, lastof(clients[ci->client_playas]));
00345 }
00346 }
00347
00348
00349
00350 Company *company;
00351 Packet *p;
00352
00353 FOR_ALL_COMPANIES(company) {
00354 p = new Packet(PACKET_SERVER_COMPANY_INFO);
00355
00356 p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00357 p->Send_bool (true);
00358 this->SendCompanyInformation(p, company, &company_stats[company->index]);
00359
00360 if (StrEmpty(clients[company->index])) {
00361 p->Send_string("<none>");
00362 } else {
00363 p->Send_string(clients[company->index]);
00364 }
00365
00366 this->SendPacket(p);
00367 }
00368
00369 p = new Packet(PACKET_SERVER_COMPANY_INFO);
00370
00371 p->Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00372 p->Send_bool (false);
00373
00374 this->SendPacket(p);
00375 return NETWORK_RECV_STATUS_OKAY;
00376 }
00377
00378 NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode error)
00379 {
00380 char str[100];
00381 Packet *p = new Packet(PACKET_SERVER_ERROR);
00382
00383 p->Send_uint8(error);
00384 this->SendPacket(p);
00385
00386 StringID strid = GetNetworkErrorMsg(error);
00387 GetString(str, strid, lastof(str));
00388
00389
00390 if (this->status > STATUS_AUTHORIZED) {
00391 NetworkClientSocket *new_cs;
00392 char client_name[NETWORK_CLIENT_NAME_LENGTH];
00393
00394 this->GetClientName(client_name, sizeof(client_name));
00395
00396 DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
00397
00398 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
00399
00400 FOR_ALL_CLIENT_SOCKETS(new_cs) {
00401 if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
00402
00403
00404 if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION) {
00405 error = NETWORK_ERROR_ILLEGAL_PACKET;
00406 }
00407 new_cs->SendErrorQuit(this->client_id, error);
00408 }
00409 }
00410
00411 NetworkAdminClientError(this->client_id, error);
00412 } else {
00413 DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", this->client_id, str);
00414 }
00415
00416
00417 return this->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
00418 }
00419
00420 NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck()
00421 {
00422 Packet *p = new Packet(PACKET_SERVER_CHECK_NEWGRFS);
00423 const GRFConfig *c;
00424 uint grf_count = 0;
00425
00426 for (c = _grfconfig; c != NULL; c = c->next) {
00427 if (!HasBit(c->flags, GCF_STATIC)) grf_count++;
00428 }
00429
00430 p->Send_uint8 (grf_count);
00431 for (c = _grfconfig; c != NULL; c = c->next) {
00432 if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
00433 }
00434
00435 this->SendPacket(p);
00436 return NETWORK_RECV_STATUS_OKAY;
00437 }
00438
00439 NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedGamePassword()
00440 {
00441
00442 if (this->status >= STATUS_AUTH_GAME) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
00443
00444 this->status = STATUS_AUTH_GAME;
00445
00446 Packet *p = new Packet(PACKET_SERVER_NEED_GAME_PASSWORD);
00447 this->SendPacket(p);
00448 return NETWORK_RECV_STATUS_OKAY;
00449 }
00450
00451 NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedCompanyPassword()
00452 {
00453
00454 if (this->status >= STATUS_AUTH_COMPANY) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
00455
00456 this->status = STATUS_AUTH_COMPANY;
00457
00458 Packet *p = new Packet(PACKET_SERVER_NEED_COMPANY_PASSWORD);
00459 p->Send_uint32(_settings_game.game_creation.generation_seed);
00460 p->Send_string(_settings_client.network.network_id);
00461 this->SendPacket(p);
00462 return NETWORK_RECV_STATUS_OKAY;
00463 }
00464
00465 NetworkRecvStatus ServerNetworkGameSocketHandler::SendWelcome()
00466 {
00467 Packet *p;
00468 NetworkClientSocket *new_cs;
00469
00470
00471 if (this->status >= STATUS_AUTHORIZED) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
00472
00473 this->status = STATUS_AUTHORIZED;
00474 _network_game_info.clients_on++;
00475
00476 p = new Packet(PACKET_SERVER_WELCOME);
00477 p->Send_uint32(this->client_id);
00478 p->Send_uint32(_settings_game.game_creation.generation_seed);
00479 p->Send_string(_settings_client.network.network_id);
00480 this->SendPacket(p);
00481
00482
00483 FOR_ALL_CLIENT_SOCKETS(new_cs) {
00484 if (new_cs != this && new_cs->status > STATUS_AUTHORIZED) {
00485 this->SendClientInfo(new_cs->GetInfo());
00486 }
00487 }
00488
00489 return this->SendClientInfo(NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER));
00490 }
00491
00492 NetworkRecvStatus ServerNetworkGameSocketHandler::SendWait()
00493 {
00494 int waiting = 0;
00495 NetworkClientSocket *new_cs;
00496 Packet *p;
00497
00498
00499 FOR_ALL_CLIENT_SOCKETS(new_cs) {
00500 if (new_cs->status == STATUS_MAP_WAIT) waiting++;
00501 }
00502
00503 p = new Packet(PACKET_SERVER_WAIT);
00504 p->Send_uint8(waiting);
00505 this->SendPacket(p);
00506 return NETWORK_RECV_STATUS_OKAY;
00507 }
00508
00509
00510 NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
00511 {
00512 static uint sent_packets;
00513
00514 if (this->status < STATUS_AUTHORIZED) {
00515
00516 return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
00517 }
00518
00519 if (this->status == STATUS_AUTHORIZED) {
00520 this->savegame = new PacketWriter(this);
00521
00522
00523 Packet *p = new Packet(PACKET_SERVER_MAP_BEGIN);
00524 p->Send_uint32(_frame_counter);
00525 this->SendPacket(p);
00526
00527 NetworkSyncCommandQueue(this);
00528 this->status = STATUS_MAP;
00529
00530 this->last_frame = _frame_counter;
00531 this->last_frame_server = _frame_counter;
00532
00533 sent_packets = 4;
00534
00535
00536 if (SaveWithFilter(this->savegame, true) != SL_OK) usererror("network savedump failed");
00537 }
00538
00539 if (this->status == STATUS_MAP) {
00540 if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical();
00541
00542 for (uint i = 0; i < sent_packets && this->savegame_packets != NULL; i++) {
00543 Packet *p = this->savegame_packets;
00544 bool last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE;
00545
00546
00547 this->savegame_packets = p->next;
00548 p->next = NULL;
00549 this->NetworkTCPSocketHandler::SendPacket(p);
00550
00551 if (last_packet) {
00552
00553
00554
00555
00556 this->status = STATUS_DONE_MAP;
00557
00558 NetworkClientSocket *new_cs;
00559 bool new_map_client = false;
00560
00561
00562 FOR_ALL_CLIENT_SOCKETS(new_cs) {
00563 if (new_cs->status == STATUS_MAP_WAIT) {
00564
00565 if (!new_map_client) {
00566
00567 new_cs->status = STATUS_AUTHORIZED;
00568 new_map_client = true;
00569 new_cs->SendMap();
00570 } else {
00571
00572 new_cs->SendWait();
00573 }
00574 }
00575 }
00576
00577
00578 break;
00579 }
00580 }
00581
00582 if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical();
00583
00584 switch (this->SendPackets()) {
00585 case SPS_CLOSED:
00586 return NETWORK_RECV_STATUS_CONN_LOST;
00587
00588 case SPS_ALL_SENT:
00589
00590 if (this->savegame_packets != NULL) sent_packets *= 2;
00591 break;
00592
00593 case SPS_PARTLY_SENT:
00594
00595 break;
00596
00597 case SPS_NONE_SENT:
00598
00599 if (sent_packets > 1) sent_packets /= 2;
00600 break;
00601 }
00602 }
00603 return NETWORK_RECV_STATUS_OKAY;
00604 }
00605
00606 NetworkRecvStatus ServerNetworkGameSocketHandler::SendJoin(ClientID client_id)
00607 {
00608 Packet *p = new Packet(PACKET_SERVER_JOIN);
00609
00610 p->Send_uint32(client_id);
00611
00612 this->SendPacket(p);
00613 return NETWORK_RECV_STATUS_OKAY;
00614 }
00615
00616
00617 NetworkRecvStatus ServerNetworkGameSocketHandler::SendFrame()
00618 {
00619 Packet *p = new Packet(PACKET_SERVER_FRAME);
00620 p->Send_uint32(_frame_counter);
00621 p->Send_uint32(_frame_counter_max);
00622 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
00623 p->Send_uint32(_sync_seed_1);
00624 #ifdef NETWORK_SEND_DOUBLE_SEED
00625 p->Send_uint32(_sync_seed_2);
00626 #endif
00627 #endif
00628
00629
00630 if (this->last_token == 0) {
00631 this->last_token = InteractiveRandomRange(UINT8_MAX - 1) + 1;
00632 p->Send_uint8(this->last_token);
00633 }
00634
00635 this->SendPacket(p);
00636 return NETWORK_RECV_STATUS_OKAY;
00637 }
00638
00639 NetworkRecvStatus ServerNetworkGameSocketHandler::SendSync()
00640 {
00641 Packet *p = new Packet(PACKET_SERVER_SYNC);
00642 p->Send_uint32(_frame_counter);
00643 p->Send_uint32(_sync_seed_1);
00644
00645 #ifdef NETWORK_SEND_DOUBLE_SEED
00646 p->Send_uint32(_sync_seed_2);
00647 #endif
00648 this->SendPacket(p);
00649 return NETWORK_RECV_STATUS_OKAY;
00650 }
00651
00652 NetworkRecvStatus ServerNetworkGameSocketHandler::SendCommand(const CommandPacket *cp)
00653 {
00654 Packet *p = new Packet(PACKET_SERVER_COMMAND);
00655
00656 this->NetworkGameSocketHandler::SendCommand(p, cp);
00657 p->Send_uint32(cp->frame);
00658 p->Send_bool (cp->my_cmd);
00659
00660 this->SendPacket(p);
00661 return NETWORK_RECV_STATUS_OKAY;
00662 }
00663
00664 NetworkRecvStatus ServerNetworkGameSocketHandler::SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, int64 data)
00665 {
00666 Packet *p = new Packet(PACKET_SERVER_CHAT);
00667
00668 p->Send_uint8 (action);
00669 p->Send_uint32(client_id);
00670 p->Send_bool (self_send);
00671 p->Send_string(msg);
00672 p->Send_uint64(data);
00673
00674 this->SendPacket(p);
00675 return NETWORK_RECV_STATUS_OKAY;
00676 }
00677
00678 NetworkRecvStatus ServerNetworkGameSocketHandler::SendErrorQuit(ClientID client_id, NetworkErrorCode errorno)
00679 {
00680 Packet *p = new Packet(PACKET_SERVER_ERROR_QUIT);
00681
00682 p->Send_uint32(client_id);
00683 p->Send_uint8 (errorno);
00684
00685 this->SendPacket(p);
00686 return NETWORK_RECV_STATUS_OKAY;
00687 }
00688
00689 NetworkRecvStatus ServerNetworkGameSocketHandler::SendQuit(ClientID client_id)
00690 {
00691 Packet *p = new Packet(PACKET_SERVER_QUIT);
00692
00693 p->Send_uint32(client_id);
00694
00695 this->SendPacket(p);
00696 return NETWORK_RECV_STATUS_OKAY;
00697 }
00698
00699 NetworkRecvStatus ServerNetworkGameSocketHandler::SendShutdown()
00700 {
00701 Packet *p = new Packet(PACKET_SERVER_SHUTDOWN);
00702 this->SendPacket(p);
00703 return NETWORK_RECV_STATUS_OKAY;
00704 }
00705
00706 NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGame()
00707 {
00708 Packet *p = new Packet(PACKET_SERVER_NEWGAME);
00709 this->SendPacket(p);
00710 return NETWORK_RECV_STATUS_OKAY;
00711 }
00712
00713 NetworkRecvStatus ServerNetworkGameSocketHandler::SendRConResult(uint16 colour, const char *command)
00714 {
00715 Packet *p = new Packet(PACKET_SERVER_RCON);
00716
00717 p->Send_uint16(colour);
00718 p->Send_string(command);
00719 this->SendPacket(p);
00720 return NETWORK_RECV_STATUS_OKAY;
00721 }
00722
00723 NetworkRecvStatus ServerNetworkGameSocketHandler::SendMove(ClientID client_id, CompanyID company_id)
00724 {
00725 Packet *p = new Packet(PACKET_SERVER_MOVE);
00726
00727 p->Send_uint32(client_id);
00728 p->Send_uint8(company_id);
00729 this->SendPacket(p);
00730 return NETWORK_RECV_STATUS_OKAY;
00731 }
00732
00733 NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyUpdate()
00734 {
00735 Packet *p = new Packet(PACKET_SERVER_COMPANY_UPDATE);
00736
00737 p->Send_uint16(_network_company_passworded);
00738 this->SendPacket(p);
00739 return NETWORK_RECV_STATUS_OKAY;
00740 }
00741
00742 NetworkRecvStatus ServerNetworkGameSocketHandler::SendConfigUpdate()
00743 {
00744 Packet *p = new Packet(PACKET_SERVER_CONFIG_UPDATE);
00745
00746 p->Send_uint8(_settings_client.network.max_companies);
00747 p->Send_uint8(_settings_client.network.max_spectators);
00748 this->SendPacket(p);
00749 return NETWORK_RECV_STATUS_OKAY;
00750 }
00751
00752
00753
00754
00755
00756
00757 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMPANY_INFO)
00758 {
00759 return this->SendCompanyInfo();
00760 }
00761
00762 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_NEWGRFS_CHECKED)
00763 {
00764 if (this->status != STATUS_NEWGRFS_CHECK) {
00765
00766 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00767 }
00768
00769 NetworkClientInfo *ci = this->GetInfo();
00770
00771
00772 if (!StrEmpty(_settings_client.network.server_password)) {
00773 return this->SendNeedGamePassword();
00774 }
00775
00776 if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
00777 return this->SendNeedCompanyPassword();
00778 }
00779
00780 return this->SendWelcome();
00781 }
00782
00783 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_JOIN)
00784 {
00785 if (this->status != STATUS_INACTIVE) {
00786
00787 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00788 }
00789
00790 char name[NETWORK_CLIENT_NAME_LENGTH];
00791 NetworkClientInfo *ci;
00792 CompanyID playas;
00793 NetworkLanguage client_lang;
00794 char client_revision[NETWORK_REVISION_LENGTH];
00795
00796 p->Recv_string(client_revision, sizeof(client_revision));
00797
00798
00799 if (!IsNetworkCompatibleVersion(client_revision)) {
00800
00801 return this->SendError(NETWORK_ERROR_WRONG_REVISION);
00802 }
00803
00804 p->Recv_string(name, sizeof(name));
00805 playas = (Owner)p->Recv_uint8();
00806 client_lang = (NetworkLanguage)p->Recv_uint8();
00807
00808 if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
00809
00810
00811 switch (playas) {
00812 case COMPANY_NEW_COMPANY:
00813 if (Company::GetNumItems() >= _settings_client.network.max_companies) {
00814 return this->SendError(NETWORK_ERROR_FULL);
00815 }
00816 break;
00817 case COMPANY_SPECTATOR:
00818 if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
00819 return this->SendError(NETWORK_ERROR_FULL);
00820 }
00821 break;
00822 default:
00823 if (!Company::IsValidHumanID(playas)) {
00824 return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
00825 }
00826 break;
00827 }
00828
00829
00830 if (StrEmpty(name)) strecpy(name, "Player", lastof(name));
00831
00832 if (!NetworkFindName(name)) {
00833
00834 return this->SendError(NETWORK_ERROR_NAME_IN_USE);
00835 }
00836
00837 ci = this->GetInfo();
00838
00839 strecpy(ci->client_name, name, lastof(ci->client_name));
00840 ci->client_playas = playas;
00841 ci->client_lang = client_lang;
00842 DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, ci->index);
00843
00844
00845 if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0;
00846
00847 this->status = STATUS_NEWGRFS_CHECK;
00848
00849 if (_grfconfig == NULL) {
00850
00851 return this->NetworkPacketReceive_PACKET_CLIENT_NEWGRFS_CHECKED_command(NULL);
00852 }
00853
00854 return this->SendNewGRFCheck();
00855 }
00856
00857 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_GAME_PASSWORD)
00858 {
00859 if (this->status != STATUS_AUTH_GAME) {
00860 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00861 }
00862
00863 char password[NETWORK_PASSWORD_LENGTH];
00864 p->Recv_string(password, sizeof(password));
00865
00866
00867 if (!StrEmpty(_settings_client.network.server_password) &&
00868 strcmp(password, _settings_client.network.server_password) != 0) {
00869
00870 return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
00871 }
00872
00873 const NetworkClientInfo *ci = this->GetInfo();
00874 if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
00875 return this->SendNeedCompanyPassword();
00876 }
00877
00878
00879 return this->SendWelcome();
00880 }
00881
00882 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMPANY_PASSWORD)
00883 {
00884 if (this->status != STATUS_AUTH_COMPANY) {
00885 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00886 }
00887
00888 char password[NETWORK_PASSWORD_LENGTH];
00889 p->Recv_string(password, sizeof(password));
00890
00891
00892
00893
00894 CompanyID playas = this->GetInfo()->client_playas;
00895 if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) &&
00896 strcmp(password, _network_company_states[playas].password) != 0) {
00897
00898 return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
00899 }
00900
00901 return this->SendWelcome();
00902 }
00903
00904 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_GETMAP)
00905 {
00906 NetworkClientSocket *new_cs;
00907
00908
00909
00910
00911
00912
00913
00914
00915 if (HasBit(_openttd_newgrf_version, 19)) {
00916 if (_openttd_newgrf_version != p->Recv_uint32()) {
00917
00918
00919 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00920 }
00921 } else if (p->size != 3) {
00922
00923
00924 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00925 }
00926
00927
00928
00929 if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) {
00930 return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
00931 }
00932
00933
00934 FOR_ALL_CLIENT_SOCKETS(new_cs) {
00935 if (new_cs->status == STATUS_MAP) {
00936
00937 this->status = STATUS_MAP_WAIT;
00938 return this->SendWait();
00939 }
00940 }
00941
00942
00943 return this->SendMap();
00944 }
00945
00946 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_MAP_OK)
00947 {
00948
00949 if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) {
00950 char client_name[NETWORK_CLIENT_NAME_LENGTH];
00951 NetworkClientSocket *new_cs;
00952
00953 this->GetClientName(client_name, sizeof(client_name));
00954
00955 NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, NULL, this->client_id);
00956
00957
00958
00959 this->status = STATUS_PRE_ACTIVE;
00960 NetworkHandleCommandQueue(this);
00961 this->SendFrame();
00962 this->SendSync();
00963
00964
00965
00966 this->last_frame = _frame_counter;
00967 this->last_frame_server = _frame_counter;
00968
00969 FOR_ALL_CLIENT_SOCKETS(new_cs) {
00970 if (new_cs->status > STATUS_AUTHORIZED) {
00971 new_cs->SendClientInfo(this->GetInfo());
00972 new_cs->SendJoin(this->client_id);
00973 }
00974 }
00975
00976 NetworkAdminClientInfo(this->GetInfo(), true);
00977
00978
00979 this->SendConfigUpdate();
00980
00981
00982 return this->SendCompanyUpdate();
00983 }
00984
00985
00986 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00987 }
00988
00993 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMMAND)
00994 {
00995
00996
00997 if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
00998 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
00999 }
01000
01001 if (this->incoming_queue.Count() >= _settings_client.network.max_commands_in_queue) {
01002 return this->SendError(NETWORK_ERROR_TOO_MANY_COMMANDS);
01003 }
01004
01005 CommandPacket cp;
01006 const char *err = this->ReceiveCommand(p, &cp);
01007
01008 if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
01009
01010 NetworkClientInfo *ci = this->GetInfo();
01011
01012 if (err != NULL) {
01013 IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, GetClientIP(ci));
01014 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01015 }
01016
01017
01018 if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) {
01019 IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci));
01020 return this->SendError(NETWORK_ERROR_KICKED);
01021 }
01022
01023 if ((GetCommandFlags(cp.cmd) & CMD_SPECTATOR) == 0 && !Company::IsValidID(cp.company) && ci->client_id != CLIENT_ID_SERVER) {
01024 IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci));
01025 return this->SendError(NETWORK_ERROR_KICKED);
01026 }
01027
01033 if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
01034 IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...",
01035 ci->client_playas + 1, GetClientIP(ci), cp.company + 1);
01036 return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH);
01037 }
01038
01039 if (cp.cmd == CMD_COMPANY_CTRL) {
01040 if (cp.p1 != 0 || cp.company != COMPANY_SPECTATOR) {
01041 return this->SendError(NETWORK_ERROR_CHEATER);
01042 }
01043
01044
01045 if (Company::GetNumItems() >= _settings_client.network.max_companies) {
01046 NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_CLIENT, ci->client_id, "cannot create new company, server full", CLIENT_ID_SERVER);
01047 return NETWORK_RECV_STATUS_OKAY;
01048 }
01049 }
01050
01051 if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = this->client_id;
01052
01053 this->incoming_queue.Append(&cp);
01054 return NETWORK_RECV_STATUS_OKAY;
01055 }
01056
01057 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_ERROR)
01058 {
01059
01060
01061 NetworkClientSocket *new_cs;
01062 char str[100];
01063 char client_name[NETWORK_CLIENT_NAME_LENGTH];
01064 NetworkErrorCode errorno = (NetworkErrorCode)p->Recv_uint8();
01065
01066
01067 if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
01068 return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01069 }
01070
01071 this->GetClientName(client_name, sizeof(client_name));
01072
01073 StringID strid = GetNetworkErrorMsg(errorno);
01074 GetString(str, strid, lastof(str));
01075
01076 DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
01077
01078 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
01079
01080 FOR_ALL_CLIENT_SOCKETS(new_cs) {
01081 if (new_cs->status > STATUS_AUTHORIZED) {
01082 new_cs->SendErrorQuit(this->client_id, errorno);
01083 }
01084 }
01085
01086 NetworkAdminClientError(this->client_id, errorno);
01087
01088 return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01089 }
01090
01091 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_QUIT)
01092 {
01093
01094
01095 NetworkClientSocket *new_cs;
01096 char client_name[NETWORK_CLIENT_NAME_LENGTH];
01097
01098
01099 if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
01100 return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01101 }
01102
01103 this->GetClientName(client_name, sizeof(client_name));
01104
01105 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
01106
01107 FOR_ALL_CLIENT_SOCKETS(new_cs) {
01108 if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
01109 new_cs->SendQuit(this->client_id);
01110 }
01111 }
01112
01113 NetworkAdminClientQuit(this->client_id);
01114
01115 return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
01116 }
01117
01118 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_ACK)
01119 {
01120 if (this->status < STATUS_AUTHORIZED) {
01121
01122 return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
01123 }
01124
01125 uint32 frame = p->Recv_uint32();
01126
01127
01128 if (this->status == STATUS_PRE_ACTIVE) {
01129
01130 if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY;
01131
01132
01133 this->status = STATUS_ACTIVE;
01134 this->last_token_frame = _frame_counter;
01135
01136
01137 IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
01138 }
01139
01140
01141 uint8 token = p->Recv_uint8();
01142 if (token == this->last_token) {
01143
01144
01145
01146
01147
01148
01149
01150
01151 this->last_token_frame = _frame_counter;
01152
01153 this->last_token = 0;
01154 }
01155
01156
01157 this->last_frame = frame;
01158
01159 this->last_frame_server = _frame_counter;
01160 return NETWORK_RECV_STATUS_OKAY;
01161 }
01162
01163
01164
01165 void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin)
01166 {
01167 NetworkClientSocket *cs;
01168 const NetworkClientInfo *ci, *ci_own, *ci_to;
01169
01170 switch (desttype) {
01171 case DESTTYPE_CLIENT:
01172
01173 if ((ClientID)dest == CLIENT_ID_SERVER) {
01174 ci = NetworkFindClientInfoFromClientID(from_id);
01175
01176 if (ci != NULL) {
01177 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
01178
01179 if (_settings_client.network.server_admin_chat) {
01180 NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
01181 }
01182 }
01183 } else {
01184
01185 FOR_ALL_CLIENT_SOCKETS(cs) {
01186 if (cs->client_id == (ClientID)dest) {
01187 cs->SendChat(action, from_id, false, msg, data);
01188 break;
01189 }
01190 }
01191 }
01192
01193
01194 if (from_id != (ClientID)dest) {
01195 if (from_id == CLIENT_ID_SERVER) {
01196 ci = NetworkFindClientInfoFromClientID(from_id);
01197 ci_to = NetworkFindClientInfoFromClientID((ClientID)dest);
01198 if (ci != NULL && ci_to != NULL) {
01199 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), true, ci_to->client_name, msg, data);
01200 }
01201 } else {
01202 FOR_ALL_CLIENT_SOCKETS(cs) {
01203 if (cs->client_id == from_id) {
01204 cs->SendChat(action, (ClientID)dest, true, msg, data);
01205 break;
01206 }
01207 }
01208 }
01209 }
01210 break;
01211 case DESTTYPE_TEAM: {
01212
01213 bool show_local = true;
01214
01215 ci_to = NULL;
01216 FOR_ALL_CLIENT_SOCKETS(cs) {
01217 ci = cs->GetInfo();
01218 if (ci->client_playas == (CompanyID)dest) {
01219 cs->SendChat(action, from_id, false, msg, data);
01220 if (cs->client_id == from_id) show_local = false;
01221 ci_to = ci;
01222 }
01223 }
01224
01225
01226 if (_local_company == (CompanyID)dest && _settings_client.network.server_admin_chat) {
01227 NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
01228 }
01229
01230 ci = NetworkFindClientInfoFromClientID(from_id);
01231 ci_own = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER);
01232 if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
01233 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
01234 if (from_id == CLIENT_ID_SERVER) show_local = false;
01235 ci_to = ci_own;
01236 }
01237
01238
01239 if (ci_to == NULL) break;
01240
01241
01242 if (ci != NULL && show_local) {
01243 if (from_id == CLIENT_ID_SERVER) {
01244 char name[NETWORK_NAME_LENGTH];
01245 StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
01246 SetDParam(0, ci_to->client_playas);
01247 GetString(name, str, lastof(name));
01248 NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data);
01249 } else {
01250 FOR_ALL_CLIENT_SOCKETS(cs) {
01251 if (cs->client_id == from_id) {
01252 cs->SendChat(action, ci_to->client_id, true, msg, data);
01253 }
01254 }
01255 }
01256 }
01257 break;
01258 }
01259 default:
01260 DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
01261
01262 case DESTTYPE_BROADCAST:
01263 FOR_ALL_CLIENT_SOCKETS(cs) {
01264 cs->SendChat(action, from_id, false, msg, data);
01265 }
01266
01267 NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
01268
01269 ci = NetworkFindClientInfoFromClientID(from_id);
01270 if (ci != NULL) {
01271 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
01272 }
01273 break;
01274 }
01275 }
01276
01277 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_CHAT)
01278 {
01279 if (this->status < STATUS_AUTHORIZED) {
01280
01281 return this->SendError(NETWORK_ERROR_NOT_AUTHORIZED);
01282 }
01283
01284 NetworkAction action = (NetworkAction)p->Recv_uint8();
01285 DestType desttype = (DestType)p->Recv_uint8();
01286 int dest = p->Recv_uint32();
01287 char msg[NETWORK_CHAT_LENGTH];
01288
01289 p->Recv_string(msg, NETWORK_CHAT_LENGTH);
01290 int64 data = p->Recv_uint64();
01291
01292 NetworkClientInfo *ci = this->GetInfo();
01293 switch (action) {
01294 case NETWORK_ACTION_GIVE_MONEY:
01295 if (!Company::IsValidID(ci->client_playas)) break;
01296
01297 case NETWORK_ACTION_CHAT:
01298 case NETWORK_ACTION_CHAT_CLIENT:
01299 case NETWORK_ACTION_CHAT_COMPANY:
01300 NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
01301 break;
01302 default:
01303 IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, GetClientIP(ci));
01304 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01305 }
01306 return NETWORK_RECV_STATUS_OKAY;
01307 }
01308
01309 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_SET_PASSWORD)
01310 {
01311 if (this->status != STATUS_ACTIVE) {
01312
01313 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01314 }
01315
01316 char password[NETWORK_PASSWORD_LENGTH];
01317 const NetworkClientInfo *ci;
01318
01319 p->Recv_string(password, sizeof(password));
01320 ci = this->GetInfo();
01321
01322 NetworkServerSetCompanyPassword(ci->client_playas, password);
01323 return NETWORK_RECV_STATUS_OKAY;
01324 }
01325
01326 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_SET_NAME)
01327 {
01328 if (this->status != STATUS_ACTIVE) {
01329
01330 return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01331 }
01332
01333 char client_name[NETWORK_CLIENT_NAME_LENGTH];
01334 NetworkClientInfo *ci;
01335
01336 p->Recv_string(client_name, sizeof(client_name));
01337 ci = this->GetInfo();
01338
01339 if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
01340
01341 if (ci != NULL) {
01342
01343 if (NetworkFindName(client_name)) {
01344 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
01345 strecpy(ci->client_name, client_name, lastof(ci->client_name));
01346 NetworkUpdateClientInfo(ci->client_id);
01347 }
01348 }
01349 return NETWORK_RECV_STATUS_OKAY;
01350 }
01351
01352 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_RCON)
01353 {
01354 if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01355
01356 char pass[NETWORK_PASSWORD_LENGTH];
01357 char command[NETWORK_RCONCOMMAND_LENGTH];
01358
01359 if (StrEmpty(_settings_client.network.rcon_password)) return NETWORK_RECV_STATUS_OKAY;
01360
01361 p->Recv_string(pass, sizeof(pass));
01362 p->Recv_string(command, sizeof(command));
01363
01364 if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
01365 DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
01366 return NETWORK_RECV_STATUS_OKAY;
01367 }
01368
01369 DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command);
01370
01371 _redirect_console_to_client = this->client_id;
01372 IConsoleCmdExec(command);
01373 _redirect_console_to_client = INVALID_CLIENT_ID;
01374 return NETWORK_RECV_STATUS_OKAY;
01375 }
01376
01377 DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_MOVE)
01378 {
01379 if (this->status != STATUS_ACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
01380
01381 CompanyID company_id = (Owner)p->Recv_uint8();
01382
01383
01384 if (company_id != COMPANY_SPECTATOR && !Company::IsValidHumanID(company_id)) return NETWORK_RECV_STATUS_OKAY;
01385
01386
01387 if (company_id != COMPANY_SPECTATOR && !StrEmpty(_network_company_states[company_id].password)) {
01388
01389 char password[NETWORK_PASSWORD_LENGTH];
01390 p->Recv_string(password, sizeof(password));
01391
01392
01393 if (strcmp(password, _network_company_states[company_id].password) != 0) {
01394 DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1);
01395 return NETWORK_RECV_STATUS_OKAY;
01396 }
01397 }
01398
01399
01400 NetworkServerDoMove(this->client_id, company_id);
01401 return NETWORK_RECV_STATUS_OKAY;
01402 }
01403
01411 void NetworkSocketHandler::SendCompanyInformation(Packet *p, const Company *c, const NetworkCompanyStats *stats, uint max_len)
01412 {
01413
01414 char company_name[NETWORK_COMPANY_NAME_LENGTH];
01415 SetDParam(0, c->index);
01416
01417 assert(max_len <= lengthof(company_name));
01418 GetString(company_name, STR_COMPANY_NAME, company_name + max_len - 1);
01419
01420
01421 Money income = 0;
01422 if (_cur_year - 1 == c->inaugurated_year) {
01423
01424 for (uint i = 0; i < lengthof(c->yearly_expenses[2]); i++) {
01425 income -= c->yearly_expenses[2][i];
01426 }
01427 } else {
01428 for (uint i = 0; i < lengthof(c->yearly_expenses[1]); i++) {
01429 income -= c->yearly_expenses[1][i];
01430 }
01431 }
01432
01433
01434 p->Send_uint8 (c->index);
01435 p->Send_string(company_name);
01436 p->Send_uint32(c->inaugurated_year);
01437 p->Send_uint64(c->old_economy[0].company_value);
01438 p->Send_uint64(c->money);
01439 p->Send_uint64(income);
01440 p->Send_uint16(c->old_economy[0].performance_history);
01441
01442
01443 p->Send_bool (!StrEmpty(_network_company_states[c->index].password));
01444
01445 for (uint i = 0; i < NETWORK_VEH_END; i++) {
01446 p->Send_uint16(stats->num_vehicle[i]);
01447 }
01448
01449 for (uint i = 0; i < NETWORK_VEH_END; i++) {
01450 p->Send_uint16(stats->num_station[i]);
01451 }
01452
01453 p->Send_bool(c->is_ai);
01454 }
01455
01460 void NetworkPopulateCompanyStats(NetworkCompanyStats *stats)
01461 {
01462 const Vehicle *v;
01463 const Station *s;
01464
01465 memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
01466
01467
01468 FOR_ALL_VEHICLES(v) {
01469 if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
01470 byte type = 0;
01471 switch (v->type) {
01472 case VEH_TRAIN: type = NETWORK_VEH_TRAIN; break;
01473 case VEH_ROAD: type = RoadVehicle::From(v)->IsBus() ? NETWORK_VEH_BUS : NETWORK_VEH_LORRY; break;
01474 case VEH_AIRCRAFT: type = NETWORK_VEH_PLANE; break;
01475 case VEH_SHIP: type = NETWORK_VEH_SHIP; break;
01476 default: continue;
01477 }
01478 stats[v->owner].num_vehicle[type]++;
01479 }
01480
01481
01482 FOR_ALL_STATIONS(s) {
01483 if (Company::IsValidID(s->owner)) {
01484 NetworkCompanyStats *npi = &stats[s->owner];
01485
01486 if (s->facilities & FACIL_TRAIN) npi->num_station[NETWORK_VEH_TRAIN]++;
01487 if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[NETWORK_VEH_LORRY]++;
01488 if (s->facilities & FACIL_BUS_STOP) npi->num_station[NETWORK_VEH_BUS]++;
01489 if (s->facilities & FACIL_AIRPORT) npi->num_station[NETWORK_VEH_PLANE]++;
01490 if (s->facilities & FACIL_DOCK) npi->num_station[NETWORK_VEH_SHIP]++;
01491 }
01492 }
01493 }
01494
01495
01496 void NetworkUpdateClientInfo(ClientID client_id)
01497 {
01498 NetworkClientSocket *cs;
01499 NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id);
01500
01501 if (ci == NULL) return;
01502
01503 DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, client_id);
01504
01505 FOR_ALL_CLIENT_SOCKETS(cs) {
01506 cs->SendClientInfo(ci);
01507 }
01508
01509 NetworkAdminClientUpdate(ci);
01510 }
01511
01512
01513 static void NetworkCheckRestartMap()
01514 {
01515 if (_settings_client.network.restart_game_year != 0 && _cur_year >= _settings_client.network.restart_game_year) {
01516 DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
01517
01518 StartNewGameWithoutGUI(GENERATE_NEW_SEED);
01519 }
01520 }
01521
01522
01523
01524
01525
01526
01527 static void NetworkAutoCleanCompanies()
01528 {
01529 const NetworkClientInfo *ci;
01530 const Company *c;
01531 bool clients_in_company[MAX_COMPANIES];
01532 int vehicles_in_company[MAX_COMPANIES];
01533
01534 if (!_settings_client.network.autoclean_companies) return;
01535
01536 memset(clients_in_company, 0, sizeof(clients_in_company));
01537
01538
01539 FOR_ALL_CLIENT_INFOS(ci) {
01540 if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
01541 }
01542
01543 if (!_network_dedicated) {
01544 ci = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER);
01545 if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
01546 }
01547
01548 if (_settings_client.network.autoclean_novehicles != 0) {
01549 memset(vehicles_in_company, 0, sizeof(vehicles_in_company));
01550
01551 const Vehicle *v;
01552 FOR_ALL_VEHICLES(v) {
01553 if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle()) continue;
01554 vehicles_in_company[v->owner]++;
01555 }
01556 }
01557
01558
01559 FOR_ALL_COMPANIES(c) {
01560
01561 if (c->is_ai) continue;
01562
01563 if (!clients_in_company[c->index]) {
01564
01565 _network_company_states[c->index].months_empty++;
01566
01567
01568 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)) {
01569
01570 DoCommandP(0, 2 | c->index << 16, 0, CMD_COMPANY_CTRL);
01571 NetworkAdminCompanyRemove(c->index, ADMIN_CRR_AUTOCLEAN);
01572 IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1);
01573 }
01574
01575 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)) {
01576
01577 _network_company_states[c->index].password[0] = '\0';
01578 IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1);
01579 _network_company_states[c->index].months_empty = 0;
01580 NetworkServerUpdateCompanyPassworded(c->index, false);
01581 }
01582
01583 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) {
01584
01585 DoCommandP(0, 2 | c->index << 16, 0, CMD_COMPANY_CTRL);
01586 NetworkAdminCompanyRemove(c->index, ADMIN_CRR_AUTOCLEAN);
01587 IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);
01588 }
01589 } else {
01590
01591 _network_company_states[c->index].months_empty = 0;
01592 }
01593 }
01594 }
01595
01596
01597
01598 bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
01599 {
01600 bool found_name = false;
01601 uint number = 0;
01602 char original_name[NETWORK_CLIENT_NAME_LENGTH];
01603
01604
01605 ttd_strlcpy(original_name, new_name, NETWORK_CLIENT_NAME_LENGTH);
01606
01607 while (!found_name) {
01608 const NetworkClientInfo *ci;
01609
01610 found_name = true;
01611 FOR_ALL_CLIENT_INFOS(ci) {
01612 if (strcmp(ci->client_name, new_name) == 0) {
01613
01614 found_name = false;
01615 break;
01616 }
01617 }
01618
01619 ci = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER);
01620 if (ci != NULL) {
01621 if (strcmp(ci->client_name, new_name) == 0) found_name = false;
01622 }
01623
01624 if (!found_name) {
01625
01626
01627
01628 if (number++ > MAX_CLIENTS) break;
01629 snprintf(new_name, NETWORK_CLIENT_NAME_LENGTH, "%s #%d", original_name, number);
01630 }
01631 }
01632
01633 return found_name;
01634 }
01635
01642 bool NetworkServerChangeClientName(ClientID client_id, const char *new_name)
01643 {
01644 NetworkClientInfo *ci;
01645
01646 FOR_ALL_CLIENT_INFOS(ci) {
01647 if (strcmp(ci->client_name, new_name) == 0) return false;
01648 }
01649
01650 ci = NetworkFindClientInfoFromClientID(client_id);
01651 if (ci == NULL) return false;
01652
01653 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, true, ci->client_name, new_name);
01654
01655 strecpy(ci->client_name, new_name, lastof(ci->client_name));
01656
01657 NetworkUpdateClientInfo(client_id);
01658 return true;
01659 }
01660
01667 void NetworkServerSetCompanyPassword(CompanyID company_id, const char *password, bool already_hashed)
01668 {
01669 if (!Company::IsValidHumanID(company_id)) return;
01670
01671 if (!already_hashed) {
01672 password = GenerateCompanyPasswordHash(password, _settings_client.network.network_id, _settings_game.game_creation.generation_seed);
01673 }
01674
01675 strecpy(_network_company_states[company_id].password, password, lastof(_network_company_states[company_id].password));
01676 NetworkServerUpdateCompanyPassworded(company_id, !StrEmpty(_network_company_states[company_id].password));
01677 }
01678
01679
01680 static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
01681 {
01682 CommandPacket *cp;
01683 while ((cp = cs->outgoing_queue.Pop()) != NULL) {
01684 cs->SendCommand(cp);
01685 free(cp);
01686 }
01687 }
01688
01689
01690 void NetworkServer_Tick(bool send_frame)
01691 {
01692 NetworkClientSocket *cs;
01693 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01694 bool send_sync = false;
01695 #endif
01696
01697 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01698 if (_frame_counter >= _last_sync_frame + _settings_client.network.sync_freq) {
01699 _last_sync_frame = _frame_counter;
01700 send_sync = true;
01701 }
01702 #endif
01703
01704
01705
01706 FOR_ALL_CLIENT_SOCKETS(cs) {
01707
01708
01709 cs->receive_limit = min(cs->receive_limit + _settings_client.network.bytes_per_frame,
01710 _settings_client.network.bytes_per_frame_burst);
01711
01712
01713 if (cs->status == NetworkClientSocket::STATUS_ACTIVE) {
01714
01715 uint lag = NetworkCalculateLag(cs) / DAY_TICKS;
01716 if (lag > 0) {
01717 if (lag > 3) {
01718
01719
01720 IConsolePrintF(CC_ERROR, cs->last_packet + 3 * DAY_TICKS * MILLISECONDS_PER_TICK > _realtime_tick ?
01721
01722 "Client #%d is dropped because the client's game state is more than 4 game-days behind" :
01723
01724 "Client #%d is dropped because the client did not respond for more than 4 game-days",
01725 cs->client_id);
01726 cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
01727 continue;
01728 }
01729
01730
01731
01732
01733
01734
01735 if (cs->lag_test == 0 && cs->last_packet + DAY_TICKS * MILLISECONDS_PER_TICK > _realtime_tick) {
01736 IConsolePrintF(CC_WARNING,"[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
01737 cs->lag_test = 1;
01738 }
01739 } else {
01740 cs->lag_test = 0;
01741 }
01742 if (cs->last_frame_server - cs->last_token_frame >= 5 * DAY_TICKS) {
01743
01744 IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id);
01745 cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
01746 continue;
01747 }
01748 } else if (cs->status == NetworkClientSocket::STATUS_PRE_ACTIVE) {
01749 uint lag = NetworkCalculateLag(cs);
01750 if (lag > _settings_client.network.max_join_time) {
01751 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);
01752 cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
01753 continue;
01754 }
01755 } else if (cs->status == NetworkClientSocket::STATUS_INACTIVE) {
01756 uint lag = NetworkCalculateLag(cs);
01757 if (lag > 4 * DAY_TICKS) {
01758 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);
01759 cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
01760 continue;
01761 }
01762 }
01763
01764 if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) {
01765
01766 NetworkHandleCommandQueue(cs);
01767
01768
01769 if (send_frame) cs->SendFrame();
01770
01771 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
01772
01773 if (send_sync) cs->SendSync();
01774 #endif
01775 }
01776 }
01777
01778
01779 NetworkUDPAdvertise();
01780 }
01781
01783 void NetworkServerYearlyLoop()
01784 {
01785 NetworkCheckRestartMap();
01786 NetworkAdminUpdate(ADMIN_FREQUENCY_ANUALLY);
01787 }
01788
01790 void NetworkServerMonthlyLoop()
01791 {
01792 NetworkAutoCleanCompanies();
01793 NetworkAdminUpdate(ADMIN_FREQUENCY_MONTHLY);
01794 if ((_cur_month % 3) == 0) NetworkAdminUpdate(ADMIN_FREQUENCY_QUARTERLY);
01795 }
01796
01798 void NetworkServerDailyLoop()
01799 {
01800 NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY);
01801 if ((_date % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY);
01802 }
01803
01804 const char *GetClientIP(NetworkClientInfo *ci)
01805 {
01806 return ci->client_address.GetHostname();
01807 }
01808
01809 void NetworkServerShowStatusToConsole()
01810 {
01811 static const char * const stat_str[] = {
01812 "inactive",
01813 "checking NewGRFs",
01814 "authorizing (server password)",
01815 "authorizing (company password)",
01816 "authorized",
01817 "waiting",
01818 "loading map",
01819 "map done",
01820 "ready",
01821 "active"
01822 };
01823 assert_compile(lengthof(stat_str) == NetworkClientSocket::STATUS_END);
01824
01825 NetworkClientSocket *cs;
01826 FOR_ALL_CLIENT_SOCKETS(cs) {
01827 uint lag = NetworkCalculateLag(cs);
01828 NetworkClientInfo *ci = cs->GetInfo();
01829 const char *status;
01830
01831 status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
01832 IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s",
01833 cs->client_id, ci->client_name, status, lag,
01834 ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
01835 GetClientIP(ci));
01836 }
01837 }
01838
01842 void NetworkServerSendConfigUpdate()
01843 {
01844 NetworkClientSocket *cs;
01845
01846 FOR_ALL_CLIENT_SOCKETS(cs) {
01847 if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendConfigUpdate();
01848 }
01849 }
01850
01851 void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
01852 {
01853 if (NetworkCompanyIsPassworded(company_id) == passworded) return;
01854
01855 SB(_network_company_passworded, company_id, 1, !!passworded);
01856 SetWindowClassesDirty(WC_COMPANY);
01857
01858 NetworkClientSocket *cs;
01859 FOR_ALL_CLIENT_SOCKETS(cs) {
01860 if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) cs->SendCompanyUpdate();
01861 }
01862
01863 NetworkAdminCompanyUpdate(Company::GetIfValid(company_id));
01864 }
01865
01872 void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
01873 {
01874
01875 if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
01876
01877 NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id);
01878
01879
01880 if (ci->client_playas == company_id) return;
01881
01882 ci->client_playas = company_id;
01883
01884 if (client_id == CLIENT_ID_SERVER) {
01885 SetLocalCompany(company_id);
01886 } else {
01887 NetworkClientSocket *cs = NetworkFindClientStateFromClientID(client_id);
01888
01889 if (cs->status < NetworkClientSocket::STATUS_AUTHORIZED) return;
01890 cs->SendMove(client_id, company_id);
01891 }
01892
01893
01894 NetworkUpdateClientInfo(client_id);
01895
01896 NetworkAction action = (company_id == COMPANY_SPECTATOR) ? NETWORK_ACTION_COMPANY_SPECTATOR : NETWORK_ACTION_COMPANY_JOIN;
01897 NetworkServerSendChat(action, DESTTYPE_BROADCAST, 0, "", client_id, company_id + 1);
01898 }
01899
01900 void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string)
01901 {
01902 NetworkFindClientStateFromClientID(client_id)->SendRConResult(colour_code, string);
01903 }
01904
01905 static void NetworkServerSendError(ClientID client_id, NetworkErrorCode error)
01906 {
01907 NetworkFindClientStateFromClientID(client_id)->SendError(error);
01908 }
01909
01910 void NetworkServerKickClient(ClientID client_id)
01911 {
01912 if (client_id == CLIENT_ID_SERVER) return;
01913 NetworkServerSendError(client_id, NETWORK_ERROR_KICKED);
01914 }
01915
01916 uint NetworkServerKickOrBanIP(const char *ip, bool ban)
01917 {
01918
01919 if (ban) *_network_ban_list.Append() = strdup(ip);
01920
01921 uint n = 0;
01922
01923
01924 NetworkClientInfo *ci;
01925 FOR_ALL_CLIENT_INFOS(ci) {
01926 if (ci->client_id == CLIENT_ID_SERVER) continue;
01927 if (ci->client_address.IsInNetmask(const_cast<char *>(ip))) {
01928 NetworkServerKickClient(ci->client_id);
01929 n++;
01930 }
01931 }
01932
01933 return n;
01934 }
01935
01936 bool NetworkCompanyHasClients(CompanyID company)
01937 {
01938 const NetworkClientInfo *ci;
01939 FOR_ALL_CLIENT_INFOS(ci) {
01940 if (ci->client_playas == company) return true;
01941 }
01942 return false;
01943 }
01944
01945
01951 void ServerNetworkGameSocketHandler::GetClientName(char *client_name, size_t size) const
01952 {
01953 const NetworkClientInfo *ci = this->GetInfo();
01954
01955 if (StrEmpty(ci->client_name)) {
01956 snprintf(client_name, size, "Client #%4d", this->client_id);
01957 } else {
01958 ttd_strlcpy(client_name, ci->client_name, size);
01959 }
01960 }
01961
01962 #endif