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