00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifdef ENABLE_NETWORK
00013
00014 #include "../stdafx.h"
00015 #include "network_gui.h"
00016 #include "../saveload/saveload.h"
00017 #include "../saveload/saveload_filter.h"
00018 #include "../command_func.h"
00019 #include "../console_func.h"
00020 #include "../strings_func.h"
00021 #include "../window_func.h"
00022 #include "../company_func.h"
00023 #include "../company_base.h"
00024 #include "../company_gui.h"
00025 #include "../core/random_func.hpp"
00026 #include "../date_func.h"
00027 #include "../gfx_func.h"
00028 #include "../error.h"
00029 #include "../rev.h"
00030 #include "network.h"
00031 #include "network_base.h"
00032 #include "network_client.h"
00033 #include "../core/backup_type.hpp"
00034
00035 #include "table/strings.h"
00036
00037
00038
00039
00041 struct PacketReader : LoadFilter {
00042 static const size_t CHUNK = 32 * 1024;
00043
00044 AutoFreeSmallVector<byte *, 16> blocks;
00045 byte *buf;
00046 byte *bufe;
00047 byte **block;
00048 size_t written_bytes;
00049 size_t read_bytes;
00050
00052 PacketReader() : LoadFilter(NULL), buf(NULL), bufe(NULL), block(NULL), written_bytes(0), read_bytes(0)
00053 {
00054 }
00055
00060 void AddPacket(const Packet *p)
00061 {
00062 assert(this->read_bytes == 0);
00063
00064 size_t in_packet = p->size - p->pos;
00065 size_t to_write = min((size_t)(this->bufe - this->buf), in_packet);
00066 const byte *pbuf = p->buffer + p->pos;
00067
00068 this->written_bytes += in_packet;
00069 if (to_write != 0) {
00070 memcpy(this->buf, pbuf, to_write);
00071 this->buf += to_write;
00072 }
00073
00074
00075 if (to_write == in_packet) return;
00076
00077
00078 pbuf += to_write;
00079 to_write = in_packet - to_write;
00080 this->buf = *this->blocks.Append() = CallocT<byte>(CHUNK);
00081 this->bufe = this->buf + CHUNK;
00082
00083 memcpy(this->buf, pbuf, to_write);
00084 this->buf += to_write;
00085 }
00086
00087 size_t Read(byte *rbuf, size_t size)
00088 {
00089
00090 size_t ret_size = size = min(this->written_bytes - this->read_bytes, size);
00091 this->read_bytes += ret_size;
00092 const byte *rbufe = rbuf + ret_size;
00093
00094 while (rbuf != rbufe) {
00095 if (this->buf == this->bufe) {
00096 this->buf = *this->block++;
00097 this->bufe = this->buf + CHUNK;
00098 }
00099
00100 size_t to_write = min(this->bufe - this->buf, rbufe - rbuf);
00101 memcpy(rbuf, this->buf, to_write);
00102 rbuf += to_write;
00103 this->buf += to_write;
00104 }
00105
00106 return ret_size;
00107 }
00108
00109 void Reset()
00110 {
00111 this->read_bytes = 0;
00112
00113 this->block = this->blocks.Begin();
00114 this->buf = *this->block++;
00115 this->bufe = this->buf + CHUNK;
00116 }
00117 };
00118
00119
00124 ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s) : NetworkGameSocketHandler(s), savegame(NULL), status(STATUS_INACTIVE)
00125 {
00126 assert(ClientNetworkGameSocketHandler::my_client == NULL);
00127 ClientNetworkGameSocketHandler::my_client = this;
00128 }
00129
00131 ClientNetworkGameSocketHandler::~ClientNetworkGameSocketHandler()
00132 {
00133 assert(ClientNetworkGameSocketHandler::my_client == this);
00134 ClientNetworkGameSocketHandler::my_client = NULL;
00135
00136 delete this->savegame;
00137 }
00138
00139 NetworkRecvStatus ClientNetworkGameSocketHandler::CloseConnection(NetworkRecvStatus status)
00140 {
00141 assert(status != NETWORK_RECV_STATUS_OKAY);
00142
00143
00144
00145
00146
00147
00148
00149 if (this->sock == INVALID_SOCKET) return status;
00150
00151 DEBUG(net, 1, "Closed client connection %d", this->client_id);
00152
00153 this->SendPackets(true);
00154
00155
00156
00157
00158
00159 CSleep(3 * MILLISECONDS_PER_TICK);
00160
00161 delete this->GetInfo();
00162 delete this;
00163
00164 return status;
00165 }
00166
00171 void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res)
00172 {
00173
00174
00175 NetworkErrorCode errorno;
00176
00177
00178 if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
00179 this->NetworkSocketHandler::CloseConnection();
00180 this->CloseConnection(res);
00181 _networking = false;
00182
00183 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00184 return;
00185 }
00186
00187 switch (res) {
00188 case NETWORK_RECV_STATUS_DESYNC: errorno = NETWORK_ERROR_DESYNC; break;
00189 case NETWORK_RECV_STATUS_SAVEGAME: errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
00190 case NETWORK_RECV_STATUS_NEWGRF_MISMATCH: errorno = NETWORK_ERROR_NEWGRF_MISMATCH; break;
00191 default: errorno = NETWORK_ERROR_GENERAL; break;
00192 }
00193
00194
00195 if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL &&
00196 res != NETWORK_RECV_STATUS_SERVER_BANNED) {
00197 SendError(errorno);
00198 }
00199
00200 _switch_mode = SM_MENU;
00201 this->CloseConnection(res);
00202 _networking = false;
00203 }
00204
00205
00211 bool ClientNetworkGameSocketHandler::Receive()
00212 {
00213 if (my_client->CanSendReceive()) {
00214 NetworkRecvStatus res = my_client->ReceivePackets();
00215 if (res != NETWORK_RECV_STATUS_OKAY) {
00216
00217
00218 my_client->ClientError(res);
00219 return false;
00220 }
00221 }
00222 return _networking;
00223 }
00224
00226 void ClientNetworkGameSocketHandler::Send()
00227 {
00228 my_client->SendPackets();
00229 my_client->CheckConnection();
00230 }
00231
00236 bool ClientNetworkGameSocketHandler::GameLoop()
00237 {
00238 _frame_counter++;
00239
00240 NetworkExecuteLocalCommandQueue();
00241
00242 extern void StateGameLoop();
00243 StateGameLoop();
00244
00245
00246 if (_sync_frame != 0) {
00247 if (_sync_frame == _frame_counter) {
00248 #ifdef NETWORK_SEND_DOUBLE_SEED
00249 if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1]) {
00250 #else
00251 if (_sync_seed_1 != _random.state[0]) {
00252 #endif
00253 NetworkError(STR_NETWORK_ERROR_DESYNC);
00254 DEBUG(desync, 1, "sync_err: %08x; %02x", _date, _date_fract);
00255 DEBUG(net, 0, "Sync error detected!");
00256 my_client->ClientError(NETWORK_RECV_STATUS_DESYNC);
00257 return false;
00258 }
00259
00260
00261
00262
00263 if (_network_first_time) {
00264 _network_first_time = false;
00265 SendAck();
00266 }
00267
00268 _sync_frame = 0;
00269 } else if (_sync_frame < _frame_counter) {
00270 DEBUG(net, 1, "Missed frame for sync-test (%d / %d)", _sync_frame, _frame_counter);
00271 _sync_frame = 0;
00272 }
00273 }
00274
00275 return true;
00276 }
00277
00278
00280 ClientNetworkGameSocketHandler * ClientNetworkGameSocketHandler::my_client = NULL;
00281
00283 static uint32 last_ack_frame;
00284
00286 static uint32 _password_game_seed;
00288 static char _password_server_id[NETWORK_SERVER_ID_LENGTH];
00289
00291 static uint8 _network_server_max_companies;
00293 static uint8 _network_server_max_spectators;
00294
00296 CompanyID _network_join_as;
00297
00299 const char *_network_join_server_password = NULL;
00301 const char *_network_join_company_password = NULL;
00302
00304 assert_compile(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1);
00305
00306
00307
00308
00309
00310
00312 NetworkRecvStatus ClientNetworkGameSocketHandler::SendCompanyInformationQuery()
00313 {
00314 my_client->status = STATUS_COMPANY_INFO;
00315 _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
00316 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00317
00318 Packet *p = new Packet(PACKET_CLIENT_COMPANY_INFO);
00319 my_client->SendPacket(p);
00320 return NETWORK_RECV_STATUS_OKAY;
00321 }
00322
00324 NetworkRecvStatus ClientNetworkGameSocketHandler::SendJoin()
00325 {
00326 my_client->status = STATUS_JOIN;
00327 _network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
00328 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00329
00330 Packet *p = new Packet(PACKET_CLIENT_JOIN);
00331 p->Send_string(_openttd_revision);
00332 p->Send_uint32(_openttd_newgrf_version);
00333 p->Send_string(_settings_client.network.client_name);
00334 p->Send_uint8 (_network_join_as);
00335 p->Send_uint8 (NETLANG_ANY);
00336 my_client->SendPacket(p);
00337 return NETWORK_RECV_STATUS_OKAY;
00338 }
00339
00341 NetworkRecvStatus ClientNetworkGameSocketHandler::SendNewGRFsOk()
00342 {
00343 Packet *p = new Packet(PACKET_CLIENT_NEWGRFS_CHECKED);
00344 my_client->SendPacket(p);
00345 return NETWORK_RECV_STATUS_OKAY;
00346 }
00347
00352 NetworkRecvStatus ClientNetworkGameSocketHandler::SendGamePassword(const char *password)
00353 {
00354 Packet *p = new Packet(PACKET_CLIENT_GAME_PASSWORD);
00355 p->Send_string(password);
00356 my_client->SendPacket(p);
00357 return NETWORK_RECV_STATUS_OKAY;
00358 }
00359
00364 NetworkRecvStatus ClientNetworkGameSocketHandler::SendCompanyPassword(const char *password)
00365 {
00366 Packet *p = new Packet(PACKET_CLIENT_COMPANY_PASSWORD);
00367 p->Send_string(GenerateCompanyPasswordHash(password, _password_server_id, _password_game_seed));
00368 my_client->SendPacket(p);
00369 return NETWORK_RECV_STATUS_OKAY;
00370 }
00371
00373 NetworkRecvStatus ClientNetworkGameSocketHandler::SendGetMap()
00374 {
00375 my_client->status = STATUS_MAP_WAIT;
00376
00377 Packet *p = new Packet(PACKET_CLIENT_GETMAP);
00378 my_client->SendPacket(p);
00379 return NETWORK_RECV_STATUS_OKAY;
00380 }
00381
00383 NetworkRecvStatus ClientNetworkGameSocketHandler::SendMapOk()
00384 {
00385 my_client->status = STATUS_ACTIVE;
00386
00387 Packet *p = new Packet(PACKET_CLIENT_MAP_OK);
00388 my_client->SendPacket(p);
00389 return NETWORK_RECV_STATUS_OKAY;
00390 }
00391
00393 NetworkRecvStatus ClientNetworkGameSocketHandler::SendAck()
00394 {
00395 Packet *p = new Packet(PACKET_CLIENT_ACK);
00396
00397 p->Send_uint32(_frame_counter);
00398 p->Send_uint8 (my_client->token);
00399 my_client->SendPacket(p);
00400 return NETWORK_RECV_STATUS_OKAY;
00401 }
00402
00407 NetworkRecvStatus ClientNetworkGameSocketHandler::SendCommand(const CommandPacket *cp)
00408 {
00409 Packet *p = new Packet(PACKET_CLIENT_COMMAND);
00410 my_client->NetworkGameSocketHandler::SendCommand(p, cp);
00411
00412 my_client->SendPacket(p);
00413 return NETWORK_RECV_STATUS_OKAY;
00414 }
00415
00417 NetworkRecvStatus ClientNetworkGameSocketHandler::SendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data)
00418 {
00419 Packet *p = new Packet(PACKET_CLIENT_CHAT);
00420
00421 p->Send_uint8 (action);
00422 p->Send_uint8 (type);
00423 p->Send_uint32(dest);
00424 p->Send_string(msg);
00425 p->Send_uint64(data);
00426
00427 my_client->SendPacket(p);
00428 return NETWORK_RECV_STATUS_OKAY;
00429 }
00430
00432 NetworkRecvStatus ClientNetworkGameSocketHandler::SendError(NetworkErrorCode errorno)
00433 {
00434 Packet *p = new Packet(PACKET_CLIENT_ERROR);
00435
00436 p->Send_uint8(errorno);
00437 my_client->SendPacket(p);
00438 return NETWORK_RECV_STATUS_OKAY;
00439 }
00440
00445 NetworkRecvStatus ClientNetworkGameSocketHandler::SendSetPassword(const char *password)
00446 {
00447 Packet *p = new Packet(PACKET_CLIENT_SET_PASSWORD);
00448
00449 p->Send_string(GenerateCompanyPasswordHash(password, _password_server_id, _password_game_seed));
00450 my_client->SendPacket(p);
00451 return NETWORK_RECV_STATUS_OKAY;
00452 }
00453
00458 NetworkRecvStatus ClientNetworkGameSocketHandler::SendSetName(const char *name)
00459 {
00460 Packet *p = new Packet(PACKET_CLIENT_SET_NAME);
00461
00462 p->Send_string(name);
00463 my_client->SendPacket(p);
00464 return NETWORK_RECV_STATUS_OKAY;
00465 }
00466
00470 NetworkRecvStatus ClientNetworkGameSocketHandler::SendQuit()
00471 {
00472 Packet *p = new Packet(PACKET_CLIENT_QUIT);
00473
00474 my_client->SendPacket(p);
00475 return NETWORK_RECV_STATUS_OKAY;
00476 }
00477
00483 NetworkRecvStatus ClientNetworkGameSocketHandler::SendRCon(const char *pass, const char *command)
00484 {
00485 Packet *p = new Packet(PACKET_CLIENT_RCON);
00486 p->Send_string(pass);
00487 p->Send_string(command);
00488 my_client->SendPacket(p);
00489 return NETWORK_RECV_STATUS_OKAY;
00490 }
00491
00497 NetworkRecvStatus ClientNetworkGameSocketHandler::SendMove(CompanyID company, const char *password)
00498 {
00499 Packet *p = new Packet(PACKET_CLIENT_MOVE);
00500 p->Send_uint8(company);
00501 p->Send_string(GenerateCompanyPasswordHash(password, _password_server_id, _password_game_seed));
00502 my_client->SendPacket(p);
00503 return NETWORK_RECV_STATUS_OKAY;
00504 }
00505
00510 bool ClientNetworkGameSocketHandler::IsConnected()
00511 {
00512 return my_client != NULL && my_client->status == STATUS_ACTIVE;
00513 }
00514
00515
00516
00517
00518
00519
00520
00521 extern bool SafeLoad(const char *filename, int mode, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = NULL);
00522
00523 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FULL(Packet *p)
00524 {
00525
00526 ShowErrorMessage(STR_NETWORK_ERROR_SERVER_FULL, INVALID_STRING_ID, WL_CRITICAL);
00527 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00528
00529 return NETWORK_RECV_STATUS_SERVER_FULL;
00530 }
00531
00532 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet *p)
00533 {
00534
00535 ShowErrorMessage(STR_NETWORK_ERROR_SERVER_BANNED, INVALID_STRING_ID, WL_CRITICAL);
00536 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00537
00538 return NETWORK_RECV_STATUS_SERVER_BANNED;
00539 }
00540
00541 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Packet *p)
00542 {
00543 if (this->status != STATUS_COMPANY_INFO) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00544
00545 byte company_info_version = p->Recv_uint8();
00546
00547 if (!this->HasClientQuit() && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
00548
00549 if (!p->Recv_bool()) return NETWORK_RECV_STATUS_CLOSE_QUERY;
00550
00551 CompanyID current = (Owner)p->Recv_uint8();
00552 if (current >= MAX_COMPANIES) return NETWORK_RECV_STATUS_CLOSE_QUERY;
00553
00554 NetworkCompanyInfo *company_info = GetLobbyCompanyInfo(current);
00555 if (company_info == NULL) return NETWORK_RECV_STATUS_CLOSE_QUERY;
00556
00557 p->Recv_string(company_info->company_name, sizeof(company_info->company_name));
00558 company_info->inaugurated_year = p->Recv_uint32();
00559 company_info->company_value = p->Recv_uint64();
00560 company_info->money = p->Recv_uint64();
00561 company_info->income = p->Recv_uint64();
00562 company_info->performance = p->Recv_uint16();
00563 company_info->use_password = p->Recv_bool();
00564 for (uint i = 0; i < NETWORK_VEH_END; i++) {
00565 company_info->num_vehicle[i] = p->Recv_uint16();
00566 }
00567 for (uint i = 0; i < NETWORK_VEH_END; i++) {
00568 company_info->num_station[i] = p->Recv_uint16();
00569 }
00570 company_info->ai = p->Recv_bool();
00571
00572 p->Recv_string(company_info->clients, sizeof(company_info->clients));
00573
00574 SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);
00575
00576 return NETWORK_RECV_STATUS_OKAY;
00577 }
00578
00579 return NETWORK_RECV_STATUS_CLOSE_QUERY;
00580 }
00581
00582
00583
00584
00585 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet *p)
00586 {
00587 NetworkClientInfo *ci;
00588 ClientID client_id = (ClientID)p->Recv_uint32();
00589 CompanyID playas = (CompanyID)p->Recv_uint8();
00590 char name[NETWORK_NAME_LENGTH];
00591
00592 p->Recv_string(name, sizeof(name));
00593
00594 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00595 if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
00596
00597 ci = NetworkClientInfo::GetByClientID(client_id);
00598 if (ci != NULL) {
00599 if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
00600
00601 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, name);
00602 } else if (playas != ci->client_playas) {
00603
00604
00605 }
00606
00607
00608
00609 if (client_id == _network_own_client_id) SetLocalCompany(!Company::IsValidID(playas) ? COMPANY_SPECTATOR : playas);
00610
00611 ci->client_playas = playas;
00612 strecpy(ci->client_name, name, lastof(ci->client_name));
00613
00614 SetWindowDirty(WC_CLIENT_LIST, 0);
00615
00616 return NETWORK_RECV_STATUS_OKAY;
00617 }
00618
00619
00620
00621
00622
00623
00624 if (!NetworkClientInfo::CanAllocateItem()) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00625
00626
00627 ci = new NetworkClientInfo(client_id);
00628 ci->client_playas = playas;
00629 if (client_id == _network_own_client_id) this->SetInfo(ci);
00630
00631 strecpy(ci->client_name, name, lastof(ci->client_name));
00632
00633 SetWindowDirty(WC_CLIENT_LIST, 0);
00634
00635 return NETWORK_RECV_STATUS_OKAY;
00636 }
00637
00638 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p)
00639 {
00640 static const StringID network_error_strings[] = {
00641 STR_NETWORK_ERROR_LOSTCONNECTION,
00642 STR_NETWORK_ERROR_LOSTCONNECTION,
00643 STR_NETWORK_ERROR_LOSTCONNECTION,
00644 STR_NETWORK_ERROR_LOSTCONNECTION,
00645 STR_NETWORK_ERROR_LOSTCONNECTION,
00646 STR_NETWORK_ERROR_LOSTCONNECTION,
00647 STR_NETWORK_ERROR_SERVER_ERROR,
00648 STR_NETWORK_ERROR_SERVER_ERROR,
00649 STR_NETWORK_ERROR_WRONG_REVISION,
00650 STR_NETWORK_ERROR_LOSTCONNECTION,
00651 STR_NETWORK_ERROR_WRONG_PASSWORD,
00652 STR_NETWORK_ERROR_SERVER_ERROR,
00653 STR_NETWORK_ERROR_KICKED,
00654 STR_NETWORK_ERROR_CHEATER,
00655 STR_NETWORK_ERROR_SERVER_FULL,
00656 STR_NETWORK_ERROR_TOO_MANY_COMMANDS,
00657 STR_NETWORK_ERROR_TIMEOUT_PASSWORD,
00658 STR_NETWORK_ERROR_TIMEOUT_COMPUTER,
00659 STR_NETWORK_ERROR_TIMEOUT_MAP,
00660 STR_NETWORK_ERROR_TIMEOUT_JOIN,
00661 };
00662 assert_compile(lengthof(network_error_strings) == NETWORK_ERROR_END);
00663
00664 NetworkErrorCode error = (NetworkErrorCode)p->Recv_uint8();
00665
00666 StringID err = STR_NETWORK_ERROR_LOSTCONNECTION;
00667 if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error];
00668
00669 ShowErrorMessage(err, INVALID_STRING_ID, WL_CRITICAL);
00670
00671 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00672
00673 return NETWORK_RECV_STATUS_SERVER_ERROR;
00674 }
00675
00676 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(Packet *p)
00677 {
00678 if (this->status != STATUS_JOIN) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00679
00680 uint grf_count = p->Recv_uint8();
00681 NetworkRecvStatus ret = NETWORK_RECV_STATUS_OKAY;
00682
00683
00684 for (; grf_count > 0; grf_count--) {
00685 GRFIdentifier c;
00686 this->ReceiveGRFIdentifier(p, &c);
00687
00688
00689 const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum);
00690 if (f == NULL) {
00691
00692 char buf[sizeof(c.md5sum) * 2 + 1];
00693 md5sumToString(buf, lastof(buf), c.md5sum);
00694 DEBUG(grf, 0, "NewGRF %08X not found; checksum %s", BSWAP32(c.grfid), buf);
00695 ret = NETWORK_RECV_STATUS_NEWGRF_MISMATCH;
00696 }
00697 }
00698
00699 if (ret == NETWORK_RECV_STATUS_OKAY) {
00700
00701 return SendNewGRFsOk();
00702 }
00703
00704
00705 ShowErrorMessage(STR_NETWORK_ERROR_NEWGRF_MISMATCH, INVALID_STRING_ID, WL_CRITICAL);
00706 return ret;
00707 }
00708
00709 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_GAME_PASSWORD(Packet *p)
00710 {
00711 if (this->status < STATUS_JOIN || this->status >= STATUS_AUTH_GAME) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00712 this->status = STATUS_AUTH_GAME;
00713
00714 const char *password = _network_join_server_password;
00715 if (!StrEmpty(password)) {
00716 return SendGamePassword(password);
00717 }
00718
00719 ShowNetworkNeedPassword(NETWORK_GAME_PASSWORD);
00720
00721 return NETWORK_RECV_STATUS_OKAY;
00722 }
00723
00724 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEED_COMPANY_PASSWORD(Packet *p)
00725 {
00726 if (this->status < STATUS_JOIN || this->status >= STATUS_AUTH_COMPANY) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00727 this->status = STATUS_AUTH_COMPANY;
00728
00729 _password_game_seed = p->Recv_uint32();
00730 p->Recv_string(_password_server_id, sizeof(_password_server_id));
00731 if (this->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00732
00733 const char *password = _network_join_company_password;
00734 if (!StrEmpty(password)) {
00735 return SendCompanyPassword(password);
00736 }
00737
00738 ShowNetworkNeedPassword(NETWORK_COMPANY_PASSWORD);
00739
00740 return NETWORK_RECV_STATUS_OKAY;
00741 }
00742
00743 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_WELCOME(Packet *p)
00744 {
00745 if (this->status < STATUS_JOIN || this->status >= STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00746 this->status = STATUS_AUTHORIZED;
00747
00748 _network_own_client_id = (ClientID)p->Recv_uint32();
00749
00750
00751 _password_game_seed = p->Recv_uint32();
00752 p->Recv_string(_password_server_id, sizeof(_password_server_id));
00753
00754
00755 return SendGetMap();
00756 }
00757
00758 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_WAIT(Packet *p)
00759 {
00760
00761 if (this->status != STATUS_MAP_WAIT) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00762
00763
00764 _network_join_status = NETWORK_JOIN_STATUS_WAITING;
00765 _network_join_waiting = p->Recv_uint8();
00766 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00767
00768 return NETWORK_RECV_STATUS_OKAY;
00769 }
00770
00771 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_BEGIN(Packet *p)
00772 {
00773 if (this->status < STATUS_AUTHORIZED || this->status >= STATUS_MAP) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00774 this->status = STATUS_MAP;
00775
00776 if (this->savegame != NULL) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00777
00778 this->savegame = new PacketReader();
00779
00780 _frame_counter = _frame_counter_server = _frame_counter_max = p->Recv_uint32();
00781
00782 _network_join_bytes = 0;
00783 _network_join_bytes_total = 0;
00784
00785 _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING;
00786 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00787
00788 return NETWORK_RECV_STATUS_OKAY;
00789 }
00790
00791 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_SIZE(Packet *p)
00792 {
00793 if (this->status != STATUS_MAP) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00794 if (this->savegame == NULL) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00795
00796 _network_join_bytes_total = p->Recv_uint32();
00797 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00798
00799 return NETWORK_RECV_STATUS_OKAY;
00800 }
00801
00802 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DATA(Packet *p)
00803 {
00804 if (this->status != STATUS_MAP) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00805 if (this->savegame == NULL) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00806
00807
00808 this->savegame->AddPacket(p);
00809
00810 _network_join_bytes = (uint32)this->savegame->written_bytes;
00811 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00812
00813 return NETWORK_RECV_STATUS_OKAY;
00814 }
00815
00816 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet *p)
00817 {
00818 if (this->status != STATUS_MAP) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00819 if (this->savegame == NULL) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00820
00821 _network_join_status = NETWORK_JOIN_STATUS_PROCESSING;
00822 SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00823
00824
00825
00826
00827
00828
00829
00830
00831 LoadFilter *lf = this->savegame;
00832 this->savegame = NULL;
00833 lf->Reset();
00834
00835
00836 ClearErrorMessages();
00837 bool load_success = SafeLoad(NULL, SL_LOAD, GM_NORMAL, NO_DIRECTORY, lf);
00838
00839
00840 this->last_packet = _realtime_tick;
00841
00842 if (!load_success) {
00843 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
00844 ShowErrorMessage(STR_NETWORK_ERROR_SAVEGAMEERROR, INVALID_STRING_ID, WL_CRITICAL);
00845 return NETWORK_RECV_STATUS_SAVEGAME;
00846 }
00847
00848
00849
00850
00851 SendMapOk();
00852
00853
00854
00855 if (_network_join_as == COMPANY_NEW_COMPANY || !Company::IsValidID(_network_join_as)) {
00856 SetLocalCompany(COMPANY_SPECTATOR);
00857
00858 if (_network_join_as != COMPANY_SPECTATOR) {
00859
00860
00861 _network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
00862 ShowJoinStatusWindow();
00863 NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL, NULL, NULL, _local_company);
00864 }
00865 } else {
00866
00867 SetLocalCompany(_network_join_as);
00868 }
00869
00870 return NETWORK_RECV_STATUS_OKAY;
00871 }
00872
00873 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FRAME(Packet *p)
00874 {
00875 if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00876
00877 _frame_counter_server = p->Recv_uint32();
00878 _frame_counter_max = p->Recv_uint32();
00879 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
00880
00881
00882 if (p->pos + 1 < p->size) {
00883 _sync_frame = _frame_counter_server;
00884 _sync_seed_1 = p->Recv_uint32();
00885 #ifdef NETWORK_SEND_DOUBLE_SEED
00886 _sync_seed_2 = p->Recv_uint32();
00887 #endif
00888 }
00889 #endif
00890
00891 if (p->pos != p->size) this->token = p->Recv_uint8();
00892
00893 DEBUG(net, 5, "Received FRAME %d", _frame_counter_server);
00894
00895
00896
00897 if (!_network_first_time && last_ack_frame < _frame_counter) {
00898 last_ack_frame = _frame_counter + DAY_TICKS;
00899 DEBUG(net, 4, "Sent ACK at %d", _frame_counter);
00900 SendAck();
00901 }
00902
00903 return NETWORK_RECV_STATUS_OKAY;
00904 }
00905
00906 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_SYNC(Packet *p)
00907 {
00908 if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00909
00910 _sync_frame = p->Recv_uint32();
00911 _sync_seed_1 = p->Recv_uint32();
00912 #ifdef NETWORK_SEND_DOUBLE_SEED
00913 _sync_seed_2 = p->Recv_uint32();
00914 #endif
00915
00916 return NETWORK_RECV_STATUS_OKAY;
00917 }
00918
00919 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMMAND(Packet *p)
00920 {
00921 if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00922
00923 CommandPacket cp;
00924 const char *err = this->ReceiveCommand(p, &cp);
00925 cp.frame = p->Recv_uint32();
00926 cp.my_cmd = p->Recv_bool();
00927
00928 if (err != NULL) {
00929 IConsolePrintF(CC_ERROR, "WARNING: %s from server, dropping...", err);
00930 return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00931 }
00932
00933 this->incoming_queue.Append(&cp);
00934
00935 return NETWORK_RECV_STATUS_OKAY;
00936 }
00937
00938 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHAT(Packet *p)
00939 {
00940 if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00941
00942 char name[NETWORK_NAME_LENGTH], msg[NETWORK_CHAT_LENGTH];
00943 const NetworkClientInfo *ci = NULL, *ci_to;
00944
00945 NetworkAction action = (NetworkAction)p->Recv_uint8();
00946 ClientID client_id = (ClientID)p->Recv_uint32();
00947 bool self_send = p->Recv_bool();
00948 p->Recv_string(msg, NETWORK_CHAT_LENGTH);
00949 int64 data = p->Recv_uint64();
00950
00951 ci_to = NetworkClientInfo::GetByClientID(client_id);
00952 if (ci_to == NULL) return NETWORK_RECV_STATUS_OKAY;
00953
00954
00955 if (self_send) {
00956 switch (action) {
00957 case NETWORK_ACTION_CHAT_CLIENT:
00958
00959 snprintf(name, sizeof(name), "%s", ci_to->client_name);
00960 ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
00961 break;
00962
00963
00964 case NETWORK_ACTION_GIVE_MONEY:
00965 if (!Company::IsValidID(ci_to->client_playas)) return NETWORK_RECV_STATUS_OKAY;
00966
00967 case NETWORK_ACTION_CHAT_COMPANY: {
00968 StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
00969 SetDParam(0, ci_to->client_playas);
00970
00971 GetString(name, str, lastof(name));
00972 ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
00973 break;
00974 }
00975
00976 default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00977 }
00978 } else {
00979
00980 snprintf(name, sizeof(name), "%s", ci_to->client_name);
00981 ci = ci_to;
00982 }
00983
00984 if (ci != NULL) {
00985 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), self_send, name, msg, data);
00986 }
00987 return NETWORK_RECV_STATUS_OKAY;
00988 }
00989
00990 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR_QUIT(Packet *p)
00991 {
00992 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00993
00994 ClientID client_id = (ClientID)p->Recv_uint32();
00995
00996 NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
00997 if (ci != NULL) {
00998 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, NULL, GetNetworkErrorMsg((NetworkErrorCode)p->Recv_uint8()));
00999 delete ci;
01000 }
01001
01002 SetWindowDirty(WC_CLIENT_LIST, 0);
01003
01004 return NETWORK_RECV_STATUS_OKAY;
01005 }
01006
01007 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_QUIT(Packet *p)
01008 {
01009 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
01010
01011 ClientID client_id = (ClientID)p->Recv_uint32();
01012
01013 NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
01014 if (ci != NULL) {
01015 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
01016 delete ci;
01017 } else {
01018 DEBUG(net, 0, "Unknown client (%d) is leaving the game", client_id);
01019 }
01020
01021 SetWindowDirty(WC_CLIENT_LIST, 0);
01022
01023
01024 return NETWORK_RECV_STATUS_OKAY;
01025 }
01026
01027 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_JOIN(Packet *p)
01028 {
01029 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
01030
01031 ClientID client_id = (ClientID)p->Recv_uint32();
01032
01033 NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
01034 if (ci != NULL) {
01035 NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name);
01036 }
01037
01038 SetWindowDirty(WC_CLIENT_LIST, 0);
01039
01040 return NETWORK_RECV_STATUS_OKAY;
01041 }
01042
01043 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_SHUTDOWN(Packet *p)
01044 {
01045
01046
01047 if (this->status >= STATUS_JOIN) {
01048 ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_SHUTDOWN, INVALID_STRING_ID, WL_CRITICAL);
01049 }
01050
01051 return NETWORK_RECV_STATUS_SERVER_ERROR;
01052 }
01053
01054 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEWGAME(Packet *p)
01055 {
01056
01057
01058 if (this->status >= STATUS_JOIN) {
01059
01060
01061
01062 _network_reconnect = _network_own_client_id % 16;
01063 ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_REBOOT, INVALID_STRING_ID, WL_CRITICAL);
01064 }
01065
01066 return NETWORK_RECV_STATUS_SERVER_ERROR;
01067 }
01068
01069 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_RCON(Packet *p)
01070 {
01071 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
01072
01073 TextColour colour_code = (TextColour)p->Recv_uint16();
01074 if (!IsValidConsoleColour(colour_code)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
01075
01076 char rcon_out[NETWORK_RCONCOMMAND_LENGTH];
01077 p->Recv_string(rcon_out, sizeof(rcon_out));
01078
01079 IConsolePrint(colour_code, rcon_out);
01080
01081 return NETWORK_RECV_STATUS_OKAY;
01082 }
01083
01084 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MOVE(Packet *p)
01085 {
01086 if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
01087
01088
01089 ClientID client_id = (ClientID)p->Recv_uint32();
01090 CompanyID company_id = (CompanyID)p->Recv_uint8();
01091
01092 if (client_id == 0) {
01093
01094 DEBUG(net, 0, "[move] received invalid client index = 0");
01095 return NETWORK_RECV_STATUS_MALFORMED_PACKET;
01096 }
01097
01098 const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
01099
01100 if (ci == NULL) return NETWORK_RECV_STATUS_OKAY;
01101
01102
01103 if (!Company::IsValidID(company_id)) company_id = COMPANY_SPECTATOR;
01104
01105 if (client_id == _network_own_client_id) {
01106 SetLocalCompany(company_id);
01107 }
01108
01109 return NETWORK_RECV_STATUS_OKAY;
01110 }
01111
01112 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CONFIG_UPDATE(Packet *p)
01113 {
01114 if (this->status < STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
01115
01116 _network_server_max_companies = p->Recv_uint8();
01117 _network_server_max_spectators = p->Recv_uint8();
01118
01119 return NETWORK_RECV_STATUS_OKAY;
01120 }
01121
01122 NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_UPDATE(Packet *p)
01123 {
01124 if (this->status < STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
01125
01126 _network_company_passworded = p->Recv_uint16();
01127 SetWindowClassesDirty(WC_COMPANY);
01128
01129 return NETWORK_RECV_STATUS_OKAY;
01130 }
01131
01135 void ClientNetworkGameSocketHandler::CheckConnection()
01136 {
01137
01138 if (this->status < STATUS_AUTHORIZED) return;
01139
01140
01141 if (_realtime_tick < this->last_packet) this->last_packet = _realtime_tick;
01142
01143
01144
01145 uint lag = (_realtime_tick - this->last_packet) / 1000;
01146 if (lag < 5) return;
01147
01148
01149
01150 if (lag > 20) {
01151 this->NetworkGameSocketHandler::CloseConnection();
01152 ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL);
01153 return;
01154 }
01155
01156
01157 static uint last_lag = 0;
01158 if (last_lag == lag) return;
01159
01160 last_lag = lag;
01161 SetDParam(0, lag);
01162 ShowErrorMessage(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION, STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION, WL_INFO);
01163 }
01164
01165
01167 void NetworkClient_Connected()
01168 {
01169
01170 _frame_counter = 0;
01171 _frame_counter_server = 0;
01172 last_ack_frame = 0;
01173
01174 MyClient::SendJoin();
01175 }
01176
01182 void NetworkClientSendRcon(const char *password, const char *command)
01183 {
01184 MyClient::SendRCon(password, command);
01185 }
01186
01193 void NetworkClientRequestMove(CompanyID company_id, const char *pass)
01194 {
01195 MyClient::SendMove(company_id, pass);
01196 }
01197
01202 void NetworkClientsToSpectators(CompanyID cid)
01203 {
01204 Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
01205
01206 if (cid == _local_company) SetLocalCompany(COMPANY_SPECTATOR);
01207
01208 NetworkClientInfo *ci;
01209 FOR_ALL_CLIENT_INFOS(ci) {
01210 if (ci->client_playas != cid) continue;
01211 NetworkTextMessage(NETWORK_ACTION_COMPANY_SPECTATOR, CC_DEFAULT, false, ci->client_name);
01212 ci->client_playas = COMPANY_SPECTATOR;
01213 }
01214
01215 cur_company.Restore();
01216 }
01217
01221 void NetworkUpdateClientName()
01222 {
01223 NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
01224
01225 if (ci == NULL) return;
01226
01227
01228 if (strcmp(ci->client_name, _settings_client.network.client_name) != 0) {
01229 if (!_network_server) {
01230 MyClient::SendSetName(_settings_client.network.client_name);
01231 } else {
01232 if (NetworkFindName(_settings_client.network.client_name)) {
01233 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, _settings_client.network.client_name);
01234 strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name));
01235 NetworkUpdateClientInfo(CLIENT_ID_SERVER);
01236 }
01237 }
01238 }
01239 }
01240
01249 void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data)
01250 {
01251 MyClient::SendChat(action, type, dest, msg, data);
01252 }
01253
01258 void NetworkClientSetCompanyPassword(const char *password)
01259 {
01260 MyClient::SendSetPassword(password);
01261 }
01262
01268 bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio)
01269 {
01270
01271 if (!_settings_client.gui.prefer_teamchat || !Company::IsValidID(cio->client_playas)) return false;
01272
01273 const NetworkClientInfo *ci;
01274 FOR_ALL_CLIENT_INFOS(ci) {
01275 if (ci->client_playas == cio->client_playas && ci != cio) return true;
01276 }
01277
01278 return false;
01279 }
01280
01285 bool NetworkMaxCompaniesReached()
01286 {
01287 return Company::GetNumItems() >= (_network_server ? _settings_client.network.max_companies : _network_server_max_companies);
01288 }
01289
01294 bool NetworkMaxSpectatorsReached()
01295 {
01296 return NetworkSpectatorCount() >= (_network_server ? _settings_client.network.max_spectators : _network_server_max_spectators);
01297 }
01298
01299 #endif