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