# udp.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    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       setsockopt(s->second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val));
    00100     }
    00101 #endif
    00102
    00103     /* Send the buffer */
    00104     int res = sendto(s->second, (const char*)p->buffer, p->size, 0, (const struct sockaddr *)send.GetAddress(), send.GetAddressLength());
    00105     DEBUG(net, 7, "[udp] sendto(%s)", send.GetAddressAsString());
    00106
    00107     /* Check for any errors, but ignore it otherwise */
    00108     if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %i", send.GetAddressAsString(), GET_LAST_ERROR());
    00109
    00110     if (!all) break;
    00111   }
    00112 }
    00113
    00117 void NetworkUDPSocketHandler::ReceivePackets()
    00118 {
    00119   for (SocketList::iterator s = this->sockets.Begin(); s != this->sockets.End(); s++) {
    00120     for (int i = 0; i < 1000; i++) { // Do not infinitely loop when DoSing with UDP
    00121       struct sockaddr_storage client_addr;
    00122       memset(&client_addr, 0, sizeof(client_addr));
    00123
    00124       Packet p(this);
    00125       socklen_t client_len = sizeof(client_addr);
    00126
    00127       /* Try to receive anything */
    00128       SetNonBlocking(s->second); // Some OSes seem to lose the non-blocking status of the socket
    00129       int nbytes = recvfrom(s->second, (char*)p.buffer, SEND_MTU, 0, (struct sockaddr *)&client_addr, &client_len);
    00130
    00131       /* Did we get the bytes for the base header of the packet? */
    00132       if (nbytes <= 0) break;    // No data, i.e. no packet
    00133       if (nbytes <= 2) continue; // Invalid data; try next packet
    00134
    00135       NetworkAddress address(client_addr, client_len);
    00136       p.PrepareToRead();
    00137
    00138       /* If the size does not match the packet must be corrupted.
    00139        * Otherwise it will be marked as corrupted later on. */
    00140       if (nbytes != p.size) {
    00141         DEBUG(net, 1, "received a packet with mismatching size from %s", address.GetAddressAsString());
    00142         continue;
    00143       }
    00144
    00145       /* Handle the packet */
    00146       this->HandleUDPPacket(&p, &address);
    00147     }
    00148   }
    00149 }
    00150
    00151
    00157 void NetworkUDPSocketHandler::SendNetworkGameInfo(Packet *p, const NetworkGameInfo *info)
    00158 {
    00159   p->Send_uint8 (NETWORK_GAME_INFO_VERSION);
    00160
    00161   /*
    00162    *              Please observe the order.
    00163    * The parts must be read in the same order as they are sent!
    00164    */
    00165
    00166   /* Update the documentation in udp.h on changes
    00167    * to the NetworkGameInfo wire-protocol! */
    00168
    00169   /* NETWORK_GAME_INFO_VERSION = 4 */
    00170   {
    00171     /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
    00172      * the GRFs that are needed, i.e. the ones that the server has
    00173      * selected in the NewGRF GUI and not the ones that are used due
    00174      * to the fact that they are in [newgrf-static] in openttd.cfg */
    00175     const GRFConfig *c;
    00176     uint count = 0;
    00177
    00178     /* Count number of GRFs to send information about */
    00179     for (c = info->grfconfig; c != NULL; c = c->next) {
    00180       if (!HasBit(c->flags, GCF_STATIC)) count++;
    00181     }
    00182     p->Send_uint8 (count); // Send number of GRFs
    00183
    00184     /* Send actual GRF Identifications */
    00185     for (c = info->grfconfig; c != NULL; c = c->next) {
    00186       if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
    00187     }
    00188   }
    00189
    00190   /* NETWORK_GAME_INFO_VERSION = 3 */
    00191   p->Send_uint32(info->game_date);
    00192   p->Send_uint32(info->start_date);
    00193
    00194   /* NETWORK_GAME_INFO_VERSION = 2 */
    00195   p->Send_uint8 (info->companies_max);
    00196   p->Send_uint8 (info->companies_on);
    00197   p->Send_uint8 (info->spectators_max);
    00198
    00199   /* NETWORK_GAME_INFO_VERSION = 1 */
    00200   p->Send_string(info->server_name);
    00201   p->Send_string(info->server_revision);
    00202   p->Send_uint8 (info->server_lang);
    00203   p->Send_bool  (info->use_password);
    00204   p->Send_uint8 (info->clients_max);
    00205   p->Send_uint8 (info->clients_on);
    00206   p->Send_uint8 (info->spectators_on);
    00207   p->Send_string(info->map_name);
    00208   p->Send_uint16(info->map_width);
    00209   p->Send_uint16(info->map_height);
    00210   p->Send_uint8 (info->map_set);
    00211   p->Send_bool  (info->dedicated);
    00212 }
    00213
    00219 void NetworkUDPSocketHandler::ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *info)
    00220 {
    00221   static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
    00222
    00223   info->game_info_version = p->Recv_uint8();
    00224
    00225   /*
    00226    *              Please observe the order.
    00227    * The parts must be read in the same order as they are sent!
    00228    */
    00229
    00230   /* Update the documentation in udp.h on changes
    00231    * to the NetworkGameInfo wire-protocol! */
    00232
    00233   switch (info->game_info_version) {
    00234     case 4: {
    00235       GRFConfig **dst = &info->grfconfig;
    00236       uint i;
    00237       uint num_grfs = p->Recv_uint8();
    00238
    00239       /* Broken/bad data. It cannot have that many NewGRFs. */
    00240       if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
    00241
    00242       for (i = 0; i < num_grfs; i++) {
    00243         GRFConfig *c = new GRFConfig();
    00244         this->ReceiveGRFIdentifier(p, &c->ident);
    00245         this->HandleIncomingNetworkGameInfoGRFConfig(c);
    00246
    00247         /* Append GRFConfig to the list */
    00248         *dst = c;
    00249         dst = &c->next;
    00250       }
    00251       /* FALL THROUGH */
    00252     }
    00253     case 3:
    00254       info->game_date      = Clamp(p->Recv_uint32(), 0, MAX_DATE);
    00255       info->start_date     = Clamp(p->Recv_uint32(), 0, MAX_DATE);
    00256       /* FALL THROUGH */
    00257     case 2:
    00258       info->companies_max  = p->Recv_uint8 ();
    00259       info->companies_on   = p->Recv_uint8 ();
    00260       info->spectators_max = p->Recv_uint8 ();
    00261       /* FALL THROUGH */
    00262     case 1:
    00263       p->Recv_string(info->server_name,     sizeof(info->server_name));
    00264       p->Recv_string(info->server_revision, sizeof(info->server_revision));
    00265       info->server_lang    = p->Recv_uint8 ();
    00266       info->use_password   = p->Recv_bool  ();
    00267       info->clients_max    = p->Recv_uint8 ();
    00268       info->clients_on     = p->Recv_uint8 ();
    00269       info->spectators_on  = p->Recv_uint8 ();
    00270       if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
    00271         info->game_date    = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
    00272         info->start_date   = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
    00273       }
    00274       p->Recv_string(info->map_name, sizeof(info->map_name));
    00275       info->map_width      = p->Recv_uint16();
    00276       info->map_height     = p->Recv_uint16();
    00277       info->map_set        = p->Recv_uint8 ();
    00278       info->dedicated      = p->Recv_bool  ();
    00279
    00280       if (info->server_lang >= NETWORK_NUM_LANGUAGES)  info->server_lang = 0;
    00281       if (info->map_set     >= NETWORK_NUM_LANDSCAPES) info->map_set     = 0;
    00282   }
    00283 }
    00284
    00289 #define UDP_COMMAND(type) case type: this->NetworkPacketReceive_ ## type ## _command(p, client_addr); break;
    00290
    00296 void NetworkUDPSocketHandler::HandleUDPPacket(Packet *p, NetworkAddress *client_addr)
    00297 {
    00298   PacketUDPType type;
    00299
    00300   /* New packet == new client, which has not quit yet */
    00301   this->Reopen();
    00302
    00303   type = (PacketUDPType)p->Recv_uint8();
    00304
    00305   switch (this->HasClientQuit() ? PACKET_UDP_END : type) {
    00306     case PACKET_UDP_CLIENT_FIND_SERVER:   this->Receive_CLIENT_FIND_SERVER(p, client_addr);   break;
    00307     case PACKET_UDP_SERVER_RESPONSE:      this->Receive_SERVER_RESPONSE(p, client_addr);      break;
    00308     case PACKET_UDP_CLIENT_DETAIL_INFO:   this->Receive_CLIENT_DETAIL_INFO(p, client_addr);   break;
    00309     case PACKET_UDP_SERVER_DETAIL_INFO:   this->Receive_SERVER_DETAIL_INFO(p, client_addr);   break;
    00310     case PACKET_UDP_SERVER_REGISTER:      this->Receive_SERVER_REGISTER(p, client_addr);      break;
    00311     case PACKET_UDP_MASTER_ACK_REGISTER:  this->Receive_MASTER_ACK_REGISTER(p, client_addr);  break;
    00312     case PACKET_UDP_CLIENT_GET_LIST:      this->Receive_CLIENT_GET_LIST(p, client_addr);      break;
    00313     case PACKET_UDP_MASTER_RESPONSE_LIST: this->Receive_MASTER_RESPONSE_LIST(p, client_addr); break;
    00314     case PACKET_UDP_SERVER_UNREGISTER:    this->Receive_SERVER_UNREGISTER(p, client_addr);    break;
    00315     case PACKET_UDP_CLIENT_GET_NEWGRFS:   this->Receive_CLIENT_GET_NEWGRFS(p, client_addr);   break;
    00316     case PACKET_UDP_SERVER_NEWGRFS:       this->Receive_SERVER_NEWGRFS(p, client_addr);       break;
    00317     case PACKET_UDP_MASTER_SESSION_KEY:   this->Receive_MASTER_SESSION_KEY(p, client_addr);   break;
    00318
    00319     default:
    00320       if (this->HasClientQuit()) {
    00321         DEBUG(net, 0, "[udp] received invalid packet type %d from %s", type, client_addr->GetAddressAsString());
    00322       } else {
    00323         DEBUG(net, 0, "[udp] received illegal packet from %s", client_addr->GetAddressAsString());
    00324       }
    00325       break;
    00326   }
    00327 }
    00328
    00334 void NetworkUDPSocketHandler::ReceiveInvalidPacket(PacketUDPType type, NetworkAddress *client_addr)
    00335 {
    00336   DEBUG(net, 0, "[udp] received packet type %d on wrong port from %s", type, client_addr->GetAddressAsString());
    00337 }
    00338
    00339 void NetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_FIND_SERVER, client_addr); }
    00340 void NetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_RESPONSE, client_addr); }
    00341 void NetworkUDPSocketHandler::Receive_CLIENT_DETAIL_INFO(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_DETAIL_INFO, client_addr); }
    00342 void NetworkUDPSocketHandler::Receive_SERVER_DETAIL_INFO(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_DETAIL_INFO, client_addr); }
    00343 void NetworkUDPSocketHandler::Receive_SERVER_REGISTER(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_REGISTER, client_addr); }
    00344 void NetworkUDPSocketHandler::Receive_MASTER_ACK_REGISTER(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_MASTER_ACK_REGISTER, client_addr); }
    00345 void NetworkUDPSocketHandler::Receive_CLIENT_GET_LIST(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_GET_LIST, client_addr); }
    00346 void NetworkUDPSocketHandler::Receive_MASTER_RESPONSE_LIST(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_MASTER_RESPONSE_LIST, client_addr); }
    00347 void NetworkUDPSocketHandler::Receive_SERVER_UNREGISTER(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_UNREGISTER, client_addr); }
    00348 void NetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_GET_NEWGRFS, client_addr); }
    00349 void NetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_NEWGRFS, client_addr); }
    00350 void NetworkUDPSocketHandler::Receive_MASTER_SESSION_KEY(Packet *p, NetworkAddress *client_addr) { this->ReceiveInvalidPacket(PACKET_UDP_MASTER_SESSION_KEY, client_addr); }
    00351
    00352 #endif /* ENABLE_NETWORK */