# udp.cpp

Go to the documentation of this file.

    00001 /* $Id: udp.cpp 14174 2008-08-25 20:10:45Z smatz $ */
    00002
    00007 #ifdef ENABLE_NETWORK
    00008
    00009 #include "../../stdafx.h"
    00010 #include "../../debug.h"
    00011 #include "../../core/bitmath_func.hpp"
    00012 #include "../../core/math_func.hpp"
    00013 #include "../../core/alloc_func.hpp"
    00014 #include "../../date_func.h"
    00015 #include "packet.h"
    00016 #include "udp.h"
    00017
    00025 bool NetworkUDPSocketHandler::Listen(const uint32 host, const uint16 port, const bool broadcast)
    00026 {
    00027   struct sockaddr_in sin;
    00028
    00029   /* Make sure socket is closed */
    00030   this->Close();
    00031
    00032   this->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    00033   if (!this->IsConnected()) {
    00034     DEBUG(net, 0, "[udp] failed to start UDP listener");
    00035     return false;
    00036   }
    00037
    00038   SetNonBlocking(this->sock);
    00039
    00040   sin.sin_family = AF_INET;
    00041   /* Listen on all IPs */
    00042   sin.sin_addr.s_addr = host;
    00043   sin.sin_port = htons(port);
    00044
    00045   if (bind(this->sock, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
    00046     DEBUG(net, 0, "[udp] bind failed on %s:%i", inet_ntoa(*(struct in_addr *)&host), port);
    00047     return false;
    00048   }
    00049
    00050   if (broadcast) {
    00051     /* Enable broadcast */
    00052     unsigned long val = 1;
    00053 #ifndef BEOS_NET_SERVER // will work around this, some day; maybe.
    00054     setsockopt(this->sock, SOL_SOCKET, SO_BROADCAST, (char *) &val , sizeof(val));
    00055 #endif
    00056   }
    00057
    00058   DEBUG(net, 1, "[udp] listening on port %s:%d", inet_ntoa(*(struct in_addr *)&host), port);
    00059
    00060   return true;
    00061 }
    00062
    00066 void NetworkUDPSocketHandler::Close()
    00067 {
    00068   if (!this->IsConnected()) return;
    00069
    00070   closesocket(this->sock);
    00071   this->sock = INVALID_SOCKET;
    00072 }
    00073
    00074 NetworkRecvStatus NetworkUDPSocketHandler::CloseConnection()
    00075 {
    00076   this->has_quit = true;
    00077   return NETWORK_RECV_STATUS_OKAY;
    00078 }
    00079
    00085 void NetworkUDPSocketHandler::SendPacket(Packet *p, const struct sockaddr_in *recv)
    00086 {
    00087   int res;
    00088
    00089   p->PrepareToSend();
    00090
    00091   /* Send the buffer */
    00092   res = sendto(this->sock, (const char*)p->buffer, p->size, 0, (struct sockaddr *)recv, sizeof(*recv));
    00093
    00094   /* Check for any errors, but ignore it otherwise */
    00095   if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR());
    00096 }
    00097
    00101 void NetworkUDPSocketHandler::ReceivePackets()
    00102 {
    00103   struct sockaddr_in client_addr;
    00104   socklen_t client_len;
    00105   int nbytes;
    00106   Packet p(this);
    00107   int packet_len;
    00108
    00109   if (!this->IsConnected()) return;
    00110
    00111   packet_len = sizeof(p.buffer);
    00112   client_len = sizeof(client_addr);
    00113
    00114   /* Try to receive anything */
    00115   SetNonBlocking(this->sock); // Some OSes seem to lose the non-blocking status of the socket
    00116   nbytes = recvfrom(this->sock, (char*)p.buffer, packet_len, 0, (struct sockaddr *)&client_addr, &client_len);
    00117
    00118   /* We got some bytes for the base header of the packet. */
    00119   if (nbytes > 2) {
    00120     p.PrepareToRead();
    00121
    00122     /* If the size does not match the packet must be corrupted.
    00123      * Otherwise it will be marked as corrupted later on. */
    00124     if (nbytes != p.size) {
    00125       DEBUG(net, 1, "received a packet with mismatching size from %s:%d",
    00126           inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
    00127
    00128       return;
    00129     }
    00130
    00131     /* Handle the packet */
    00132     this->HandleUDPPacket(&p, &client_addr);
    00133   }
    00134 }
    00135
    00136
    00142 void NetworkUDPSocketHandler::Send_NetworkGameInfo(Packet *p, const NetworkGameInfo *info)
    00143 {
    00144   p->Send_uint8 (NETWORK_GAME_INFO_VERSION);
    00145
    00146   /*
    00147    *              Please observe the order.
    00148    * The parts must be read in the same order as they are sent!
    00149    */
    00150
    00151   /* Update the documentation in udp.h on changes
    00152    * to the NetworkGameInfo wire-protocol! */
    00153
    00154   /* NETWORK_GAME_INFO_VERSION = 4 */
    00155   {
    00156     /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
    00157      * the GRFs that are needed, i.e. the ones that the server has
    00158      * selected in the NewGRF GUI and not the ones that are used due
    00159      * to the fact that they are in [newgrf-static] in openttd.cfg */
    00160     const GRFConfig *c;
    00161     uint count = 0;
    00162
    00163     /* Count number of GRFs to send information about */
    00164     for (c = info->grfconfig; c != NULL; c = c->next) {
    00165       if (!HasBit(c->flags, GCF_STATIC)) count++;
    00166     }
    00167     p->Send_uint8 (count); // Send number of GRFs
    00168
    00169     /* Send actual GRF Identifications */
    00170     for (c = info->grfconfig; c != NULL; c = c->next) {
    00171       if (!HasBit(c->flags, GCF_STATIC)) this->Send_GRFIdentifier(p, c);
    00172     }
    00173   }
    00174
    00175   /* NETWORK_GAME_INFO_VERSION = 3 */
    00176   p->Send_uint32(info->game_date);
    00177   p->Send_uint32(info->start_date);
    00178
    00179   /* NETWORK_GAME_INFO_VERSION = 2 */
    00180   p->Send_uint8 (info->companies_max);
    00181   p->Send_uint8 (info->companies_on);
    00182   p->Send_uint8 (info->spectators_max);
    00183
    00184   /* NETWORK_GAME_INFO_VERSION = 1 */
    00185   p->Send_string(info->server_name);
    00186   p->Send_string(info->server_revision);
    00187   p->Send_uint8 (info->server_lang);
    00188   p->Send_bool  (info->use_password);
    00189   p->Send_uint8 (info->clients_max);
    00190   p->Send_uint8 (info->clients_on);
    00191   p->Send_uint8 (info->spectators_on);
    00192   p->Send_string(info->map_name);
    00193   p->Send_uint16(info->map_width);
    00194   p->Send_uint16(info->map_height);
    00195   p->Send_uint8 (info->map_set);
    00196   p->Send_bool  (info->dedicated);
    00197 }
    00198
    00204 void NetworkUDPSocketHandler::Recv_NetworkGameInfo(Packet *p, NetworkGameInfo *info)
    00205 {
    00206   static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
    00207
    00208   info->game_info_version = p->Recv_uint8();
    00209
    00210   /*
    00211    *              Please observe the order.
    00212    * The parts must be read in the same order as they are sent!
    00213    */
    00214
    00215   /* Update the documentation in udp.h on changes
    00216    * to the NetworkGameInfo wire-protocol! */
    00217
    00218   switch (info->game_info_version) {
    00219     case 4: {
    00220       GRFConfig **dst = &info->grfconfig;
    00221       uint i;
    00222       uint num_grfs = p->Recv_uint8();
    00223
    00224       /* Broken/bad data. It cannot have that many NewGRFs. */
    00225       if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
    00226
    00227       for (i = 0; i < num_grfs; i++) {
    00228         GRFConfig *c = CallocT<GRFConfig>(1);
    00229         this->Recv_GRFIdentifier(p, c);
    00230         this->HandleIncomingNetworkGameInfoGRFConfig(c);
    00231
    00232         /* Append GRFConfig to the list */
    00233         *dst = c;
    00234         dst = &c->next;
    00235       }
    00236     } /* Fallthrough */
    00237     case 3:
    00238       info->game_date      = Clamp(p->Recv_uint32(), 0, MAX_DATE);
    00239       info->start_date     = Clamp(p->Recv_uint32(), 0, MAX_DATE);
    00240       /* Fallthrough */
    00241     case 2:
    00242       info->companies_max  = p->Recv_uint8 ();
    00243       info->companies_on   = p->Recv_uint8 ();
    00244       info->spectators_max = p->Recv_uint8 ();
    00245       /* Fallthrough */
    00246     case 1:
    00247       p->Recv_string(info->server_name,     sizeof(info->server_name));
    00248       p->Recv_string(info->server_revision, sizeof(info->server_revision));
    00249       info->server_lang    = p->Recv_uint8 ();
    00250       info->use_password   = p->Recv_bool  ();
    00251       info->clients_max    = p->Recv_uint8 ();
    00252       info->clients_on     = p->Recv_uint8 ();
    00253       info->spectators_on  = p->Recv_uint8 ();
    00254       if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
    00255         info->game_date    = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
    00256         info->start_date   = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
    00257       }
    00258       p->Recv_string(info->map_name, sizeof(info->map_name));
    00259       info->map_width      = p->Recv_uint16();
    00260       info->map_height     = p->Recv_uint16();
    00261       info->map_set        = p->Recv_uint8 ();
    00262       info->dedicated      = p->Recv_bool  ();
    00263
    00264       if (info->server_lang >= NETWORK_NUM_LANGUAGES)  info->server_lang = 0;
    00265       if (info->map_set     >= NETWORK_NUM_LANDSCAPES) info->map_set     = 0;
    00266   }
    00267 }
    00268
    00273 #define UDP_COMMAND(type) case type: this->NetworkPacketReceive_ ## type ## _command(p, client_addr); break;
    00274
    00280 void NetworkUDPSocketHandler::HandleUDPPacket(Packet *p, const struct sockaddr_in *client_addr)
    00281 {
    00282   PacketUDPType type;
    00283
    00284   /* New packet == new client, which has not quit yet */
    00285   this->has_quit = false;
    00286
    00287   type = (PacketUDPType)p->Recv_uint8();
    00288
    00289   switch (this->HasClientQuit() ? PACKET_UDP_END : type) {
    00290     UDP_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
    00291     UDP_COMMAND(PACKET_UDP_SERVER_RESPONSE);
    00292     UDP_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
    00293     UDP_COMMAND(PACKET_UDP_SERVER_DETAIL_INFO);
    00294     UDP_COMMAND(PACKET_UDP_SERVER_REGISTER);
    00295     UDP_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
    00296     UDP_COMMAND(PACKET_UDP_CLIENT_GET_LIST);
    00297     UDP_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST);
    00298     UDP_COMMAND(PACKET_UDP_SERVER_UNREGISTER);
    00299     UDP_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
    00300     UDP_COMMAND(PACKET_UDP_SERVER_NEWGRFS);
    00301
    00302     default:
    00303       if (this->HasClientQuit()) {
    00304         DEBUG(net, 0, "[udp] received invalid packet type %d from %s:%d", type,  inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
    00305       } else {
    00306         DEBUG(net, 0, "[udp] received illegal packet from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
    00307       }
    00308       break;
    00309   }
    00310 }
    00311
    00318 #define DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(type) \
    00319 void NetworkUDPSocketHandler::NetworkPacketReceive_## type ##_command(\
    00320     Packet *p, const struct sockaddr_in *client_addr) { \
    00321   DEBUG(net, 0, "[udp] received packet type %d on wrong port from %s:%d", \
    00322       type, inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); \
    00323 }
    00324
    00325 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
    00326 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE);
    00327 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
    00328 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_DETAIL_INFO);
    00329 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_REGISTER);
    00330 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
    00331 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_LIST);
    00332 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST);
    00333 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_UNREGISTER);
    00334 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
    00335 DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS);
    00336
    00337 #endif /* ENABLE_NETWORK */