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