Torque3D Documentation / _generateds / platformNet.cpp

platformNet.cpp

Engine/source/platform/platformNet.cpp

More...

Classes:

Namespaces:

Public Variables

Public Functions

addPolledSocket(NetSocket handleFd, SOCKET fd, S32 state, char * remoteAddr, S32 port)
gPolledSockets(__FILE__ , __LINE__ )
IPSocket6ToNetAddress(const struct sockaddr_in6 * sockAddr, NetAddress * address)
IPSocketToNetAddress(const struct sockaddr_in * sockAddr, NetAddress * address)
NetAddressToIPSocket(const NetAddress * address, struct sockaddr_in * sockAddr)
NetAddressToIPSocket6(const NetAddress * address, struct sockaddr_in6 * sockAddr)
bool
netSocketWaitForWritable(NetSocket handleFd, S32 timeoutMs)

Detailed Description

Public Variables

const SOCKET InvalidSocketHandle 

Public Functions

addPolledSocket(NetSocket handleFd, SOCKET fd, S32 state, char * remoteAddr, S32 port)

gPolledSockets(__FILE__ , __LINE__ )

IPSocket6ToNetAddress(const struct sockaddr_in6 * sockAddr, NetAddress * address)

IPSocketToNetAddress(const struct sockaddr_in * sockAddr, NetAddress * address)

NetAddressToIPSocket(const NetAddress * address, struct sockaddr_in * sockAddr)

NetAddressToIPSocket6(const NetAddress * address, struct sockaddr_in6 * sockAddr)

netSocketWaitForWritable(NetSocket handleFd, S32 timeoutMs)

   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24#include "platform/platformNet.h"
  25#include "platform/threads/mutex.h"
  26#include "core/strings/stringFunctions.h"
  27#include "core/util/hashFunction.h"
  28#include "console/consoleTypes.h"
  29
  30// jamesu - debug DNS
  31//#define TORQUE_DEBUG_LOOKUPS
  32
  33
  34#if defined (TORQUE_OS_WIN)
  35#define TORQUE_USE_WINSOCK
  36#include <errno.h>
  37#include <ws2tcpip.h>
  38
  39#ifndef EINPROGRESS
  40#define EINPROGRESS             WSAEINPROGRESS
  41#endif // EINPROGRESS
  42
  43#define ioctl ioctlsocket
  44
  45typedef S32 socklen_t;
  46
  47#elif defined ( TORQUE_OS_MAC )
  48
  49#include <unistd.h>
  50#include <sys/types.h>
  51#include <sys/socket.h>
  52#include <sys/poll.h>
  53#include <arpa/inet.h>
  54#include <netdb.h>
  55#include <netinet/in.h>
  56#include <errno.h>
  57#include <sys/ioctl.h>
  58#include <net/if.h>
  59
  60typedef sockaddr_in SOCKADDR_IN;
  61typedef sockaddr * PSOCKADDR;
  62typedef sockaddr SOCKADDR;
  63typedef in_addr IN_ADDR;
  64typedef int SOCKET;
  65
  66#define INVALID_SOCKET -1
  67#define SOCKET_ERROR   -1
  68
  69#define closesocket close
  70
  71#elif defined( TORQUE_OS_LINUX )
  72
  73#include <unistd.h>
  74#include <sys/types.h>
  75#include <sys/socket.h>
  76#include <sys/poll.h>
  77#include <arpa/inet.h>
  78#include <netdb.h>
  79#include <netinet/in.h>
  80#include <errno.h>
  81#include <sys/ioctl.h>
  82#include <net/if.h>
  83
  84typedef sockaddr_in SOCKADDR_IN;
  85typedef sockaddr_in6 SOCKADDR_IN6;
  86typedef sockaddr * PSOCKADDR;
  87typedef sockaddr SOCKADDR;
  88typedef in_addr IN_ADDR;
  89typedef in6_addr IN6_ADDR;
  90typedef int SOCKET;
  91
  92#define INVALID_SOCKET -1
  93#define SOCKET_ERROR   -1
  94
  95#define closesocket close
  96
  97#endif
  98
  99#if defined(TORQUE_USE_WINSOCK)
 100static const char* strerror_wsa( S32 code )
 101{
 102   switch( code )
 103   {
 104#define E( name ) case name: return #name;
 105      E( WSANOTINITIALISED );
 106      E( WSAENETDOWN );
 107      E( WSAEADDRINUSE );
 108      E( WSAEINPROGRESS );
 109      E( WSAEALREADY );
 110      E( WSAEADDRNOTAVAIL );
 111      E( WSAEAFNOSUPPORT );
 112      E( WSAEFAULT );
 113      E( WSAEINVAL );
 114      E( WSAEISCONN );
 115      E( WSAENETUNREACH );
 116      E( WSAEHOSTUNREACH );
 117      E( WSAENOBUFS );
 118      E( WSAENOTSOCK );
 119      E( WSAETIMEDOUT );
 120      E( WSAEWOULDBLOCK );
 121      E( WSAEACCES );
 122#undef E
 123      default:
 124         return "Unknown";
 125   }
 126}
 127#endif
 128
 129#include "core/util/tVector.h"
 130#include "platform/platformNetAsync.h"
 131#include "console/console.h"
 132#include "core/util/journal/process.h"
 133#include "core/util/journal/journal.h"
 134
 135
 136NetSocket NetSocket::INVALID = NetSocket::fromHandle(-1);
 137
 138template<class T> class ReservedSocketList
 139{
 140public:
 141   struct EntryType
 142   {
 143      T value;
 144      bool used;
 145
 146      EntryType() : value(-1), used(false) { ; }
 147
 148      bool operator==(const EntryType &e1)
 149      {
 150         return value == e1.value && used == e1.used;
 151      }
 152
 153      bool operator!=(const EntryType &e1)
 154      {
 155         return !(value == e1.value && used == e1.used);
 156      }
 157   };
 158
 159   Vector<EntryType> mSocketList;
 160   Mutex *mMutex;
 161
 162   ReservedSocketList()
 163   {
 164      mMutex = new Mutex;
 165   }
 166
 167   ~ReservedSocketList()
 168   {
 169      delete mMutex;
 170   }
 171
 172   inline void modify() { Mutex::lockMutex(mMutex); }
 173   inline void endModify() { Mutex::unlockMutex(mMutex); }
 174
 175   NetSocket reserve(SOCKET reserveId = -1, bool doLock = true);
 176   void remove(NetSocket socketToRemove, bool doLock = true);
 177
 178   T activate(NetSocket socketToActivate, int family, bool useUDP, bool clearOnFail = false);
 179   T resolve(NetSocket socketToResolve);
 180};
 181
 182const SOCKET InvalidSocketHandle = -1;
 183
 184static void IPSocketToNetAddress(const struct sockaddr_in *sockAddr, NetAddress *address);
 185static void IPSocket6ToNetAddress(const struct sockaddr_in6 *sockAddr, NetAddress *address);
 186
 187namespace PlatformNetState
 188{
 189   static S32 initCount = 0;
 190
 191   static const S32 defaultPort = 28000;
 192   static S32 netPort = 0;
 193
 194   static NetSocket udpSocket = NetSocket::INVALID;
 195   static NetSocket udp6Socket = NetSocket::INVALID;
 196   static NetSocket multicast6Socket = NetSocket::INVALID;
 197
 198   static ipv6_mreq multicast6Group;
 199
 200   static ReservedSocketList<SOCKET> smReservedSocketList;
 201
 202   Net::Error getLastError()
 203   {
 204#if defined(TORQUE_USE_WINSOCK)
 205      S32 err = WSAGetLastError();
 206      switch (err)
 207      {
 208      case 0:
 209         return Net::NoError;
 210      case WSAEWOULDBLOCK:
 211         return Net::WouldBlock;
 212      default:
 213         return Net::UnknownError;
 214      }
 215#else
 216      int theError = errno;
 217      if (errno == EAGAIN)
 218         return Net::WouldBlock;
 219      if (errno == 0)
 220         return Net::NoError;
 221      if (errno == EINPROGRESS)
 222         return Net::WouldBlock;
 223      
 224      return Net::UnknownError;
 225#endif
 226   }
 227
 228   S32 getDefaultGameProtocol()
 229   {
 230      // we turn off VDP in non-release builds because VDP does not support broadcast packets
 231      // which are required for LAN queries (PC->Xbox connectivity).  The wire protocol still
 232      // uses the VDP packet structure, though.
 233      S32 protocol = IPPROTO_UDP;
 234#ifdef TORQUE_DISABLE_PC_CONNECTIVITY
 235      // Xbox uses a VDP (voice/data protocol) socket for networking
 236      protocol = IPPROTO_VDP;
 237      useVDP = true;
 238#endif
 239
 240      return protocol;
 241   }
 242
 243   struct addrinfo* pickAddressByProtocol(struct addrinfo* addr, int protocol)
 244   {
 245      for (addr; addr != NULL; addr = addr->ai_next)
 246      {
 247         if (addr->ai_family == protocol)
 248            return addr;
 249      }
 250
 251      return NULL;
 252   }
 253
 254   /// Extracts core address parts from an address string. Returns false if it's malformed.
 255   bool extractAddressParts(const char *addressString, char outAddress[256], int &outPort, int &outFamily)
 256   {
 257      outPort = 0;
 258      outFamily = AF_UNSPEC;
 259
 260      if (!dStrnicmp(addressString, "ipx:", 4))
 261         // ipx support deprecated
 262         return false;
 263
 264      if (!dStrnicmp(addressString, "ip:", 3))
 265      {
 266         addressString += 3;  // eat off the ip:
 267         outFamily = AF_INET;
 268      }
 269      else if (!dStrnicmp(addressString, "ip6:", 4))
 270      {
 271         addressString += 4;  // eat off the ip6:
 272         outFamily = AF_INET6;
 273      }
 274
 275      if (strlen(addressString) > 255)
 276         return false;
 277
 278      char *portString = NULL;
 279
 280      if (addressString[0] == '[')
 281      {
 282         // Must be ipv6 notation
 283         dStrcpy(outAddress, addressString+1, 256);
 284         addressString = outAddress;
 285
 286         portString = dStrchr(outAddress, ']');
 287         if (portString)
 288         {
 289            // Sort out the :port after the ]
 290            *portString++ = '\0';
 291            if (*portString != ':')
 292            {
 293               portString = NULL;
 294            }
 295            else
 296            {
 297               *portString++ = '\0';
 298            }
 299         }
 300
 301         if (outFamily == AF_UNSPEC)
 302         {
 303            outFamily = AF_INET6;
 304         }
 305      }
 306      else
 307      {
 308         dStrcpy(outAddress, addressString, 256);
 309         addressString = outAddress;
 310
 311         // Check to see if we have multiple ":" which would indicate this is an ipv6 address
 312         char* scan = outAddress;
 313         int colonCount = 0;
 314         while (*scan != '\0' && colonCount < 2)
 315         {
 316            if (*scan++ == ':')
 317               colonCount++;
 318         }
 319         if (colonCount <= 1)
 320         {
 321            // either ipv4 or host
 322            portString = dStrchr(outAddress, ':');
 323
 324            if (portString)
 325            {
 326               *portString++ = '\0';
 327            }
 328         }
 329         else if (outFamily == AF_UNSPEC)
 330         {
 331            // Must be ipv6
 332            outFamily = AF_INET6;
 333         }
 334      }
 335
 336      if (portString)
 337      {
 338         outPort = dAtoi(portString);
 339      }
 340
 341      return true;
 342   }
 343
 344   Net::Error getSocketAddress(SOCKET socketFd, int requiredFamily, NetAddress *outAddress)
 345   {
 346      Net::Error error = Net::UnknownError;
 347
 348      if (requiredFamily == AF_INET)
 349      {
 350         sockaddr_in ipAddr;
 351         socklen_t len = sizeof(ipAddr);
 352         if (getsockname(socketFd, (struct sockaddr*)&ipAddr, &len) >= 0)
 353         {
 354            IPSocketToNetAddress(&ipAddr, outAddress);
 355            error = Net::NoError;
 356         }
 357         else
 358         {
 359            error = getLastError();
 360         }
 361      }
 362      else if (requiredFamily == AF_INET6)
 363      {
 364         sockaddr_in6 ipAddr;
 365         socklen_t len = sizeof(ipAddr);
 366         if (getsockname(socketFd, (struct sockaddr*)&ipAddr, &len) >= 0)
 367         {
 368            IPSocket6ToNetAddress(&ipAddr, outAddress);
 369            error = Net::NoError;
 370         }
 371         else
 372         {
 373            error = getLastError();
 374         }
 375      }
 376
 377      return error;
 378   }
 379};
 380
 381
 382
 383template<class T> NetSocket ReservedSocketList<T>::reserve(SOCKET reserveId, bool doLock)
 384{
 385   MutexHandle handle;
 386   if (doLock)
 387   {
 388      handle.lock(mMutex, true);
 389   }
 390
 391   S32 idx = mSocketList.find_next(EntryType());
 392   if (idx == -1)
 393   {
 394      EntryType entry;
 395      entry.value = reserveId;
 396      entry.used = true;
 397      mSocketList.push_back(entry);
 398      return NetSocket::fromHandle(mSocketList.size() - 1);
 399   }
 400   else
 401   {
 402      EntryType &entry = mSocketList[idx];
 403      entry.used = true;
 404      entry.value = reserveId;
 405   }
 406
 407   return NetSocket::fromHandle(idx);
 408}
 409
 410template<class T> void ReservedSocketList<T>::remove(NetSocket socketToRemove, bool doLock)
 411{
 412   MutexHandle handle;
 413   if (doLock)
 414   {
 415      handle.lock(mMutex, true);
 416   }
 417
 418   if ((U32)socketToRemove.getHandle() >= (U32)mSocketList.size())
 419      return;
 420
 421   mSocketList[socketToRemove.getHandle()] = EntryType();
 422}
 423
 424template<class T> T ReservedSocketList<T>::activate(NetSocket socketToActivate, int family, bool useUDP, bool clearOnFail)
 425{
 426   MutexHandle h;
 427   h.lock(mMutex, true);
 428
 429   int typeID = useUDP ? SOCK_DGRAM : SOCK_STREAM;
 430   int protocol = useUDP ? PlatformNetState::getDefaultGameProtocol() : 0;
 431
 432   if ((U32)socketToActivate.getHandle() >= (U32)mSocketList.size())
 433      return -1;
 434
 435   EntryType &entry = mSocketList[socketToActivate.getHandle()];
 436   if (!entry.used)
 437      return -1;
 438
 439   T socketFd = entry.value;
 440   if (socketFd == -1)
 441   {
 442      socketFd = ::socket(family, typeID, protocol);
 443
 444      if (socketFd == InvalidSocketHandle)
 445      {
 446         if (clearOnFail)
 447         {
 448            remove(socketToActivate, false);
 449         }
 450         return InvalidSocketHandle;
 451      }
 452      else
 453      {
 454         entry.used = true;
 455         entry.value = socketFd;
 456         return socketFd;
 457      }
 458   }
 459
 460   return socketFd;
 461}
 462
 463template<class T> T ReservedSocketList<T>::resolve(NetSocket socketToResolve)
 464{
 465   MutexHandle h;
 466   h.lock(mMutex, true);
 467
 468   if ((U32)socketToResolve.getHandle() >= (U32)mSocketList.size())
 469      return -1;
 470
 471   EntryType &entry = mSocketList[socketToResolve.getHandle()];
 472   return entry.used ? entry.value : -1;
 473}
 474
 475ConnectionNotifyEvent*   Net::smConnectionNotify = NULL;
 476ConnectionAcceptedEvent* Net::smConnectionAccept = NULL;
 477ConnectionReceiveEvent*  Net::smConnectionReceive = NULL;
 478PacketReceiveEvent*      Net::smPacketReceive = NULL;
 479
 480ConnectionNotifyEvent& Net::getConnectionNotifyEvent()
 481{
 482   return *smConnectionNotify;
 483}
 484
 485ConnectionAcceptedEvent& Net::getConnectionAcceptedEvent()
 486{
 487   return *smConnectionAccept;
 488}
 489
 490ConnectionReceiveEvent& Net::getConnectionReceiveEvent()
 491{
 492   return *smConnectionReceive;
 493}
 494
 495PacketReceiveEvent& Net::getPacketReceiveEvent()
 496{
 497   return *smPacketReceive;
 498}
 499
 500// Multicast stuff
 501bool Net::smMulticastEnabled = true;
 502//
 503// Protocol Stuff
 504bool Net::smIpv4Enabled = true;
 505bool Net::smIpv6Enabled = false;
 506//
 507
 508// the Socket structure helps us keep track of the
 509// above states
 510struct PolledSocket
 511{
 512   // local enum for socket states for polled sockets
 513   enum SocketState
 514   {
 515      InvalidState,
 516      Connected,
 517      ConnectionPending,
 518      Listening,
 519      NameLookupRequired
 520   };
 521
 522   PolledSocket()
 523   {
 524      fd = -1;
 525      handleFd = NetSocket::INVALID;
 526      state = InvalidState;
 527      remoteAddr[0] = 0;
 528      remotePort = -1;
 529   }
 530
 531   SOCKET fd;
 532   NetSocket handleFd;
 533   S32 state;
 534   char remoteAddr[256];
 535   S32 remotePort;
 536};
 537
 538// list of polled sockets
 539static Vector<PolledSocket*> gPolledSockets( __FILE__, __LINE__ );
 540
 541static PolledSocket* addPolledSocket(NetSocket handleFd, SOCKET fd, S32 state,
 542                               char* remoteAddr = NULL, S32 port = -1)
 543{
 544   PolledSocket* sock = new PolledSocket();
 545   sock->fd = fd;
 546   sock->handleFd = handleFd;
 547   sock->state = state;
 548   if (remoteAddr)
 549      dStrcpy(sock->remoteAddr, remoteAddr, 256);
 550   if (port != -1)
 551      sock->remotePort = port;
 552   gPolledSockets.push_back(sock);
 553   return sock;
 554}
 555
 556bool netSocketWaitForWritable(NetSocket handleFd, S32 timeoutMs)
 557{  
 558   fd_set writefds;
 559   timeval timeout;
 560   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
 561
 562   FD_ZERO( &writefds );
 563   FD_SET( socketFd, &writefds );
 564
 565   timeout.tv_sec = timeoutMs / 1000;
 566   timeout.tv_usec = ( timeoutMs % 1000 ) * 1000;
 567
 568   if( select(socketFd + 1, NULL, &writefds, NULL, &timeout) > 0 )
 569      return true;
 570
 571   return false;
 572}
 573
 574bool Net::init()
 575{
 576#if defined(TORQUE_USE_WINSOCK)
 577   if(!PlatformNetState::initCount)
 578   {
 579      WSADATA stWSAData;
 580      AssertISV( !WSAStartup( 0x0101, &stWSAData ), "Net::init - failed to init WinSock!" );
 581
 582      //logprintf("Winsock initialization %s", success ? "succeeded." : "failed!");
 583   }
 584#endif
 585   PlatformNetState::initCount++;
 586
 587   smConnectionNotify = new ConnectionNotifyEvent();
 588   smConnectionAccept = new ConnectionAcceptedEvent();
 589   smConnectionReceive = new ConnectionReceiveEvent();
 590   smPacketReceive = new PacketReceiveEvent();
 591
 592
 593   Process::notify(&Net::process, PROCESS_NET_ORDER);
 594
 595   return(true);
 596}
 597
 598void Net::shutdown()
 599{
 600   Process::remove(&Net::process);
 601
 602   while (gPolledSockets.size() > 0)
 603   {
 604      if (gPolledSockets[0] == NULL)
 605         gPolledSockets.erase(gPolledSockets.begin());
 606      else
 607         closeConnectTo(gPolledSockets[0]->handleFd);
 608   }
 609
 610   closePort();
 611   PlatformNetState::initCount--;
 612
 613   // Destroy event handlers
 614   delete smConnectionNotify;
 615   delete smConnectionAccept;
 616   delete smConnectionReceive;
 617   delete smPacketReceive;
 618
 619#if defined(TORQUE_USE_WINSOCK)
 620   if(!PlatformNetState::initCount)
 621   {
 622      WSACleanup();
 623   }
 624#endif
 625}
 626
 627// ipv4 version of name routines
 628
 629static void NetAddressToIPSocket(const NetAddress *address, struct sockaddr_in *sockAddr)
 630{
 631   dMemset(sockAddr, 0, sizeof(struct sockaddr_in));
 632   sockAddr->sin_family = AF_INET;
 633   sockAddr->sin_port = htons(address->port);
 634   #if defined(TORQUE_OS_BSD) || defined(TORQUE_OS_MAC)
 635   sockAddr->sin_len = sizeof(struct sockaddr_in);
 636   #endif
 637   if (address->type == NetAddress::IPBroadcastAddress)
 638   {
 639      sockAddr->sin_addr.s_addr = htonl(INADDR_BROADCAST);
 640   }
 641   else
 642   {
 643      dMemcpy(&sockAddr->sin_addr, &address->address.ipv4.netNum[0], 4);
 644   }
 645}
 646
 647static void IPSocketToNetAddress(const struct sockaddr_in *sockAddr, NetAddress *address)
 648{
 649   address->type = NetAddress::IPAddress;
 650   address->port = ntohs(sockAddr->sin_port);
 651   dMemcpy(&address->address.ipv4.netNum[0], &sockAddr->sin_addr, 4);
 652}
 653
 654// ipv6 version of name routines
 655
 656static void NetAddressToIPSocket6(const NetAddress *address, struct sockaddr_in6 *sockAddr)
 657{
 658   dMemset(sockAddr, 0, sizeof(struct sockaddr_in6));
 659#ifdef SIN6_LEN
 660   sockAddr->sin6_len = sizeof(struct sockaddr_in6);
 661#endif
 662   sockAddr->sin6_family = AF_INET6;
 663   sockAddr->sin6_port = ntohs(address->port);
 664
 665   if (address->type == NetAddress::IPV6MulticastAddress)
 666   {
 667      sockAddr->sin6_addr = PlatformNetState::multicast6Group.ipv6mr_multiaddr;
 668      sockAddr->sin6_scope_id = PlatformNetState::multicast6Group.ipv6mr_interface;
 669   }
 670   else
 671   {
 672      sockAddr->sin6_flowinfo = address->address.ipv6.netFlow;
 673      sockAddr->sin6_scope_id = address->address.ipv6.netScope;
 674      dMemcpy(&sockAddr->sin6_addr, address->address.ipv6.netNum, sizeof(address->address.ipv6.netNum));
 675   }
 676}
 677
 678static void IPSocket6ToNetAddress(const struct sockaddr_in6 *sockAddr, NetAddress *address)
 679{
 680   address->type = NetAddress::IPV6Address;
 681   address->port = ntohs(sockAddr->sin6_port);
 682   dMemcpy(address->address.ipv6.netNum, &sockAddr->sin6_addr, sizeof(address->address.ipv6.netNum));
 683   address->address.ipv6.netFlow = sockAddr->sin6_flowinfo;
 684   address->address.ipv6.netScope = sockAddr->sin6_scope_id;
 685}
 686
 687//
 688
 689NetSocket Net::openListenPort(U16 port, NetAddress::Type addressType)
 690{
 691   if(Journal::IsPlaying())
 692   {
 693      U32 ret;
 694      Journal::Read(&ret);
 695      return NetSocket::fromHandle(ret);
 696   }
 697
 698   Net::Error error = NoError;
 699   NetAddress address;
 700   if (Net::getListenAddress(addressType, &address) != Net::NoError)
 701      error = Net::WrongProtocolType;
 702
 703   NetSocket handleFd = NetSocket::INVALID;
 704   SOCKET sockId = InvalidSocketHandle;
 705
 706   if (error == NoError)
 707   {
 708      handleFd = openSocket();
 709      sockId = PlatformNetState::smReservedSocketList.activate(handleFd, address.type == NetAddress::IPAddress ? AF_INET : AF_INET6, false, true);
 710   }
 711
 712   if (error == NoError && (handleFd == NetSocket::INVALID || sockId == InvalidSocketHandle))
 713   {
 714      Con::errorf("Unable to open listen socket: %s", strerror(errno));
 715      error = NotASocket;
 716      handleFd = NetSocket::INVALID;
 717   }
 718
 719   if (error == NoError)
 720   {
 721      address.port = port;
 722      error = bindAddress(address, handleFd, false);
 723      if (error != NoError)
 724      {
 725         Con::errorf("Unable to bind port %d: %s", port, strerror(errno));
 726         closeSocket(handleFd);
 727         handleFd = NetSocket::INVALID;
 728      }
 729   }
 730
 731   if (error == NoError)
 732   {
 733      error = listen(handleFd, 4);
 734      if (error != NoError)
 735      {
 736         Con::errorf("Unable to listen on port %d: %s", port, strerror(errno));
 737         closeSocket(handleFd);
 738         handleFd = NetSocket::INVALID;
 739      }
 740   }
 741
 742   if (error == NoError)
 743   {
 744      setBlocking(handleFd, false);
 745      addPolledSocket(handleFd, sockId, PolledSocket::Listening);
 746   }
 747
 748   if(Journal::IsRecording())
 749      Journal::Write(U32(handleFd.getHandle()));
 750
 751   return handleFd;
 752}
 753
 754NetSocket Net::openConnectTo(const char *addressString)
 755{
 756   if (Journal::IsPlaying())
 757   {
 758      U32 ret;
 759      Journal::Read(&ret);
 760      return NetSocket::fromHandle(ret);
 761   }
 762
 763   NetAddress address;
 764   NetSocket handleFd = NetSocket::INVALID;
 765   Net::Error error = NoError;
 766
 767   error = Net::stringToAddress(addressString, &address, false);
 768
 769   if (error == NoError && address.type != NetAddress::IPAddress && address.type != NetAddress::IPV6Address)
 770   {
 771      error = Net::WrongProtocolType;
 772   }
 773
 774   // Open socket
 775   if (error == NoError || error == NeedHostLookup)
 776   {
 777      handleFd = openSocket();
 778   }
 779
 780   // Attempt to connect or queue a lookup
 781   if (error == NoError && address.type == NetAddress::IPAddress)
 782   {
 783      sockaddr_in ipAddr;
 784      NetAddressToIPSocket(&address, &ipAddr);
 785      SOCKET socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET, false, true);
 786      if (socketFd != InvalidSocketHandle)
 787      {
 788         setBlocking(handleFd, false);
 789         if (::connect(socketFd, (struct sockaddr *)&ipAddr, sizeof(ipAddr)) == -1)
 790         {
 791            Net::Error err = PlatformNetState::getLastError();
 792            if (err != Net::WouldBlock)
 793            {
 794               Con::errorf("Error connecting to %s: %u",
 795                  addressString, err);
 796               closeSocket(handleFd);
 797               handleFd = NetSocket::INVALID;
 798            }
 799         }
 800      }
 801      else
 802      {
 803         PlatformNetState::smReservedSocketList.remove(handleFd);
 804         handleFd = NetSocket::INVALID;
 805      }
 806
 807      if (handleFd != NetSocket::INVALID)
 808      {
 809         // add this socket to our list of polled sockets
 810         addPolledSocket(handleFd, socketFd, PolledSocket::ConnectionPending);
 811      }
 812   }
 813   else if (error == NoError && address.type == NetAddress::IPV6Address)
 814   {
 815      sockaddr_in6 ipAddr6;
 816      NetAddressToIPSocket6(&address, &ipAddr6);
 817      SOCKET socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET6, false, true);
 818      if (socketFd != InvalidSocketHandle)
 819      {
 820         setBlocking(handleFd, false);
 821         if (::connect(socketFd, (struct sockaddr *)&ipAddr6, sizeof(ipAddr6)) == -1)
 822         {
 823            Net::Error err = PlatformNetState::getLastError();
 824            if (err != Net::WouldBlock)
 825            {
 826               Con::errorf("Error connecting to %s: %u",
 827                  addressString, err);
 828               closeSocket(handleFd);
 829               handleFd = NetSocket::INVALID;
 830            }
 831         }
 832      }
 833      else
 834      {
 835         PlatformNetState::smReservedSocketList.remove(handleFd);
 836         handleFd = NetSocket::INVALID;
 837      }
 838
 839      if (handleFd != NetSocket::INVALID)
 840      {
 841         // add this socket to our list of polled sockets
 842         addPolledSocket(handleFd, socketFd, PolledSocket::ConnectionPending);
 843      }
 844   }
 845   else if (error == Net::NeedHostLookup)
 846   {
 847      // need to do an asynchronous name lookup.  first, add the socket
 848      // to the polled list
 849      char addr[256];
 850      int port = 0;
 851      int actualFamily = AF_UNSPEC;
 852      if (PlatformNetState::extractAddressParts(addressString, addr, port, actualFamily))
 853      {
 854         addPolledSocket(handleFd, InvalidSocketHandle, PolledSocket::NameLookupRequired, addr, port);
 855         // queue the lookup
 856         gNetAsync.queueLookup(addressString, handleFd);
 857      }
 858      else
 859      {
 860         closeSocket(handleFd);
 861         handleFd = NetSocket::INVALID;
 862      }
 863   }
 864   else
 865   {
 866      closeSocket(handleFd);
 867      handleFd = NetSocket::INVALID;
 868   }
 869
 870   if (Journal::IsRecording())
 871      Journal::Write(U32(handleFd.getHandle()));
 872   return handleFd;
 873}
 874
 875void Net::closeConnectTo(NetSocket handleFd)
 876{
 877   if(Journal::IsPlaying())
 878      return;
 879
 880   // if this socket is in the list of polled sockets, remove it
 881   for (S32 i = 0; i < gPolledSockets.size(); ++i)
 882   {
 883      if (gPolledSockets[i] && gPolledSockets[i]->handleFd == handleFd)
 884      {
 885         delete gPolledSockets[i];
 886         gPolledSockets[i] = NULL;
 887         break;
 888      }
 889   }
 890
 891   closeSocket(handleFd);
 892}
 893
 894Net::Error Net::sendtoSocket(NetSocket handleFd, const U8 *buffer, S32  bufferSize, S32 *outBufferWritten)
 895{
 896   if(Journal::IsPlaying())
 897   {
 898      U32 e;
 899      S32 outBytes;
 900      Journal::Read(&e);
 901      Journal::Read(&outBytes);
 902      if (outBufferWritten)
 903         *outBufferWritten = outBytes;
 904
 905      return (Net::Error) e;
 906   }
 907
 908   S32 outBytes = 0;
 909   Net::Error e = send(handleFd, buffer, bufferSize, &outBytes);
 910
 911   if (Journal::IsRecording())
 912   {
 913      Journal::Write(U32(e));
 914      Journal::Write(outBytes);
 915   }
 916
 917   if (outBufferWritten)
 918      *outBufferWritten = outBytes;
 919
 920   return e;
 921}
 922
 923bool Net::openPort(S32 port, bool doBind)
 924{
 925   if (PlatformNetState::udpSocket != NetSocket::INVALID)
 926   {
 927      closeSocket(PlatformNetState::udpSocket);
 928      PlatformNetState::udpSocket = NetSocket::INVALID;
 929   }
 930   if (PlatformNetState::udp6Socket != NetSocket::INVALID)
 931   {
 932      closeSocket(PlatformNetState::udp6Socket);
 933      PlatformNetState::udp6Socket = NetSocket::INVALID;
 934   }
 935
 936   // Update prefs
 937   Net::smMulticastEnabled = Con::getBoolVariable("pref::Net::Multicast6Enabled", true);
 938   Net::smIpv4Enabled = Con::getBoolVariable("pref::Net::IPV4Enabled", true);
 939   Net::smIpv6Enabled = Con::getBoolVariable("pref::Net::IPV6Enabled", false);
 940
 941   // we turn off VDP in non-release builds because VDP does not support broadcast packets
 942   // which are required for LAN queries (PC->Xbox connectivity).  The wire protocol still
 943   // uses the VDP packet structure, though.
 944   S32 protocol = PlatformNetState::getDefaultGameProtocol();
 945
 946   SOCKET socketFd = InvalidSocketHandle;
 947   NetAddress address;
 948   NetAddress listenAddress;
 949   char listenAddressStr[256];
 950
 951   if (Net::smIpv4Enabled)
 952   {
 953      if (Net::getListenAddress(NetAddress::IPAddress, &address) == Net::NoError)
 954      {
 955         address.port = port;
 956         socketFd = ::socket(AF_INET, SOCK_DGRAM, protocol);
 957         
 958         if (socketFd != InvalidSocketHandle)
 959         {
 960            PlatformNetState::udpSocket = PlatformNetState::smReservedSocketList.reserve(socketFd);
 961            Net::Error error = NoError;
 962            if (doBind)
 963            {
 964               error = bindAddress(address, PlatformNetState::udpSocket, true);
 965            }
 966            
 967            if (error == NoError)
 968               error = setBufferSize(PlatformNetState::udpSocket, 32768 * 8);
 969               
 970#ifndef TORQUE_DISABLE_PC_CONNECTIVITY
 971            if (error == NoError)
 972               error = setBroadcast(PlatformNetState::udpSocket, true);
 973#endif
 974               
 975            if (error == NoError)
 976               error = setBlocking(PlatformNetState::udpSocket, false);
 977
 978            if (error == NoError)
 979            {
 980               error = PlatformNetState::getSocketAddress(socketFd, AF_INET, &listenAddress);
 981               if (error == NoError)
 982               {
 983                  Net::addressToString(&listenAddress, listenAddressStr);
 984                  Con::printf("UDP initialized on ipv4 %s", listenAddressStr);
 985               }
 986            }
 987
 988            if (error != NoError)
 989            {
 990               closeSocket(PlatformNetState::udpSocket);
 991               PlatformNetState::udpSocket = NetSocket::INVALID;
 992               Con::printf("Unable to initialize UDP on ipv4 - error %d", error);
 993            }
 994         }
 995      }
 996      else
 997      {
 998         Con::errorf("Unable to initialize UDP on ipv4 - invalid address.");
 999         PlatformNetState::udpSocket = NetSocket::INVALID;
1000      }
1001   }
1002   
1003   if (Net::smIpv6Enabled)
1004   {
1005      if (Net::getListenAddress(NetAddress::IPV6Address, &address) == Net::NoError)
1006      {
1007         address.port = port;
1008         socketFd = ::socket(AF_INET6, SOCK_DGRAM, protocol);
1009
1010         if (socketFd != InvalidSocketHandle)
1011         {
1012            PlatformNetState::udp6Socket = PlatformNetState::smReservedSocketList.reserve(socketFd);
1013
1014            Net::Error error = NoError;
1015
1016            int v = 1;
1017            setsockopt(socketFd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&v, sizeof(v));
1018            PlatformNetState::getLastError();
1019
1020            if (doBind)
1021            {
1022               error = bindAddress(address, PlatformNetState::udp6Socket, true);
1023            }
1024
1025            if (error == NoError)
1026               error = setBufferSize(PlatformNetState::udp6Socket, 32768 * 8);
1027
1028            if (error == NoError)
1029               error = setBlocking(PlatformNetState::udp6Socket, false);
1030
1031            if (error == NoError)
1032            {
1033               error = PlatformNetState::getSocketAddress(socketFd, AF_INET6, &listenAddress);
1034               if (error == NoError)
1035               {
1036                  Net::addressToString(&listenAddress, listenAddressStr);
1037                  Con::printf("UDP initialized on ipv6 %s", listenAddressStr);
1038               }
1039            }
1040            
1041            if (error != NoError)
1042            {
1043               closeSocket(PlatformNetState::udp6Socket);
1044               PlatformNetState::udp6Socket = NetSocket::INVALID;
1045               Con::printf("Unable to initialize UDP on ipv6 - error %d", error);
1046            }
1047
1048            if (Net::smMulticastEnabled && doBind)
1049            {
1050               Net::enableMulticast();
1051            }
1052            else
1053            {
1054               Net::disableMulticast();
1055            }
1056         }
1057      }
1058   }
1059
1060   PlatformNetState::netPort = port;
1061
1062   return PlatformNetState::udpSocket != NetSocket::INVALID || PlatformNetState::udp6Socket != NetSocket::INVALID;
1063}
1064
1065NetSocket Net::getPort()
1066{
1067   return PlatformNetState::udpSocket;
1068}
1069
1070void Net::closePort()
1071{
1072   if (PlatformNetState::udpSocket != NetSocket::INVALID)
1073      closeSocket(PlatformNetState::udpSocket);
1074   if (PlatformNetState::udp6Socket != NetSocket::INVALID)
1075      closeSocket(PlatformNetState::udp6Socket);
1076}
1077
1078Net::Error Net::sendto(const NetAddress *address, const U8 *buffer, S32  bufferSize)
1079{
1080   if(Journal::IsPlaying())
1081      return NoError;
1082
1083   SOCKET socketFd;
1084
1085   if(address->type == NetAddress::IPAddress || address->type == NetAddress::IPBroadcastAddress)
1086   {
1087      socketFd = PlatformNetState::smReservedSocketList.resolve(PlatformNetState::udpSocket);
1088      if (socketFd != InvalidSocketHandle)
1089      {
1090         sockaddr_in ipAddr;
1091         NetAddressToIPSocket(address, &ipAddr);
1092
1093         if (::sendto(socketFd, (const char*)buffer, bufferSize, 0,
1094            (sockaddr *)&ipAddr, sizeof(sockaddr_in)) == SOCKET_ERROR)
1095            return PlatformNetState::getLastError();
1096         else
1097            return NoError;
1098      }
1099      else
1100      {
1101         return NotASocket;
1102      }
1103   }
1104   else if (address->type == NetAddress::IPV6Address || address->type == NetAddress::IPV6MulticastAddress)
1105   {
1106      socketFd = PlatformNetState::smReservedSocketList.resolve(address->type == NetAddress::IPV6MulticastAddress ? PlatformNetState::multicast6Socket : PlatformNetState::udp6Socket);
1107
1108      if (socketFd != InvalidSocketHandle)
1109      {
1110         sockaddr_in6 ipAddr;
1111         NetAddressToIPSocket6(address, &ipAddr);
1112         if (::sendto(socketFd, (const char*)buffer, bufferSize, 0,
1113          (struct sockaddr *) &ipAddr, sizeof(sockaddr_in6)) == SOCKET_ERROR)
1114            return PlatformNetState::getLastError();
1115         else
1116            return NoError;
1117      }
1118      else
1119      {
1120         return NotASocket;
1121      }
1122   }
1123
1124   return WrongProtocolType;
1125}
1126
1127void Net::process()
1128{
1129   // Process listening sockets
1130   processListenSocket(PlatformNetState::udpSocket);
1131   processListenSocket(PlatformNetState::udp6Socket);
1132
1133   // process the polled sockets.  This blob of code performs functions
1134   // similar to WinsockProc in winNet.cc
1135
1136   if (gPolledSockets.size() == 0)
1137      return;
1138
1139   S32 optval;
1140   socklen_t optlen = sizeof(S32);
1141   S32 bytesRead;
1142   Net::Error err;
1143   bool removeSock = false;
1144   PolledSocket *currentSock = NULL;
1145   NetSocket incomingHandleFd = NetSocket::INVALID;
1146   NetAddress out_h_addr;
1147   S32 out_h_length = 0;
1148   RawData readBuff;
1149   NetSocket removeSockHandle;
1150
1151   for (S32 i = 0; i < gPolledSockets.size();
1152      /* no increment, this is done at end of loop body */)
1153   {
1154      removeSock = false;
1155      currentSock = gPolledSockets[i];
1156      
1157      // Cleanup if we've removed it
1158      if (currentSock == NULL)
1159      {
1160         gPolledSockets.erase(i);
1161         continue;
1162      }
1163      
1164      switch (currentSock->state)
1165      {
1166      case PolledSocket::InvalidState:
1167         Con::errorf("Error, InvalidState socket in polled sockets  list");
1168         break;
1169      case PolledSocket::ConnectionPending:
1170         // see if it is now connected
1171         if (getsockopt(currentSock->fd, SOL_SOCKET, SO_ERROR,
1172            (char*)&optval, &optlen) == -1)
1173         {
1174            Con::errorf("Error getting socket options: %s",  strerror(errno));
1175            
1176            removeSock = true;
1177            removeSockHandle = currentSock->handleFd;
1178
1179            smConnectionNotify->trigger(currentSock->handleFd, Net::ConnectFailed);
1180         }
1181         else
1182         {
1183            if (optval == EINPROGRESS)
1184               // still connecting...
1185               break;
1186
1187            if (optval == 0)
1188            {
1189               // poll for writable status to be sure we're connected.
1190               bool ready = netSocketWaitForWritable(currentSock->handleFd,0);
1191               if(!ready)
1192                  break;
1193
1194               currentSock->state = PolledSocket::Connected;
1195               smConnectionNotify->trigger(currentSock->handleFd, Net::Connected);
1196            }
1197            else
1198            {
1199               // some kind of error
1200               Con::errorf("Error connecting: %s", strerror(errno));
1201               
1202               removeSock = true;
1203               removeSockHandle = currentSock->handleFd;
1204               
1205               smConnectionNotify->trigger(currentSock->handleFd, Net::ConnectFailed);
1206            }
1207         }
1208         break;
1209      case PolledSocket::Connected:
1210
1211         // try to get some data
1212         bytesRead = 0;
1213         readBuff.alloc(MaxPacketDataSize);
1214         err = Net::recv(currentSock->handleFd, (U8*)readBuff.data, MaxPacketDataSize, &bytesRead);
1215         if(err == Net::NoError)
1216         {
1217            if (bytesRead > 0)
1218            {
1219               // got some data, post it
1220               readBuff.size = bytesRead;
1221               smConnectionReceive->trigger(currentSock->handleFd, readBuff);
1222            }
1223            else
1224            {
1225               // ack! this shouldn't happen
1226               if (bytesRead < 0)
1227                  Con::errorf("Unexpected error on socket: %s", strerror(errno));
1228               
1229               removeSock = true;
1230               removeSockHandle = currentSock->handleFd;
1231
1232               // zero bytes read means EOF
1233               smConnectionNotify->trigger(currentSock->handleFd, Net::Disconnected);
1234            }
1235         }
1236         else if (err != Net::NoError && err != Net::WouldBlock)
1237         {
1238            Con::errorf("Error reading from socket: %s",  strerror(errno));
1239            
1240            removeSock = true;
1241            removeSockHandle = currentSock->handleFd;
1242            
1243            smConnectionNotify->trigger(currentSock->handleFd, Net::Disconnected);
1244         }
1245         break;
1246      case PolledSocket::NameLookupRequired:
1247         U32 newState;
1248
1249         // is the lookup complete?
1250         if (!gNetAsync.checkLookup(
1251            currentSock->handleFd, &out_h_addr, &out_h_length,
1252            sizeof(out_h_addr)))
1253            break;
1254
1255         if (out_h_length == -1)
1256         {
1257            Con::errorf("DNS lookup failed: %s", currentSock->remoteAddr);
1258            newState = Net::DNSFailed;
1259            removeSock = true;
1260            removeSockHandle = currentSock->handleFd;
1261         }
1262         else
1263         {
1264            // try to connect
1265            out_h_addr.port = currentSock->remotePort;
1266            const sockaddr *ai_addr = NULL;
1267            int ai_addrlen = 0;
1268            sockaddr_in socketAddress;
1269            sockaddr_in6 socketAddress6;
1270
1271            if (out_h_addr.type == NetAddress::IPAddress)
1272            {
1273               ai_addr = (const sockaddr*)&socketAddress;
1274               ai_addrlen = sizeof(socketAddress);
1275               NetAddressToIPSocket(&out_h_addr, &socketAddress);
1276
1277               currentSock->fd = PlatformNetState::smReservedSocketList.activate(currentSock->handleFd, AF_INET, false);
1278               setBlocking(currentSock->handleFd, false);
1279
1280#ifdef TORQUE_DEBUG_LOOKUPS
1281               char addrString[256];
1282               NetAddress addr;
1283               IPSocketToNetAddress(&socketAddress, &addr);
1284               Net::addressToString(&addr, addrString);
1285               Con::printf("DNS: lookup resolved to %s", addrString);
1286#endif
1287            }
1288            else if (out_h_addr.type == NetAddress::IPV6Address)
1289            {
1290               ai_addr = (const sockaddr*)&socketAddress6;
1291               ai_addrlen = sizeof(socketAddress6);
1292               NetAddressToIPSocket6(&out_h_addr, &socketAddress6);
1293
1294               currentSock->fd = PlatformNetState::smReservedSocketList.activate(currentSock->handleFd, AF_INET6, false);
1295               setBlocking(currentSock->handleFd, false);
1296
1297#ifdef TORQUE_DEBUG_LOOKUPS
1298               char addrString[256];
1299               NetAddress addr;
1300               IPSocket6ToNetAddress(&socketAddress6, &addr);
1301               Net::addressToString(&addr, addrString);
1302               Con::printf("DNS: lookup resolved to %s", addrString);
1303#endif
1304            }
1305            else
1306            {
1307               Con::errorf("Error connecting to %s: Invalid Protocol",
1308               currentSock->remoteAddr);
1309               newState = Net::ConnectFailed;
1310               removeSock = true;
1311               removeSockHandle = currentSock->handleFd;
1312            }
1313
1314            if (ai_addr)
1315            {
1316               if (::connect(currentSock->fd, ai_addr,
1317                  ai_addrlen) == -1)
1318               {
1319                  err = PlatformNetState::getLastError();
1320                  if (err != Net::WouldBlock)
1321                  {
1322                     Con::errorf("Error connecting to %s: %u",
1323                     currentSock->remoteAddr, err);
1324                     newState = Net::ConnectFailed;
1325                     removeSock = true;
1326                     removeSockHandle = currentSock->handleFd;
1327                  }
1328                  else
1329                  {
1330                     newState = Net::DNSResolved;
1331                     currentSock->state = PolledSocket::ConnectionPending;
1332                  }
1333               }
1334               else
1335               {
1336                  newState = Net::Connected;
1337                  currentSock->state = Connected;
1338               }
1339            }
1340         }
1341
1342         smConnectionNotify->trigger(currentSock->handleFd, newState);
1343         break;
1344      case PolledSocket::Listening:
1345         NetAddress incomingAddy;
1346
1347         incomingHandleFd = Net::accept(currentSock->handleFd, &incomingAddy);
1348         if(incomingHandleFd != NetSocket::INVALID)
1349         {
1350            setBlocking(incomingHandleFd, false);
1351            addPolledSocket(incomingHandleFd, PlatformNetState::smReservedSocketList.resolve(incomingHandleFd), Connected);
1352            smConnectionAccept->trigger(currentSock->handleFd, incomingHandleFd, incomingAddy);
1353         }
1354         break;
1355      }
1356
1357      // only increment index if we're not removing the connection,  since
1358      // the removal will shift the indices down by one
1359      if (removeSock)
1360         closeConnectTo(removeSockHandle);
1361      else
1362         i++;
1363   }
1364}
1365
1366void Net::processListenSocket(NetSocket socketHandle)
1367{
1368   if (socketHandle == NetSocket::INVALID)
1369      return;
1370
1371   sockaddr_storage sa;
1372   sa.ss_family = AF_UNSPEC;
1373   NetAddress srcAddress;
1374   RawData tmpBuffer;
1375   tmpBuffer.alloc(Net::MaxPacketDataSize);
1376
1377   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(socketHandle);
1378
1379   for (;;)
1380   {
1381      socklen_t addrLen = sizeof(sa);
1382      S32 bytesRead = -1;
1383
1384      if (socketHandle != NetSocket::INVALID)
1385         bytesRead = ::recvfrom(socketFd, (char *)tmpBuffer.data, Net::MaxPacketDataSize, 0, (struct sockaddr*)&sa, &addrLen);
1386
1387      if (bytesRead == -1)
1388         break;
1389
1390      if (sa.ss_family == AF_INET)
1391         IPSocketToNetAddress((sockaddr_in *)&sa, &srcAddress);
1392      else if (sa.ss_family == AF_INET6)
1393        IPSocket6ToNetAddress((sockaddr_in6 *)&sa, &srcAddress);
1394     else
1395         continue;
1396
1397      if (bytesRead <= 0)
1398         continue;
1399
1400      if (srcAddress.type == NetAddress::IPAddress &&
1401         srcAddress.address.ipv4.netNum[0] == 127 &&
1402         srcAddress.address.ipv4.netNum[1] == 0 &&
1403         srcAddress.address.ipv4.netNum[2] == 0 &&
1404         srcAddress.address.ipv4.netNum[3] == 1 &&
1405         srcAddress.port == PlatformNetState::netPort)
1406         continue;
1407
1408      tmpBuffer.size = bytesRead;
1409
1410      smPacketReceive->trigger(srcAddress, tmpBuffer);
1411   }
1412}
1413
1414NetSocket Net::openSocket()
1415{
1416   return PlatformNetState::smReservedSocketList.reserve();
1417}
1418
1419Net::Error Net::closeSocket(NetSocket handleFd)
1420{
1421   if(handleFd != NetSocket::INVALID)
1422   {
1423      SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
1424     PlatformNetState::smReservedSocketList.remove(handleFd);
1425
1426      if(!::closesocket(socketFd))
1427         return NoError;
1428      else
1429         return PlatformNetState::getLastError();
1430   }
1431   else
1432      return NotASocket;
1433}
1434
1435Net::Error Net::connect(NetSocket handleFd, const NetAddress *address)
1436{
1437   if(!(address->type == NetAddress::IPAddress || address->type == NetAddress::IPV6Address))
1438      return WrongProtocolType;
1439
1440   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
1441
1442   if (address->type == NetAddress::IPAddress)
1443   {
1444      sockaddr_in socketAddress;
1445      NetAddressToIPSocket(address, &socketAddress);
1446
1447      if (socketFd == InvalidSocketHandle)
1448      {
1449         socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET, false);
1450      }
1451
1452      if (!::connect(socketFd, (struct sockaddr *) &socketAddress, sizeof(socketAddress)))
1453         return NoError;
1454   }
1455   else if (address->type == NetAddress::IPV6Address)
1456   {
1457      sockaddr_in6 socketAddress;
1458      NetAddressToIPSocket6(address, &socketAddress);
1459
1460      if (socketFd == InvalidSocketHandle)
1461      {
1462         socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET6, false);
1463      }
1464
1465      if (!::connect(socketFd, (struct sockaddr *) &socketAddress, sizeof(socketAddress)))
1466         return NoError;
1467   }
1468
1469   return PlatformNetState::getLastError();
1470}
1471
1472Net::Error Net::listen(NetSocket handleFd, S32 backlog)
1473{
1474   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
1475   if (socketFd == InvalidSocketHandle)
1476      return NotASocket;
1477
1478   if(!::listen(socketFd, backlog))
1479      return NoError;
1480   return PlatformNetState::getLastError();
1481}
1482
1483NetSocket Net::accept(NetSocket handleFd, NetAddress *remoteAddress)
1484{
1485   sockaddr_storage addr;
1486   socklen_t addrLen = sizeof(addr);
1487
1488   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
1489   if (socketFd == InvalidSocketHandle)
1490      return NetSocket::INVALID;
1491
1492   SOCKET acceptedSocketFd = ::accept(socketFd, (sockaddr *)&addr, &addrLen);
1493   if (acceptedSocketFd != InvalidSocketHandle)
1494   {
1495      if (addr.ss_family == AF_INET)
1496      {
1497         // ipv4
1498         IPSocketToNetAddress(((struct sockaddr_in*)&addr), remoteAddress);
1499      }
1500      else if (addr.ss_family == AF_INET6)
1501      {
1502         // ipv6
1503         IPSocket6ToNetAddress(((struct sockaddr_in6*)&addr), remoteAddress);
1504      }
1505
1506      NetSocket newHandleFd = PlatformNetState::smReservedSocketList.reserve(acceptedSocketFd);
1507      return newHandleFd;
1508   }
1509
1510   return NetSocket::INVALID;
1511}
1512
1513Net::Error Net::bindAddress(const NetAddress &address, NetSocket handleFd, bool useUDP)
1514{
1515   int error = 0;
1516   sockaddr_storage socketAddress;
1517
1518   dMemset(&socketAddress, '\0', sizeof(socketAddress));
1519
1520   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
1521   if (socketFd == InvalidSocketHandle)
1522   {
1523      if (handleFd.getHandle() == -1)
1524         return NotASocket;
1525   }
1526
1527   if (address.type == NetAddress::IPAddress)
1528   {
1529      socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET, useUDP);
1530      NetAddressToIPSocket(&address, (struct sockaddr_in*)&socketAddress);
1531      error = ::bind(socketFd, (struct sockaddr*)&socketAddress, sizeof(sockaddr_in));
1532   }
1533   else if (address.type == NetAddress::IPV6Address)
1534   {
1535      socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET6, useUDP);
1536      NetAddressToIPSocket6(&address, (struct sockaddr_in6*)&socketAddress);
1537      error = ::bind(socketFd, (struct sockaddr*)&socketAddress, sizeof(sockaddr_in6));
1538   }
1539
1540   if (!error)
1541      return NoError;
1542   return PlatformNetState::getLastError();
1543}
1544
1545Net::Error Net::setBufferSize(NetSocket handleFd, S32 bufferSize)
1546{
1547   S32 error;
1548   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
1549   if (socketFd == InvalidSocketHandle)
1550      return NotASocket;
1551
1552   error = ::setsockopt(socketFd, SOL_SOCKET, SO_RCVBUF, (char *)  &bufferSize, sizeof(bufferSize));
1553   if(!error)
1554      error = ::setsockopt(socketFd, SOL_SOCKET, SO_SNDBUF, (char *)  &bufferSize, sizeof(bufferSize));
1555   if(!error)
1556      return NoError;
1557   return PlatformNetState::getLastError();
1558}
1559
1560Net::Error Net::setBroadcast(NetSocket handleFd, bool broadcast)
1561{
1562   S32 bc = broadcast;
1563   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
1564   if (socketFd == InvalidSocketHandle)
1565      return NotASocket;
1566   S32 error = ::setsockopt(socketFd, SOL_SOCKET, SO_BROADCAST, (char*)&bc,  sizeof(bc));
1567   if(!error)
1568      return NoError;
1569   return PlatformNetState::getLastError();
1570}
1571
1572Net::Error Net::setBlocking(NetSocket handleFd, bool blockingIO)
1573{
1574   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
1575   if (socketFd == InvalidSocketHandle)
1576      return NotASocket;
1577
1578   unsigned long notblock = !blockingIO;
1579   S32 error = ioctl(socketFd, FIONBIO, &notblock);
1580   if(!error)
1581      return NoError;
1582   return PlatformNetState::getLastError();
1583}
1584
1585Net::Error Net::getListenAddress(const NetAddress::Type type, NetAddress *address, bool forceDefaults)
1586{
1587   if (type == NetAddress::IPAddress)
1588   {
1589      const char* serverIP = forceDefaults ? NULL : Con::getVariable("pref::Net::BindAddress");
1590      if (!serverIP || serverIP[0] == '\0')
1591      {
1592         address->type = type;
1593         address->port = 0;
1594         *((U32*)address->address.ipv4.netNum) = INADDR_ANY;
1595         return Net::NoError;
1596      }
1597      else
1598      {
1599         return Net::stringToAddress(serverIP, address, false);
1600      }
1601   }
1602   else if (type == NetAddress::IPBroadcastAddress)
1603   {
1604      address->type = type;
1605      address->port = 0;
1606      *((U32*)address->address.ipv4.netNum) = INADDR_BROADCAST;
1607      return Net::NoError;
1608   }
1609   else if (type == NetAddress::IPV6Address)
1610   {
1611      const char* serverIP6 = forceDefaults ? NULL : Con::getVariable("pref::Net::BindAddress6");
1612      if (!serverIP6 || serverIP6[0] == '\0')
1613      {
1614         sockaddr_in6 addr;
1615         dMemset(&addr, '\0', sizeof(addr));
1616
1617         addr.sin6_port = 0;
1618         addr.sin6_addr = in6addr_any;
1619
1620         IPSocket6ToNetAddress(&addr, address);
1621         return Net::NoError;
1622      }
1623      else
1624      {
1625         return Net::stringToAddress(serverIP6, address, false);
1626      }
1627   }
1628   else if (type == NetAddress::IPV6MulticastAddress)
1629   {
1630      const char* multicastAddressValue = forceDefaults ? NULL : Con::getVariable("pref::Net::Multicast6Address");
1631      if (!multicastAddressValue || multicastAddressValue[0] == '\0')
1632      {
1633         multicastAddressValue = TORQUE_NET_DEFAULT_MULTICAST_ADDRESS;
1634      }
1635
1636      return Net::stringToAddress(multicastAddressValue, address, false);
1637   }
1638   else
1639   {
1640      return Net::WrongProtocolType;
1641   }
1642}
1643
1644void Net::getIdealListenAddress(NetAddress *address)
1645{
1646   dMemset(address, '\0', sizeof(NetAddress));
1647
1648   if (Net::smIpv6Enabled)
1649   {
1650      if (Net::getListenAddress(NetAddress::IPV6Address, address) == NeedHostLookup)
1651      {
1652         Net::getListenAddress(NetAddress::IPV6Address, address, true);
1653      }
1654   }
1655   else
1656   {
1657      if (Net::getListenAddress(NetAddress::IPAddress, address) == NeedHostLookup)
1658      {
1659         Net::getListenAddress(NetAddress::IPAddress, address, true);
1660      }
1661   }
1662}
1663
1664Net::Error Net::send(NetSocket handleFd, const U8 *buffer, S32 bufferSize, S32 *outBytesWritten)
1665{
1666   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
1667   if (socketFd == InvalidSocketHandle)
1668      return NotASocket;
1669
1670   errno = 0;
1671   S32 bytesWritten = ::send(socketFd, (const char*)buffer, bufferSize, 0);
1672
1673   if (outBytesWritten)
1674   {
1675      *outBytesWritten = *outBytesWritten < 0 ? 0 : bytesWritten;
1676   }
1677
1678   return PlatformNetState::getLastError();
1679}
1680
1681Net::Error Net::recv(NetSocket handleFd, U8 *buffer, S32 bufferSize, S32  *bytesRead)
1682{
1683   SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd);
1684   if (socketFd == InvalidSocketHandle)
1685      return NotASocket;
1686
1687   *bytesRead = ::recv(socketFd, (char*)buffer, bufferSize, 0);
1688   if(*bytesRead == -1)
1689      return PlatformNetState::getLastError();
1690   return NoError;
1691}
1692
1693bool Net::compareAddresses(const NetAddress *a1, const NetAddress *a2)
1694{
1695   return a1->isSameAddressAndPort(*a2);
1696}
1697
1698Net::Error Net::stringToAddress(const char *addressString, NetAddress  *address, bool hostLookup, int requiredFamily)
1699{
1700   char addr[256];
1701   int port = 0;
1702   int actualFamily = AF_UNSPEC;
1703   if (!PlatformNetState::extractAddressParts(addressString, addr, port, actualFamily))
1704   {
1705      return WrongProtocolType;
1706   }
1707   
1708   // Make sure family matches (in cast we have IP: stuff in address)
1709   if (requiredFamily != AF_UNSPEC && actualFamily != AF_UNSPEC && (actualFamily != requiredFamily))
1710   {
1711      return WrongProtocolType;
1712   }
1713   
1714   if (actualFamily == AF_UNSPEC)
1715   {
1716      actualFamily = requiredFamily;
1717   }
1718   
1719   addressString = addr;
1720   dMemset(address, '\0', sizeof(NetAddress));
1721   
1722   if (!dStricmp(addressString, "broadcast"))
1723   {
1724      address->type = NetAddress::IPBroadcastAddress;
1725      if (!(actualFamily == AF_UNSPEC || actualFamily == AF_INET))
1726         return WrongProtocolType;
1727      
1728      if (port != 0)
1729         address->port = port;
1730      else
1731         address->port = PlatformNetState::defaultPort;
1732   }
1733   else if (!dStricmp(addressString, "multicast"))
1734   {
1735      address->type = NetAddress::IPV6MulticastAddress;
1736      if (!(actualFamily == AF_UNSPEC || actualFamily == AF_INET6))
1737         return WrongProtocolType;
1738      
1739      if (port != 0)
1740         address->port = port;
1741      else
1742         address->port = PlatformNetState::defaultPort;
1743   }
1744   else
1745   {
1746      sockaddr_in ipAddr;
1747      sockaddr_in6 ipAddr6;
1748      
1749      dMemset(&ipAddr, 0, sizeof(ipAddr));
1750      dMemset(&ipAddr6, 0, sizeof(ipAddr6));
1751      
1752      bool hasInterface = dStrchr(addressString, '%') != NULL; // if we have an interface, best use getaddrinfo to parse
1753      
1754      // Check if we've got a simple ipv4 / ipv6
1755      
1756      if (inet_pton(AF_INET, addressString, &ipAddr.sin_addr) == 1)
1757      {
1758         if (!(actualFamily == AF_UNSPEC || actualFamily == AF_INET))
1759            return WrongProtocolType;
1760         IPSocketToNetAddress(((struct sockaddr_in*)&ipAddr), address);
1761         
1762         if (port != 0)
1763            address->port = port;
1764         else
1765            address->port = PlatformNetState::defaultPort;
1766         
1767         return NoError;
1768      }
1769      else if (!hasInterface && inet_pton(AF_INET6, addressString, &ipAddr6.sin6_addr) == 1)
1770      {
1771         if (!(actualFamily == AF_UNSPEC || actualFamily == AF_INET6))
1772            return WrongProtocolType;
1773         IPSocket6ToNetAddress(((struct sockaddr_in6*)&ipAddr6), address);
1774         
1775         if (port != 0)
1776            address->port = port;
1777         else
1778            address->port = PlatformNetState::defaultPort;
1779         
1780         return NoError;
1781      }
1782      else
1783      {
1784         if (!hostLookup && !hasInterface)
1785            return NeedHostLookup;
1786         
1787         struct addrinfo hint, *res = NULL;
1788         dMemset(&hint, 0, sizeof(hint));
1789         hint.ai_family = actualFamily;
1790         hint.ai_flags = hostLookup ? 0 : AI_NUMERICHOST;
1791         
1792         if (getaddrinfo(addressString, NULL, &hint, &res) == 0)
1793         {
1794            if (actualFamily != AF_UNSPEC)
1795            {
1796               // Prefer desired protocol
1797               res = PlatformNetState::pickAddressByProtocol(res, actualFamily);
1798            }
1799            
1800            if (res && res->ai_family == AF_INET)
1801            {
1802               // ipv4
1803               IPSocketToNetAddress(((struct sockaddr_in*)res->ai_addr), address);
1804            }
1805            else if (res && res->ai_family == AF_INET6)
1806            {
1807               // ipv6
1808               IPSocket6ToNetAddress(((struct sockaddr_in6*)res->ai_addr), address);
1809            }
1810            else
1811            {
1812               // unknown
1813               return UnknownError;
1814            }
1815            
1816            if (port != 0)
1817               address->port = port;
1818            else
1819               address->port = PlatformNetState::defaultPort;
1820         }
1821      }
1822   }
1823   
1824   return NoError;
1825}
1826
1827void Net::addressToString(const NetAddress *address, char  addressString[256])
1828{
1829   if(address->type == NetAddress::IPAddress || address->type == NetAddress::IPBroadcastAddress)
1830   {
1831      sockaddr_in ipAddr;
1832      NetAddressToIPSocket(address, &ipAddr);
1833      
1834      if (ipAddr.sin_addr.s_addr == htonl(INADDR_BROADCAST) || address->type == NetAddress::IPBroadcastAddress)
1835      {
1836         if (ipAddr.sin_port == 0)
1837            dSprintf(addressString, 256, "IP:Broadcast");
1838         else
1839            dSprintf(addressString, 256, "IP:Broadcast:%d", ntohs(ipAddr.sin_port));
1840      }
1841      else
1842      {
1843         char buffer[256];
1844         buffer[0] = '\0';
1845         inet_ntop(AF_INET, &(ipAddr.sin_addr), buffer, sizeof(buffer));
1846         if (ipAddr.sin_port == 0)
1847            dSprintf(addressString, 256, "IP:%s", buffer);
1848         else
1849            dSprintf(addressString, 256, "IP:%s:%i", buffer, ntohs(ipAddr.sin_port));
1850      }
1851   }
1852   else if (address->type == NetAddress::IPV6Address)
1853   {
1854      char buffer[256];
1855      buffer[0] = '\0';
1856      sockaddr_in6 ipAddr;
1857      NetAddressToIPSocket6(address, &ipAddr);
1858      inet_ntop(AF_INET6, &(ipAddr.sin6_addr), buffer, sizeof(buffer));
1859      if (ipAddr.sin6_port == 0)
1860         dSprintf(addressString, 256, "IP6:%s", buffer);
1861      else
1862         dSprintf(addressString, 256, "IP6:[%s]:%i", buffer, ntohs(ipAddr.sin6_port));
1863   }
1864   else if (address->type == NetAddress::IPV6MulticastAddress)
1865   {
1866      if (address->port == 0)
1867         dSprintf(addressString, 256, "IP6:Multicast");
1868      else
1869         dSprintf(addressString, 256, "IP6:Multicast:%d", address->port);
1870   }
1871   else
1872   {
1873      *addressString = 0;
1874      return;
1875   }
1876}
1877
1878void Net::enableMulticast()
1879{
1880   SOCKET socketFd;
1881
1882   if (Net::smIpv6Enabled)
1883   {
1884      socketFd = PlatformNetState::smReservedSocketList.resolve(PlatformNetState::udp6Socket);
1885
1886      if (socketFd != InvalidSocketHandle)
1887      {
1888         PlatformNetState::multicast6Socket = PlatformNetState::udp6Socket;
1889
1890         Net::Error error = NoError;
1891
1892         if (error == NoError)
1893         {
1894            unsigned long multicastTTL = 1;
1895
1896            if (setsockopt(socketFd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
1897               (char*)&multicastTTL, sizeof(multicastTTL)) < 0)
1898            {
1899               error = PlatformNetState::getLastError();
1900            }
1901         }
1902
1903         // Find multicast to bind to...
1904
1905         NetAddress multicastAddress;
1906         sockaddr_in6 multicastSocketAddress;
1907
1908         const char *multicastAddressValue = Con::getVariable("pref::Net::Multicast6Address");
1909         if (!multicastAddressValue || multicastAddressValue[0] == '\0')
1910         {
1911            multicastAddressValue = TORQUE_NET_DEFAULT_MULTICAST_ADDRESS;
1912         }
1913
1914         error = Net::stringToAddress(multicastAddressValue, &multicastAddress, false);
1915
1916         if (error == NoError)
1917         {
1918            dMemset(&PlatformNetState::multicast6Group, '\0', sizeof(&PlatformNetState::multicast6Group));
1919            NetAddressToIPSocket6(&multicastAddress, &multicastSocketAddress);
1920            dMemcpy(&PlatformNetState::multicast6Group.ipv6mr_multiaddr, &multicastSocketAddress.sin6_addr, sizeof(PlatformNetState::multicast6Group.ipv6mr_multiaddr));
1921         }
1922
1923         // Setup group
1924
1925         if (error == NoError)
1926         {
1927            const char *multicastInterface = Con::getVariable("pref::Net::Multicast6Interface");
1928
1929            if (multicastInterface && multicastInterface[0] != '\0')
1930            {
1931#ifdef TORQUE_USE_WINSOCK
1932               PlatformNetState::multicast6Group.ipv6mr_interface = dAtoi(multicastInterface);
1933#else
1934               PlatformNetState::multicast6Group.ipv6mr_interface = if_nametoindex(multicastInterface);
1935#endif
1936            }
1937            else
1938            {
1939               PlatformNetState::multicast6Group.ipv6mr_interface = 0; // 0 == accept from any interface
1940            }
1941
1942            if (PlatformNetState::multicast6Group.ipv6mr_interface && error == NoError)
1943            {
1944               if (setsockopt(socketFd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&PlatformNetState::multicast6Group.ipv6mr_interface, sizeof(PlatformNetState::multicast6Group.ipv6mr_interface)) < 0)
1945               {
1946                  error = PlatformNetState::getLastError();
1947               }
1948            }
1949
1950            if (error == NoError && setsockopt(socketFd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char*)&PlatformNetState::multicast6Group, sizeof(PlatformNetState::multicast6Group)) < 0)
1951            {
1952               error = PlatformNetState::getLastError();
1953            }
1954         }
1955
1956
1957         if (error == NoError)
1958         {
1959            char listenAddressStr[256];
1960            Net::addressToString(&multicastAddress, listenAddressStr);
1961            Con::printf("Multicast initialized on %s", listenAddressStr);
1962         }
1963
1964          if (error != NoError)
1965         {
1966            PlatformNetState::multicast6Socket = NetSocket::INVALID;
1967            Con::printf("Unable to multicast UDP - error %d", error);
1968         }
1969      }
1970   }
1971}
1972
1973void Net::disableMulticast()
1974{
1975   if (PlatformNetState::multicast6Socket != NetSocket::INVALID)
1976   {
1977      PlatformNetState::multicast6Socket = NetSocket::INVALID;
1978   }
1979}
1980
1981bool Net::isMulticastEnabled()
1982{
1983   return PlatformNetState::multicast6Socket != NetSocket::INVALID;
1984}
1985
1986U32 NetAddress::getHash() const
1987{
1988   U32 value = 0;
1989   switch (type)
1990   {
1991   case NetAddress::IPAddress:
1992      value = Torque::hash((const U8*)&address.ipv4.netNum, sizeof(address.ipv4.netNum), 0);
1993      break;
1994   case NetAddress::IPV6Address:
1995      value = Torque::hash((const U8*)address.ipv6.netNum, sizeof(address.ipv6.netNum), 0);
1996      break;
1997   default:
1998      value = 0;
1999      break;
2000   }
2001   return value;
2002}
2003
2004bool Net::isAddressTypeAvailable(NetAddress::Type addressType)
2005{
2006   switch (addressType)
2007   {
2008   case NetAddress::IPAddress:
2009      return PlatformNetState::udpSocket != NetSocket::INVALID;
2010   case NetAddress::IPV6Address:
2011      return PlatformNetState::udp6Socket != NetSocket::INVALID;
2012   case NetAddress::IPBroadcastAddress:
2013      return PlatformNetState::udpSocket != NetSocket::INVALID;
2014   case NetAddress::IPV6MulticastAddress:
2015      return PlatformNetState::multicast6Socket != NetSocket::INVALID;
2016   default:
2017      return false;
2018   }
2019}
2020