udp.cpp

Go to the documentation of this file.
00001 /* $Id: udp.cpp 26046 2013-11-22 21:41:19Z 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 "../../debug.h"
00019 #include "udp.h"
00020 
00025 NetworkUDPSocketHandler::NetworkUDPSocketHandler(NetworkAddressList *bind)
00026 {
00027   if (bind != NULL) {
00028     for (NetworkAddress *addr = bind->Begin(); addr != bind->End(); addr++) {
00029       *this->bind.Append() = *addr;
00030     }
00031   } else {
00032     /* As hostname NULL and port 0/NULL don't go well when
00033      * resolving it we need to add an address for each of
00034      * the address families we support. */
00035     *this->bind.Append() = NetworkAddress(NULL, 0, AF_INET);
00036     *this->bind.Append() = NetworkAddress(NULL, 0, AF_INET6);
00037   }
00038 }
00039 
00040 
00045 bool NetworkUDPSocketHandler::Listen()
00046 {
00047   /* Make sure socket is closed */
00048   this->Close();
00049 
00050   for (NetworkAddress *addr = this->bind.Begin(); addr != this->bind.End(); addr++) {
00051     addr->Listen(SOCK_DGRAM, &this->sockets);
00052   }
00053 
00054   return this->sockets.Length() != 0;
00055 }
00056 
00060 void NetworkUDPSocketHandler::Close()
00061 {
00062   for (SocketList::iterator s = this->sockets.Begin(); s != this->sockets.End(); s++) {
00063     closesocket(s->second);
00064   }
00065   this->sockets.Clear();
00066 }
00067 
00068 NetworkRecvStatus NetworkUDPSocketHandler::CloseConnection(bool error)
00069 {
00070   NetworkSocketHandler::CloseConnection(error);
00071   return NETWORK_RECV_STATUS_OKAY;
00072 }
00073 
00081 void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool all, bool broadcast)
00082 {
00083   if (this->sockets.Length() == 0) this->Listen();
00084 
00085   for (SocketList::iterator s = this->sockets.Begin(); s != this->sockets.End(); s++) {
00086     /* Make a local copy because if we resolve it we cannot
00087      * easily unresolve it so we can resolve it later again. */
00088     NetworkAddress send(*recv);
00089 
00090     /* Not the same type */
00091     if (!send.IsFamily(s->first.GetAddress()->ss_family)) continue;
00092 
00093     p->PrepareToSend();
00094 
00095 #ifndef BEOS_NET_SERVER /* will work around this, some day; maybe. */
00096     if (broadcast) {
00097       /* Enable broadcast */
00098       unsigned long val = 1;
00099       if (setsockopt(s->second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) {
00100         DEBUG(net, 1, "[udp] setting broadcast failed with: %i", GET_LAST_ERROR());
00101       }
00102     }
00103 #endif
00104 
00105     /* Send the buffer */
00106     int res = sendto(s->second, (const char*)p->buffer, p->size, 0, (const struct sockaddr *)send.GetAddress(), send.GetAddressLength());
00107     DEBUG(net, 7, "[udp] sendto(%s)", send.GetAddressAsString());
00108 
00109     /* Check for any errors, but ignore it otherwise */
00110     if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %i", send.GetAddressAsString(), GET_LAST_ERROR());
00111 
00112     if (!all) break;
00113   }
00114 }
00115 
00119 void NetworkUDPSocketHandler::ReceivePackets()
00120 {
00121   for (SocketList::iterator s = this->sockets.Begin(); s != this->sockets.End(); s++) {
00122     for (int i = 0; i < 1000; i++) { // Do not infinitely loop when DoSing with UDP
00123       struct sockaddr_storage client_addr;
00124       memset(&client_addr, 0, sizeof(client_addr));
00125 
00126       Packet p(this);
00127       socklen_t client_len = sizeof(client_addr);
00128 
00129       /* Try to receive anything */
00130       SetNonBlocking(s->second); // Some OSes seem to lose the non-blocking status of the socket
00131       int nbytes = recvfrom(s->second, (char*)p.buffer, SEND_MTU, 0, (struct sockaddr *)&client_addr, &client_len);
00132 
00133       /* Did we get the bytes for the base header of the packet? */
00134       if (nbytes <= 0) break;    // No data, i.e. no packet
00135       if (nbytes <= 2) continue; // Invalid data; try next packet
00136 
00137       NetworkAddress address(client_addr, client_len);
00138       p.PrepareToRead();
00139 
00140       /* If the size does not match the packet must be corrupted.
00141        * Otherwise it will be marked as corrupted later on. */
00142       if (nbytes != p.size) {
00143         DEBUG(net, 1, "received a packet with mismatching size from %s", address.GetAddressAsString());
00144         continue;
00145       }
00146 
00147       /* Handle the packet */
00148       this->HandleUDPPacket(&p, &address);
00149     }
00150   }
00151 }
00152 
00153 
00159 void NetworkUDPSocketHandler::SendNetworkGameInfo(Packet *p, const NetworkGameInfo *info)
00160 {
00161   p->Send_uint8 (NETWORK_GAME_INFO_VERSION);
00162 
00163   /*
00164    *              Please observe the order.
00165    * The parts must be read in the same order as they are sent!
00166    */
00167 
00168   /* Update the documentation in udp.h on changes
00169    * to the NetworkGameInfo wire-protocol! */
00170 
00171   /* NETWORK_GAME_INFO_VERSION = 4 */
00172   {
00173     /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
00174      * the GRFs that are needed, i.e. the ones that the server has
00175      * selected in the NewGRF GUI and not the ones that are used due
00176      * to the fact that they are in [newgrf-static] in openttd.cfg */
00177     const GRFConfig *c;
00178     uint count = 0;
00179 
00180     /* Count number of GRFs to send information about */
00181     for (c = info->grfconfig; c != NULL; c = c->next) {
00182       if (!HasBit(c->flags, GCF_STATIC)) count++;
00183     }
00184     p->Send_uint8 (count); // Send number of GRFs
00185 
00186     /* Send actual GRF Identifications */
00187     for (c = info->grfconfig; c != NULL; c = c->next) {
00188       if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
00189     }
00190   }
00191 
00192   /* NETWORK_GAME_INFO_VERSION = 3 */
00193   p->Send_uint32(info->game_date);
00194   p->Send_uint32(info->start_date);
00195 
00196   /* NETWORK_GAME_INFO_VERSION = 2 */
00197   p->Send_uint8 (info->companies_max);
00198   p->Send_uint8 (info->companies_on);
00199   p->Send_uint8 (info->spectators_max);
00200 
00201   /* NETWORK_GAME_INFO_VERSION = 1 */
00202   p->Send_string(info->server_name);
00203   p->Send_string(info->server_revision);
00204   p->Send_uint8 (info->server_lang);
00205   p->Send_bool  (info->use_password);
00206   p->Send_uint8 (info->clients_max);
00207   p->Send_uint8 (info->clients_on);
00208   p->Send_uint8 (info->spectators_on);
00209   p->Send_string(info->map_name);
00210   p->Send_uint16(info->map_width);
00211   p->Send_uint16(info->map_height);
00212   p->Send_uint8 (info->map_set);
00213   p->Send_bool  (info->dedicated);
00214 }
00215 
00221 void NetworkUDPSocketHandler::ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *info)
00222 {
00223   static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
00224 
00225   info->game_info_version = p->Recv_uint8();
00226 
00227   /*
00228    *              Please observe the order.
00229    * The parts must be read in the same order as they are sent!
00230    */
00231 
00232   /* Update the documentation in udp.h on changes
00233    * to the NetworkGameInfo wire-protocol! */
00234 
00235   switch (info->game_info_version) {
00236     case 4: {
00237       GRFConfig **dst = &info->grfconfig;
00238       uint i;
00239       uint num_grfs = p->Recv_uint8();
00240 
00241       /* Broken/bad data. It cannot have that many NewGRFs. */
00242       if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
00243 
00244       for (i = 0; i < num_grfs; i++) {
00245         GRFConfig *c = new GRFConfig();
00246         this->ReceiveGRFIdentifier(p, &c->ident);
00247         this->HandleIncomingNetworkGameInfoGRFConfig(c);
00248 
00249         /* Append GRFConfig to the list */
00250         *dst = c;
00251         dst = &c->next;
00252       }
00253       /* FALL THROUGH */
00254     }
00255     case 3:
00256       info->game_date      = Clamp(p->Recv_uint32(), 0, MAX_DATE);
00257       info->start_date     = Clamp(p->Recv_uint32(), 0, MAX_DATE);
00258       /* FALL THROUGH */
00259     case 2:
00260       info->companies_max  = p->Recv_uint8 ();
00261       info->companies_on   = p->Recv_uint8 ();
00262       info->spectators_max = p->Recv_uint8 ();
00263       /* FALL THROUGH */
00264     case 1:
00265       p->Recv_string(info->server_name,     sizeof(info->server_name));
00266       p->Recv_string(info->server_revision, sizeof(info->server_revision));
00267       info->server_lang    = p->Recv_uint8 ();
00268       info->use_password   = p->Recv_bool  ();
00269       info->clients_max    = p->Recv_uint8 ();
00270       info->clients_on     = p->Recv_uint8 ();
00271       info->spectators_on  = p->Recv_uint8 ();
00272       if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
00273         info->game_date    = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
00274         info->start_date   = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
00275       }
00276       p->Recv_string(info->map_name, sizeof(info->map_name));
00277       info->map_width      = p->Recv_uint16();
00278       info->map_height     = p->Recv_uint16();
00279       info->map_set        = p->Recv_uint8 ();
00280       info->dedicated      = p->Recv_bool  ();
00281 
00282       if (info->server_lang >= NETWORK_NUM_LANGUAGES)  info->server_lang = 0;
00283       if (info->map_set     >= NETWORK_NUM_LANDSCAPES) info->map_set     = 0;
00284   }
00285 }
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     case PACKET_UDP_CLIENT_FIND_SERVER:   this->Receive_CLIENT_FIND_SERVER(p, client_addr);   break;
00303     case PACKET_UDP_SERVER_RESPONSE:      this->Receive_SERVER_RESPONSE(p, client_addr);      break;
00304     case PACKET_UDP_CLIENT_DETAIL_INFO:   this->Receive_CLIENT_DETAIL_INFO(p, client_addr);   break;
00305     case PACKET_UDP_SERVER_DETAIL_INFO:   this->Receive_SERVER_DETAIL_INFO(p, client_addr);   break;
00306     case PACKET_UDP_SERVER_REGISTER:      this->Receive_SERVER_REGISTER(p, client_addr);      break;
00307     case PACKET_UDP_MASTER_ACK_REGISTER:  this->Receive_MASTER_ACK_REGISTER(p, client_addr);  break;
00308     case PACKET_UDP_CLIENT_GET_LIST:      this->Receive_CLIENT_GET_LIST(p, client_addr);      break;
00309     case PACKET_UDP_MASTER_RESPONSE_LIST: this->Receive_MASTER_RESPONSE_LIST(p, client_addr); break;
00310     case PACKET_UDP_SERVER_UNREGISTER:    this->Receive_SERVER_UNREGISTER(p, client_addr);    break;
00311     case PACKET_UDP_CLIENT_GET_NEWGRFS:   this->Receive_CLIENT_GET_NEWGRFS(p, client_addr);   break;
00312     case PACKET_UDP_SERVER_NEWGRFS:       this->Receive_SERVER_NEWGRFS(p, client_addr);       break;
00313     case PACKET_UDP_MASTER_SESSION_KEY:   this->Receive_MASTER_SESSION_KEY(p, client_addr);   break;
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 
00330 void NetworkUDPSocketHandler::ReceiveInvalidPacket(PacketUDPType type, NetworkAddress *client_addr)
00331 {
00332   DEBUG(net, 0, "[udp] received packet type %d on wrong port from %s", type, client_addr->GetAddressAsString());
00333 }
00334 
00335 void NetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_FIND_SERVER, client_addr); }
00336 void NetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_RESPONSE, client_addr); }
00337 void NetworkUDPSocketHandler::Receive_CLIENT_DETAIL_INFO(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_DETAIL_INFO, client_addr); }
00338 void NetworkUDPSocketHandler::Receive_SERVER_DETAIL_INFO(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_DETAIL_INFO, client_addr); }
00339 void NetworkUDPSocketHandler::Receive_SERVER_REGISTER(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_REGISTER, client_addr); }
00340 void NetworkUDPSocketHandler::Receive_MASTER_ACK_REGISTER(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_MASTER_ACK_REGISTER, client_addr); }
00341 void NetworkUDPSocketHandler::Receive_CLIENT_GET_LIST(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_GET_LIST, client_addr); }
00342 void NetworkUDPSocketHandler::Receive_MASTER_RESPONSE_LIST(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_MASTER_RESPONSE_LIST, client_addr); }
00343 void NetworkUDPSocketHandler::Receive_SERVER_UNREGISTER(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_UNREGISTER, client_addr); }
00344 void NetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_GET_NEWGRFS, client_addr); }
00345 void NetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_NEWGRFS, client_addr); }
00346 void NetworkUDPSocketHandler::Receive_MASTER_SESSION_KEY(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_MASTER_SESSION_KEY, client_addr); }
00347 
00348 #endif /* ENABLE_NETWORK */