00001
00002
00010 #ifdef ENABLE_NETWORK
00011
00012 #include "../stdafx.h"
00013 #include "../date_func.h"
00014 #include "../map_func.h"
00015 #include "network_gamelist.h"
00016 #include "network_internal.h"
00017 #include "network_udp.h"
00018 #include "core/host.h"
00019 #include "../core/endian_func.hpp"
00020 #include "../core/alloc_func.hpp"
00021 #include "../string_func.h"
00022 #include "../company_base.h"
00023 #include "../settings_type.h"
00024 #include "../thread.h"
00025 #include "../rev.h"
00026
00027 #include "core/udp.h"
00028
00029 ThreadMutex *_network_udp_mutex = ThreadMutex::New();
00030
00031 enum {
00032 ADVERTISE_NORMAL_INTERVAL = 30000,
00033 ADVERTISE_RETRY_INTERVAL = 300,
00034 ADVERTISE_RETRY_TIMES = 3
00035 };
00036
00037 NetworkUDPSocketHandler *_udp_client_socket = NULL;
00038 NetworkUDPSocketHandler *_udp_server_socket = NULL;
00039 NetworkUDPSocketHandler *_udp_master_socket = NULL;
00040
00042
00043 class MasterNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
00044 protected:
00045 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
00046 public:
00047 virtual ~MasterNetworkUDPSocketHandler() {}
00048 };
00049
00050 DEF_UDP_RECEIVE_COMMAND(Master, PACKET_UDP_MASTER_ACK_REGISTER)
00051 {
00052 _network_advertise_retries = 0;
00053 DEBUG(net, 2, "[udp] advertising on master server successful");
00054
00055
00056 if (!_settings_client.network.server_advertise) NetworkUDPRemoveAdvertise(false);
00057 }
00058
00060
00061 class ServerNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
00062 protected:
00063 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
00064 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
00065 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
00066 public:
00067 virtual ~ServerNetworkUDPSocketHandler() {}
00068 };
00069
00070 DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_FIND_SERVER)
00071 {
00072
00073 if (!_network_udp_server) {
00074 return;
00075 }
00076
00077 NetworkGameInfo ngi;
00078
00079
00080 ngi.clients_on = _network_game_info.clients_on;
00081 ngi.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
00082
00083 ngi.server_lang = _settings_client.network.server_lang;
00084 ngi.use_password = !StrEmpty(_settings_client.network.server_password);
00085 ngi.clients_max = _settings_client.network.max_clients;
00086 ngi.companies_on = ActiveCompanyCount();
00087 ngi.companies_max = _settings_client.network.max_companies;
00088 ngi.spectators_on = NetworkSpectatorCount();
00089 ngi.spectators_max = _settings_client.network.max_spectators;
00090 ngi.game_date = _date;
00091 ngi.map_width = MapSizeX();
00092 ngi.map_height = MapSizeY();
00093 ngi.map_set = _settings_game.game_creation.landscape;
00094 ngi.dedicated = _network_dedicated;
00095 ngi.grfconfig = _grfconfig;
00096
00097 strecpy(ngi.map_name, _network_game_info.map_name, lastof(ngi.map_name));
00098 strecpy(ngi.server_name, _settings_client.network.server_name, lastof(ngi.server_name));
00099 strecpy(ngi.server_revision, _openttd_revision, lastof(ngi.server_revision));
00100
00101 Packet packet(PACKET_UDP_SERVER_RESPONSE);
00102 this->Send_NetworkGameInfo(&packet, &ngi);
00103
00104
00105 this->SendPacket(&packet, client_addr);
00106
00107 DEBUG(net, 2, "[udp] queried from '%s'", inet_ntoa(client_addr->sin_addr));
00108 }
00109
00110 DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_DETAIL_INFO)
00111 {
00112
00113 if (!_network_udp_server) return;
00114
00115 Packet packet(PACKET_UDP_SERVER_DETAIL_INFO);
00116
00117
00118 packet.Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
00119 packet.Send_uint8 (ActiveCompanyCount());
00120
00121
00122 NetworkCompanyStats company_stats[MAX_COMPANIES];
00123 NetworkPopulateCompanyStats(company_stats);
00124
00125 Company *company;
00126
00127 FOR_ALL_COMPANIES(company) {
00128
00129 this->Send_CompanyInformation(&packet, company, &company_stats[company->index]);
00130 }
00131
00132 this->SendPacket(&packet, client_addr);
00133 }
00134
00148 DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_GET_NEWGRFS)
00149 {
00150 uint8 num_grfs;
00151 uint i;
00152
00153 const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT];
00154 uint8 in_reply_count = 0;
00155 size_t packet_len = 0;
00156
00157 DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
00158
00159 num_grfs = p->Recv_uint8 ();
00160 if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
00161
00162 for (i = 0; i < num_grfs; i++) {
00163 GRFConfig c;
00164 const GRFConfig *f;
00165
00166 this->Recv_GRFIdentifier(p, &c);
00167
00168
00169 f = FindGRFConfig(c.grfid, c.md5sum);
00170 if (f == NULL) continue;
00171
00172
00173
00174
00175 packet_len += sizeof(c.grfid) + sizeof(c.md5sum) +
00176 min(strlen((f->name != NULL && !StrEmpty(f->name)) ? f->name : f->filename) + 1, (size_t)NETWORK_GRF_NAME_LENGTH);
00177 if (packet_len > SEND_MTU - 4) {
00178 break;
00179 }
00180 in_reply[in_reply_count] = f;
00181 in_reply_count++;
00182 }
00183
00184 if (in_reply_count == 0) return;
00185
00186 Packet packet(PACKET_UDP_SERVER_NEWGRFS);
00187 packet.Send_uint8(in_reply_count);
00188 for (i = 0; i < in_reply_count; i++) {
00189 char name[NETWORK_GRF_NAME_LENGTH];
00190
00191
00192 strecpy(name, (in_reply[i]->name != NULL && !StrEmpty(in_reply[i]->name)) ?
00193 in_reply[i]->name : in_reply[i]->filename, lastof(name));
00194 this->Send_GRFIdentifier(&packet, in_reply[i]);
00195 packet.Send_string(name);
00196 }
00197
00198 this->SendPacket(&packet, client_addr);
00199 }
00200
00202
00203 class ClientNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
00204 protected:
00205 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE);
00206 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST);
00207 DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS);
00208 virtual void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config);
00209 public:
00210 virtual ~ClientNetworkUDPSocketHandler() {}
00211 };
00212
00213 DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_RESPONSE)
00214 {
00215 NetworkGameList *item;
00216
00217
00218 if (_network_udp_server) return;
00219
00220 DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
00221
00222
00223 item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port));
00224
00225 this->Recv_NetworkGameInfo(p, &item->info);
00226
00227 item->info.compatible = true;
00228 {
00229
00230
00231
00232
00233
00234
00235
00236 const GRFConfig *in_request[NETWORK_MAX_GRF_COUNT];
00237 const GRFConfig *c;
00238 uint in_request_count = 0;
00239 struct sockaddr_in out_addr;
00240
00241 for (c = item->info.grfconfig; c != NULL; c = c->next) {
00242 if (c->status == GCS_NOT_FOUND) item->info.compatible = false;
00243 if (c->status != GCS_NOT_FOUND || strcmp(c->name, UNKNOWN_GRF_NAME_PLACEHOLDER) != 0) continue;
00244 in_request[in_request_count] = c;
00245 in_request_count++;
00246 }
00247
00248 if (in_request_count > 0) {
00249
00250 uint i;
00251 Packet packet(PACKET_UDP_CLIENT_GET_NEWGRFS);
00252
00253 packet.Send_uint8(in_request_count);
00254 for (i = 0; i < in_request_count; i++) {
00255 this->Send_GRFIdentifier(&packet, in_request[i]);
00256 }
00257
00258 out_addr.sin_family = AF_INET;
00259 out_addr.sin_port = htons(item->port);
00260 out_addr.sin_addr.s_addr = item->ip;
00261 this->SendPacket(&packet, &out_addr);
00262 }
00263 }
00264
00265 if (item->info.hostname[0] == '\0')
00266 snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr));
00267
00268
00269 item->info.version_compatible = IsNetworkCompatibleVersion(item->info.server_revision);
00270 item->info.compatible &= item->info.version_compatible;
00271
00272 item->online = true;
00273
00274 UpdateNetworkGameWindow(false);
00275 }
00276
00277 DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_MASTER_RESPONSE_LIST)
00278 {
00279
00280
00281
00282
00283
00284
00285 uint8 ver = p->Recv_uint8();
00286
00287 if (ver == 1) {
00288 for (int i = p->Recv_uint16(); i != 0 ; i--) {
00289 uint32 ip = TO_LE32(p->Recv_uint32());
00290 uint16 port = p->Recv_uint16();
00291
00292
00293 if (this->HasClientQuit()) return;
00294 NetworkUDPQueryServer(NetworkAddress(ip, port));
00295 }
00296 }
00297 }
00298
00300 DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_NEWGRFS)
00301 {
00302 uint8 num_grfs;
00303 uint i;
00304
00305 DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
00306
00307 num_grfs = p->Recv_uint8 ();
00308 if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
00309
00310 for (i = 0; i < num_grfs; i++) {
00311 char *unknown_name;
00312 char name[NETWORK_GRF_NAME_LENGTH];
00313 GRFConfig c;
00314
00315 this->Recv_GRFIdentifier(p, &c);
00316 p->Recv_string(name, sizeof(name));
00317
00318
00319
00320 if (StrEmpty(name)) continue;
00321
00322
00323
00324
00325 unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
00326 if (unknown_name != NULL && strcmp(unknown_name, UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
00327 ttd_strlcpy(unknown_name, name, NETWORK_GRF_NAME_LENGTH);
00328 }
00329 }
00330 }
00331
00332 void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
00333 {
00334
00335 const GRFConfig *f = FindGRFConfig(config->grfid, config->md5sum);
00336 if (f == NULL) {
00337
00338
00339
00340 config->name = FindUnknownGRFName(config->grfid, config->md5sum, true);
00341 config->status = GCS_NOT_FOUND;
00342 } else {
00343 config->filename = f->filename;
00344 config->name = f->name;
00345 config->info = f->info;
00346 }
00347 SetBit(config->flags, GCF_COPY);
00348 }
00349
00350
00351 void NetworkUDPCloseAll()
00352 {
00353 DEBUG(net, 1, "[udp] closed listeners");
00354
00355 _network_udp_mutex->BeginCritical();
00356 _udp_server_socket->Close();
00357 _udp_master_socket->Close();
00358 _udp_client_socket->Close();
00359 _network_udp_mutex->EndCritical();
00360
00361 _network_udp_server = false;
00362 _network_udp_broadcast = 0;
00363 }
00364
00365
00366 static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket)
00367 {
00368 uint i;
00369
00370 for (i = 0; _broadcast_list[i] != 0; i++) {
00371 Packet p(PACKET_UDP_CLIENT_FIND_SERVER);
00372 struct sockaddr_in out_addr;
00373
00374 out_addr.sin_family = AF_INET;
00375 out_addr.sin_port = htons(_settings_client.network.server_port);
00376 out_addr.sin_addr.s_addr = _broadcast_list[i];
00377
00378 DEBUG(net, 4, "[udp] broadcasting to %s", inet_ntoa(out_addr.sin_addr));
00379
00380 socket->SendPacket(&p, &out_addr);
00381 }
00382 }
00383
00384
00385
00386 void NetworkUDPQueryMasterServer()
00387 {
00388 struct sockaddr_in out_addr;
00389
00390 if (!_udp_client_socket->IsConnected()) {
00391 if (!_udp_client_socket->Listen(0, 0, true)) return;
00392 }
00393
00394 Packet p(PACKET_UDP_CLIENT_GET_LIST);
00395
00396 out_addr.sin_family = AF_INET;
00397 out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
00398 out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
00399
00400
00401 p.Send_uint8(NETWORK_MASTER_SERVER_VERSION);
00402
00403 _udp_client_socket->SendPacket(&p, &out_addr);
00404
00405 DEBUG(net, 2, "[udp] master server queried at %s:%d", inet_ntoa(out_addr.sin_addr), ntohs(out_addr.sin_port));
00406 }
00407
00408
00409 void NetworkUDPSearchGame()
00410 {
00411
00412 if (_network_udp_broadcast > 0) return;
00413
00414
00415 if (!_udp_client_socket->IsConnected()) {
00416 if (!_udp_client_socket->Listen(0, 0, true)) return;
00417 }
00418
00419 DEBUG(net, 0, "[udp] searching server");
00420
00421 NetworkUDPBroadCast(_udp_client_socket);
00422 _network_udp_broadcast = 300;
00423 }
00424
00426 struct NetworkUDPQueryServerInfo : NetworkAddress {
00427 bool manually;
00428 NetworkUDPQueryServerInfo(const NetworkAddress &address, bool manually) :
00429 NetworkAddress(address),
00430 manually(manually)
00431 {
00432 }
00433 };
00434
00439 void NetworkUDPQueryServerThread(void *pntr)
00440 {
00441 NetworkUDPQueryServerInfo *info = (NetworkUDPQueryServerInfo*)pntr;
00442
00443 struct sockaddr_in out_addr;
00444 out_addr.sin_family = AF_INET;
00445 out_addr.sin_port = htons(info->GetPort());
00446 out_addr.sin_addr.s_addr = info->GetIP();
00447
00448
00449 NetworkGameList *item = CallocT<NetworkGameList>(1);
00450 item->ip = info->GetIP();
00451 item->port = info->GetPort();
00452 strecpy(item->info.server_name, info->GetHostname(), lastof(item->info.server_name));
00453 strecpy(item->info.hostname, info->GetHostname(), lastof(item->info.hostname));
00454 item->manually = info->manually;
00455 NetworkGameListAddItemDelayed(item);
00456
00457 _network_udp_mutex->BeginCritical();
00458
00459 Packet p(PACKET_UDP_CLIENT_FIND_SERVER);
00460 if (_udp_client_socket != NULL) _udp_client_socket->SendPacket(&p, &out_addr);
00461 _network_udp_mutex->EndCritical();
00462
00463 delete info;
00464 }
00465
00466 void NetworkUDPQueryServer(NetworkAddress address, bool manually)
00467 {
00468
00469 if (!_udp_client_socket->IsConnected()) {
00470 if (!_udp_client_socket->Listen(0, 0, true)) return;
00471 }
00472
00473 NetworkUDPQueryServerInfo *info = new NetworkUDPQueryServerInfo(address, manually);
00474 if (address.IsResolved() || !ThreadObject::New(NetworkUDPQueryServerThread, info)) {
00475 NetworkUDPQueryServerThread(info);
00476 }
00477 }
00478
00479 void NetworkUDPRemoveAdvertiseThread(void *pntr)
00480 {
00481 DEBUG(net, 1, "[udp] removing advertise from master server");
00482
00483
00484 struct sockaddr_in out_addr;
00485 out_addr.sin_family = AF_INET;
00486 out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
00487 out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
00488
00489
00490 Packet p(PACKET_UDP_SERVER_UNREGISTER);
00491
00492 p.Send_uint8 (NETWORK_MASTER_SERVER_VERSION);
00493 p.Send_uint16(_settings_client.network.server_port);
00494
00495 _network_udp_mutex->BeginCritical();
00496 if (_udp_master_socket != NULL) _udp_master_socket->SendPacket(&p, &out_addr);
00497 _network_udp_mutex->EndCritical();
00498 }
00499
00504 void NetworkUDPRemoveAdvertise(bool blocking)
00505 {
00506
00507 if (!_networking || !_network_server || !_network_udp_server) return;
00508
00509
00510 if (!_udp_master_socket->IsConnected()) {
00511 if (!_udp_master_socket->Listen(_network_server_bind_ip, 0, false)) return;
00512 }
00513
00514 if (blocking || !ThreadObject::New(NetworkUDPRemoveAdvertiseThread, NULL)) {
00515 NetworkUDPRemoveAdvertiseThread(NULL);
00516 }
00517 }
00518
00519 void NetworkUDPAdvertiseThread(void *pntr)
00520 {
00521
00522 struct sockaddr_in out_addr;
00523 out_addr.sin_family = AF_INET;
00524 out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
00525 out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
00526
00527 DEBUG(net, 1, "[udp] advertising to master server");
00528
00529
00530 Packet p(PACKET_UDP_SERVER_REGISTER);
00531
00532 p.Send_string(NETWORK_MASTER_SERVER_WELCOME_MESSAGE);
00533 p.Send_uint8 (NETWORK_MASTER_SERVER_VERSION);
00534 p.Send_uint16(_settings_client.network.server_port);
00535
00536 _network_udp_mutex->BeginCritical();
00537 if (_udp_master_socket != NULL) _udp_master_socket->SendPacket(&p, &out_addr);
00538 _network_udp_mutex->EndCritical();
00539 }
00540
00541
00542
00543 void NetworkUDPAdvertise()
00544 {
00545
00546 if (!_networking || !_network_server || !_network_udp_server || !_settings_client.network.server_advertise)
00547 return;
00548
00549
00550 if (!_udp_master_socket->IsConnected()) {
00551 if (!_udp_master_socket->Listen(_network_server_bind_ip, 0, false)) return;
00552 }
00553
00554 if (_network_need_advertise) {
00555 _network_need_advertise = false;
00556 _network_advertise_retries = ADVERTISE_RETRY_TIMES;
00557 } else {
00558
00559 if (_network_advertise_retries == 0) {
00560 if ((_network_last_advertise_frame + ADVERTISE_NORMAL_INTERVAL) > _frame_counter)
00561 return;
00562 _network_advertise_retries = ADVERTISE_RETRY_TIMES;
00563 }
00564
00565 if ((_network_last_advertise_frame + ADVERTISE_RETRY_INTERVAL) > _frame_counter)
00566 return;
00567 }
00568
00569 _network_advertise_retries--;
00570 _network_last_advertise_frame = _frame_counter;
00571
00572 if (!ThreadObject::New(NetworkUDPAdvertiseThread, NULL)) {
00573 NetworkUDPAdvertiseThread(NULL);
00574 }
00575 }
00576
00577 void NetworkUDPInitialize()
00578 {
00579 assert(_udp_client_socket == NULL && _udp_server_socket == NULL && _udp_master_socket == NULL);
00580
00581 _network_udp_mutex->BeginCritical();
00582 _udp_client_socket = new ClientNetworkUDPSocketHandler();
00583 _udp_server_socket = new ServerNetworkUDPSocketHandler();
00584 _udp_master_socket = new MasterNetworkUDPSocketHandler();
00585
00586 _network_udp_server = false;
00587 _network_udp_broadcast = 0;
00588 _network_udp_mutex->EndCritical();
00589 }
00590
00591 void NetworkUDPShutdown()
00592 {
00593 NetworkUDPCloseAll();
00594
00595 _network_udp_mutex->BeginCritical();
00596 delete _udp_client_socket;
00597 delete _udp_server_socket;
00598 delete _udp_master_socket;
00599 _udp_client_socket = NULL;
00600 _udp_server_socket = NULL;
00601 _udp_master_socket = NULL;
00602 _network_udp_mutex->EndCritical();
00603 }
00604
00605 #endif