# udp.cpp

Go to the documentation of this file.

    00001 /* $Id: udp.cpp 17963 2009-11-03 17:30:08Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00014 #ifdef ENABLE_NETWORK
    00015
    00016 #include "../../stdafx.h"
    00017 #include "../../date_func.h"
    00018 #include "udp.h"
    00019
    00024 NetworkUDPSocketHandler::NetworkUDPSocketHandler(NetworkAddressList *bind)
    00025 {
    00026   if (bind != NULL) {
    00027     for (NetworkAddress *addr = bind->Begin(); addr != bind->End(); addr++) {
    00028       *this->bind.Append() = *addr;
    00029     }
    00030   } else {
    00031     /* As hostname NULL and port 0/NULL don't go well when
    00032      * resolving it we need to add an address for each of
    00033      * the address families we support. */
    00034     *this->bind.Append() = NetworkAddress(NULL, 0, AF_INET);
    00035     *this->bind.Append() = NetworkAddress(NULL, 0, AF_INET6);
    00036   }
    00037 }
    00038
    00039
    00044 bool NetworkUDPSocketHandler::Listen()
    00045 {
    00046   /* Make sure socket is closed */
    00047   this->Close();
    00048
    00049   for (NetworkAddress *addr = this->bind.Begin(); addr != this->bind.End(); addr++) {
    00050     addr->Listen(SOCK_DGRAM, &this->sockets);
    00051   }
    00052
    00053   return this->sockets.Length() != 0;
    00054 }
    00055
    00059 void NetworkUDPSocketHandler::Close()
    00060 {
    00061   for (SocketList::iterator s = this->sockets.Begin(); s != this->sockets.End(); s++) {
    00062     closesocket(s->second);
    00063   }
    00064   this->sockets.Clear();
    00065 }
    00066
    00067 NetworkRecvStatus NetworkUDPSocketHandler::CloseConnection(bool error)
    00068 {
    00069   NetworkSocketHandler::CloseConnection(error);
    00070   return NETWORK_RECV_STATUS_OKAY;
    00071 }
    00072
    00080 void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool all, bool broadcast)
    00081 {
    00082   if (this->sockets.Length() == 0) this->Listen();
    00083
    00084   for (SocketList::iterator s = this->sockets.Begin(); s != this->sockets.End(); s++) {
    00085     /* Make a local copy because if we resolve it we cannot
    00086      * easily unresolve it so we can resolve it later again. */
    00087     NetworkAddress send(*recv);
    00088
    00089     /* Not the same type */
    00090     if (!send.IsFamily(s->first.GetAddress()->ss_family)) continue;
    00091
    00092     p->PrepareToSend();
    00093
    00094 #ifndef BEOS_NET_SERVER /* will work around this, some day; maybe. */
    00095     if (broadcast) {
    00096       /* Enable broadcast */
    00097       unsigned long val = 1;
    00098       setsockopt(s->second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val));
    00099     }
    00100 #endif
    00101
    00102     /* Send the buffer */
    00103     int res = sendto(s->second, (const char*)p->buffer, p->size, 0, (struct sockaddr *)send.GetAddress(), send.GetAddressLength());
    00104     DEBUG(net, 7, "[udp] sendto(%s)", send.GetAddressAsString());
    00105
    00106     /* Check for any errors, but ignore it otherwise */
    00107     if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %i", send.GetAddressAsString(), GET_LAST_ERROR());
    00108
    00109     if (!all) break;
    00110   }
    00111 }
    00112
    00116 void NetworkUDPSocketHandler::ReceivePackets()
    00117 {
    00118   for (SocketList::iterator s = this->sockets.Begin(); s != this->sockets.End(); s++) {
    00119     struct sockaddr_storage client_addr;
    00120     memset(&client_addr, 0, sizeof(client_addr));
    00121
    00122     Packet p(this);
    00123     int packet_len = sizeof(p.buffer);
    00124     socklen_t client_len = sizeof(client_addr);
    00125
    00126     /* Try to receive anything */
    00127     SetNonBlocking(s->second); // Some OSes seem to lose the non-blocking status of the socket
    00128     int nbytes = recvfrom(s->second, (char*)p.buffer, packet_len, 0, (struct sockaddr *)&client_addr, &client_len);
    00129
    00130     /* We got some bytes for the base header of the packet. */
    00131     if (nbytes > 2) {
    00132       NetworkAddress address(client_addr, client_len);
    00133       p.PrepareToRead();
    00134
    00135       /* If the size does not match the packet must be corrupted.
    00136        * Otherwise it will be marked as corrupted later on. */
    00137       if (nbytes != p.size) {
    00138         DEBUG(net, 1, "received a packet with mismatching size from %s", address.GetAddressAsString());
    00139         return;
    00140       }
    00141
    00142       /* Handle the packet */
    00143       this->HandleUDPPacket(&p, &address);
    00144     }
    00145   }
    00146 }
    00147
    00148
    00154 void NetworkUDPSocketHandler::Send_NetworkGameInfo(Packet *p, const NetworkGameInfo *info)
    00155 {
    00156   p->Send_uint8 (NETWORK_GAME_INFO_VERSION);
    00157
    00158   /*
    00159    *              Please observe the order.
    00160    * The parts must be read in the same order as they are sent!
    00161    */
    00162
    00163   /* Update the documentation in udp.h on changes
    00164    * to the NetworkGameInfo wire-protocol! */
    00165
    00166   /* NETWORK_GAME_INFO_VERSION = 4 */
    00167   {
    00168     /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
    00169      * the GRFs that are needed, i.e. the ones that the server has
    00170      * selected in the NewGRF GUI and not the ones that are used due
    00171      * to the fact that they are in [newgrf-static] in openttd.cfg */
    00172     const GRFConfig *c;
    00173     uint count = 0;
    00174
    00175     /* Count number of GRFs to send information about */
    00176     for (c = info->grfconfig; c != NULL; c = c->next) {
    00177       if (!HasBit(c->flags, GCF_STATIC)) count++;
    00178     }
    00179     p->Send_uint8 (count); // Send number of GRFs
    00180
    00181     /* Send actual GRF Identifications */
    00182     for (c = info->grfconfig; c != NULL; c = c->next) {
    00183       if (!HasBit(c->flags, GCF_STATIC)) this->Send_GRFIdentifier(p, c);
    00184     }
    00185   }
    00186
    00187   /* NETWORK_GAME_INFO_VERSION = 3 */
    00188   p->Send_uint32(info->game_date);
    00189   p->Send_uint32(info->start_date);
    00190
    00191   /* NETWORK_GAME_INFO_VERSION = 2 */
    00192   p->Send_uint8 (info->companies_max);
    00193   p->Send_uint8 (info->companies_on);
    00194   p->Send_uint8 (info->spectators_max);
    00195
    00196   /* NETWORK_GAME_INFO_VERSION = 1 */
    00197   p->Send_string(info->server_name);
    00198   p->Send_string(info->server_revision);
    00199   p->Send_uint8 (info->server_lang);
    00200   p->Send_bool  (info->use_password);
    00201   p->Send_uint8 (info->clients_max);
    00202   p->Send_uint8 (info->clients_on);
    00203   p->Send_uint8 (info->spectators_on);
    00204   p->Send_string(info->map_name);
    00205   p->Send_uint16(info->map_width);
    00206   p->Send_uint16(info->map_height);
    00207   p->Send_uint8 (info->map_set);
    00208   p->Send_bool  (info->dedicated);
    00209 }
    00210
    00216 void NetworkUDPSocketHandler::Recv_NetworkGameInfo(Packet *p, NetworkGameInfo *info)
    00217 {
    00218   static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
    00219
    00220   info->game_info_version = p->Recv_uint8();
    00221
    00222   /*
    00223    *              Please observe the order.
    00224    * The parts must be read in the same order as they are sent!
    00225    */
    00226
    00227   /* Update the documentation in udp.h on changes
    00228    * to the NetworkGameInfo wire-protocol! */
    00229
    00230   switch (info->game_info_version) {
    00231     case 4: {
    00232       GRFConfig **dst = &info->grfconfig;
    00233       uint i;
    00234       uint num_grfs = p->Recv_uint8();
    00235
    00236       /* Broken/bad data. It cannot have that many NewGRFs. */
    00237       if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
    00238
    00239       for (i = 0; i < num_grfs; i++) {
    00240         GRFConfig *c = CallocT<GRFConfig>(1);
    00241         this->Recv_GRFIdentifier(p, c);
    00242         this->HandleIncomingNetworkGameInfoGRFConfig(c);
    00243
    00244         /* Append GRFConfig to the list */
    00245         *dst = c;
    00246         dst = &c->next;
    00247       }
    00248     } // Fallthrough
    00249     case 3:
    00250       info->game_date      = Clamp(p->Recv_uint32(), 0, MAX_DATE);
    00251       info->start_date     = Clamp(p->Recv_uint32(), 0, MAX_DATE);
    00252       /* Fallthrough */
    00253     case 2:
    00254       info->companies_max  = p->Recv_uint8 ();
    00255       info->companies_on   = p->Recv_uint8 ();
    00256       info->spectators_max = p->Recv_uint8 ();
    00257       /* Fallthrough */
    00258     case 1:
    00259       p->Recv_string(info->server_name,     sizeof(info->server_name));
    00260       p->Recv_string(info->server_revision, sizeof(info->server_revision));
    00261       info->server_lang    = p->Recv_uint8 ();
    00262       info->use_password   = p->Recv_bool  ();
    00263       info->clients_max    = p->Recv_uint8 ();
    00264       info->clients_on     = p->Recv_uint8 ();
    00265       info->spectators_on  = p->Recv_uint8 ();
    00266       if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
    00267         info->game_date    = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
    00268         info->start_date   = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
    00269       }
    00270       p->Recv_string(info->map_name, sizeof(info->map_name));
    00271       info->map_width      = p->Recv_uint16();
    00272       info->map_height     = p->Recv_uint16();
    00273       info->map_set        = p->Recv_uint8 ();
    00274       info->dedicated      = p->Recv_bool  ();
    00275
    00276       if (info->server_lang >= NETWORK_NUM_LANGUAGES)  info->server_lang = 0;
    00277       if (info->map_set     >= NETWORK_NUM_LANDSCAPES) info->map_set     = 0;
    00278   }
    00279 }
    00280
    00285 #define UDP_COMMAND(type) case type: this->NetworkPacketReceive_ ## type ## _command(p, client_addr); break;
    00286
    00292 void NetworkUDPSocketHandler::HandleUDPPacket(Packet *p, NetworkAddress *client_addr)
    00293 {
    00294   PacketUDPType type;
    00295
    00296   /* New packet == new client, which has not quit yet */
    00297   this->Reopen();
    00298
    00299   type = (PacketUDPType)p->Recv_uint8();
    00300
    00301   switch (this->HasClientQuit() ? PACKET_UDP_END : type) {
    00302     UDP_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
    00303     UDP_COMMAND(PACKET_UDP_SERVER_RESPONSE);
    00304     UDP_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
    00305     UDP_COMMAND(PACKET_UDP_SERVER_DETAIL_INFO);
    00306     UDP_COMMAND(PACKET_UDP_SERVER_REGISTER);
    00307     UDP_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
    00308     UDP_COMMAND(PACKET_UDP_CLIENT_GET_LIST);
    00309     UDP_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST);
    00310     UDP_COMMAND(PACKET_UDP_SERVER_UNREGISTER);
    00311     UDP_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
    00312     UDP_COMMAND(PACKET_UDP_SERVER_NEWGRFS);
    00313     UDP_COMMAND(PACKET_UDP_MASTER_SESSION_KEY);
    00314
    00315     default:
    00316       if (this->HasClientQuit()) {
    00317         DEBUG(net, 0, "[udp] received invalid packet type %d from %s", type, client_addr->GetAddressAsString());
    00318       } else {
    00319         DEBUG(net, 0, "[udp] received illegal packet from %s", client_addr->GetAddressAsString());
    00320       }
    00321       break;
    00322   }
    00323 }
    00324
    00331 #define DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(type) \
    00332 void NetworkUDPSocketHandler::NetworkPacketReceive_## type ##_command(\
    00333     Packet *p, NetworkAddress *client_addr) { \
    00334   DEBUG(net, 0, "[udp] received packet type %d on wrong port from %s", \
    00335       type, client_addr->GetAddressAsString()); \
    00336 }
    00337
    00338 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
    00339 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE);
    00340 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
    00341 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_DETAIL_INFO);
    00342 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_REGISTER);
    00343 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
    00344 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_LIST);
    00345 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST);
    00346 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_UNREGISTER);
    00347 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
    00348 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS);
    00349 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_SESSION_KEY);
    00350
    00351 #endif /* ENABLE_NETWORK */