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