Torque3D Documentation / _generateds / platformNet.cpp

platformNet.cpp

Engine/source/platform/platformNet.cpp

More...

Classes:

Namespaces:

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 
ConnectionAcceptedEvent * smConnectionAccept 
ConnectionNotifyEvent * smConnectionNotify 
ConnectionReceiveEvent * smConnectionReceive 
PacketReceiveEvent * smPacketReceive 

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