浏览代码

Merge pull request #1817 from jamesu/ipv6_pr

Preliminary IPV6 Support
Areloch 8 年之前
父节点
当前提交
a3740719b1

+ 7 - 0
Engine/source/app/game.cpp

@@ -162,6 +162,13 @@ DefineConsoleFunction( setNetPort, bool, (int port, bool bind), (true), "(int po
    return Net::openPort((S32)port, bind);
 }
 
+DefineConsoleFunction(isAddressTypeAvailable, bool, (int addressType), , "(protocol id)"
+	"@brief Determines if a specified address type can be reached.\n\n"
+	"@ingroup Networking")
+{
+	return Net::isAddressTypeAvailable((NetAddress::Type)addressType);
+}
+
 DefineConsoleFunction( closeNetPort, void, (), , "()" 
    "@brief Closes the current network port\n\n"
    "@ingroup Networking")

+ 1 - 1
Engine/source/app/mainLoop.cpp

@@ -320,7 +320,7 @@ void StandardMainLoop::init()
    Sampler::init();
 
    // Hook in for UDP notification
-   Net::smPacketReceive.notify(GNet, &NetInterface::processPacketReceiveEvent);
+   Net::getPacketReceiveEvent().notify(GNet, &NetInterface::processPacketReceiveEvent);
 
    #ifdef TORQUE_DEBUG_GUARD
       Memory::flagCurrentAllocs( Memory::FLAG_Static );

+ 140 - 9
Engine/source/app/net/serverQuery.cpp

@@ -177,7 +177,7 @@ static Vector<Ping> gQueryList(__FILE__, __LINE__);
 
 struct PacketStatus
 {
-   U8  index;
+   U16  index;
    S32 key;
    U32 time;
    U32 tryCount;
@@ -191,6 +191,9 @@ struct PacketStatus
       time = _time;
       tryCount = gPacketRetryCount;
    }
+
+   inline U8 getOldIndex() { return (U8)index; }
+   inline U16 getIndex() { return index; }
 };
 
 static Vector<PacketStatus> gPacketStatusList(__FILE__, __LINE__);
@@ -212,6 +215,7 @@ struct ServerFilter
       OnlineQuery       = 0,        // Authenticated with master
       OfflineQuery      = BIT(0),   // On our own
       NoStringCompress  = BIT(1),
+      NewStyleResponse  = BIT(2),  // Include IPV6 servers
    };
 
    enum // Filter flags:
@@ -222,6 +226,14 @@ struct ServerFilter
       CurrentVersion    = BIT(7),
       NotXenon          = BIT(6)
    };
+
+   enum // Region mask flags
+   {
+      RegionIsIPV4Address = BIT(30),
+      RegionIsIPV6Address = BIT(31),
+
+      RegionAddressMask = RegionIsIPV4Address | RegionIsIPV6Address
+   };
    
    //Rearranging the fields according to their sizes
    char* gameType;
@@ -241,7 +253,7 @@ struct ServerFilter
    ServerFilter()
    {
       type = Normal;
-      queryFlags = 0;
+      queryFlags = NewStyleResponse;
       gameType = NULL;
       missionType = NULL;
       minPlayers = 0;
@@ -401,10 +413,17 @@ void queryLanServers(U32 port, U8 flags, const char* gameType, const char* missi
 
    NetAddress addr;
    char addrText[256];
+
+   // IPV4
    dSprintf( addrText, sizeof( addrText ), "IP:BROADCAST:%d", port );
    Net::stringToAddress( addrText, &addr );
    pushPingBroadcast( &addr );
 
+   // IPV6
+   dSprintf(addrText, sizeof(addrText), "IP6:MULTICAST:%d", port);
+   Net::stringToAddress(addrText, &addr);
+   pushPingBroadcast(&addr);
+
    Con::executef("onServerQueryStatus", "start", "Querying LAN servers", "0");
    processPingsAndQueries( gPingSession );
 }
@@ -502,7 +521,7 @@ void queryMasterServer(U8 flags, const char* gameType, const char* missionType,
          dStrcpy( sActiveFilter.missionType, missionType );
       }
 
-      sActiveFilter.queryFlags   = flags;
+      sActiveFilter.queryFlags   = flags | ServerFilter::NewStyleResponse;
       sActiveFilter.minPlayers   = minPlayers;
       sActiveFilter.maxPlayers   = maxPlayers;
       sActiveFilter.maxBots      = maxBots;
@@ -519,6 +538,7 @@ void queryMasterServer(U8 flags, const char* gameType, const char* missionType,
       sActiveFilter.type = ServerFilter::Buddy;
       sActiveFilter.buddyCount = buddyCount;
       sActiveFilter.buddyList = (U32*) dRealloc( sActiveFilter.buddyList, buddyCount * 4 );
+      sActiveFilter.queryFlags = ServerFilter::NewStyleResponse;
       dMemcpy( sActiveFilter.buddyList, buddyList, buddyCount * 4 );
       clearServerList();
    }
@@ -775,7 +795,7 @@ Vector<MasterInfo>* getMasterServerList()
          U32 region = 1; // needs to default to something > 0
          dSscanf(master,"%d:",&region);
          const char* madd = dStrchr(master,':') + 1;
-         if (region && Net::stringToAddress(madd,&address)) {
+         if (region && Net::stringToAddress(madd,&address) == Net::NoError) {
             masterList.increment();
             MasterInfo& info = masterList.last();
             info.address = address;
@@ -1171,10 +1191,13 @@ static void processMasterServerQuery( U32 session )
             // Send a request to the master server for the server list:
             BitStream *out = BitStream::getPacketStream();
             out->clearStringBuffer();
+
             out->write( U8( NetInterface::MasterServerListRequest ) );
+            
             out->write( U8( sActiveFilter.queryFlags) );
             out->write( ( gMasterServerPing.session << 16 ) | ( gMasterServerPing.key & 0xFFFF ) );
             out->write( U8( 255 ) );
+
             writeCString( out, sActiveFilter.gameType );
             writeCString( out, sActiveFilter.missionType );
             out->write( sActiveFilter.minPlayers );
@@ -1359,23 +1382,35 @@ static void processServerListPackets( U32 session )
          if ( !p.tryCount )
          {
             // Packet timed out :(
-            Con::printf( "Server list packet #%d timed out.", p.index + 1 );
+            Con::printf( "Server list packet #%d timed out.", p.getIndex() + 1 );
             gPacketStatusList.erase( i );
          }
          else
          {
             // Try again...
-            Con::printf( "Rerequesting server list packet #%d...", p.index + 1 );
+            Con::printf( "Rerequesting server list packet #%d...", p.getIndex() + 1 );
             p.tryCount--;
             p.time = currentTime;
             p.key = gKey++;
 
             BitStream *out = BitStream::getPacketStream();
+            bool extendedPacket = (sActiveFilter.queryFlags & ServerFilter::NewStyleResponse) != 0;
+
             out->clearStringBuffer();
-            out->write( U8( NetInterface::MasterServerListRequest ) );
+
+            if ( extendedPacket )
+               out->write( U8( NetInterface::MasterServerExtendedListRequest ) );
+            else
+               out->write( U8( NetInterface::MasterServerListRequest ) );
+
             out->write( U8( sActiveFilter.queryFlags ) );   // flags
             out->write( ( session << 16) | ( p.key & 0xFFFF ) );
-            out->write( p.index );  // packet index
+            
+            if ( extendedPacket )
+               out->write( p.getOldIndex() );  // packet index
+            else
+               out->write( p.getIndex() );  // packet index
+
             out->write( U8( 0 ) );  // game type
             out->write( U8( 0 ) );  // mission type
             out->write( U8( 0 ) );  // minPlayers
@@ -1569,6 +1604,98 @@ static void handleMasterServerListResponse( BitStream* stream, U32 key, U8 /*fla
 
 //-----------------------------------------------------------------------------
 
+static void handleExtendedMasterServerListResponse(BitStream* stream, U32 key, U8 /*flags*/)
+{
+   U16 packetIndex, packetTotal;
+   U32 i;
+   U16 serverCount, port;
+   U8 netNum[16];
+   char addressBuffer[256];
+   NetAddress addr;
+
+   stream->read(&packetIndex);
+   // Validate the packet key:
+   U32 packetKey = gMasterServerPing.key;
+   if (gGotFirstListPacket)
+   {
+      for (i = 0; i < gPacketStatusList.size(); i++)
+      {
+         if (gPacketStatusList[i].index == packetIndex)
+         {
+            packetKey = gPacketStatusList[i].key;
+            break;
+         }
+      }
+   }
+
+   U32 testKey = (gPingSession << 16) | (packetKey & 0xFFFF);
+   if (testKey != key)
+      return;
+
+   stream->read(&packetTotal);
+   stream->read(&serverCount);
+
+   Con::printf("Received server list packet %d of %d from the master server (%d servers).", (packetIndex + 1), packetTotal, serverCount);
+
+   // Enter all of the servers in this packet into the ping list:
+   for (i = 0; i < serverCount; i++)
+   {
+      U8 type;
+      stream->read(&type);
+      dMemset(&addr, '\0', sizeof(NetAddress));
+
+      if (type == 0)
+      {
+         // IPV4
+         addr.type = NetAddress::IPAddress;
+         stream->read(4, &addr.address.ipv4.netNum[0]);
+         stream->read(&addr.port);
+      }
+      else
+      {
+         // IPV6
+         addr.type = NetAddress::IPV6Address;
+         stream->read(16, &addr.address.ipv6.netNum[0]);
+         stream->read(&addr.port);
+      }
+
+      pushPingRequest(&addr);
+   }
+
+   // If this is the first list packet we have received, fill the packet status list
+   // and start processing:
+   if (!gGotFirstListPacket)
+   {
+      gGotFirstListPacket = true;
+      gMasterServerQueryAddress = gMasterServerPing.address;
+      U32 currentTime = Platform::getVirtualMilliseconds();
+      for (i = 0; i < packetTotal; i++)
+      {
+         if (i != packetIndex)
+         {
+            PacketStatus* p = new PacketStatus(i, gMasterServerPing.key, currentTime);
+            gPacketStatusList.push_back(*p);
+         }
+      }
+
+      processServerListPackets(gPingSession);
+   }
+   else
+   {
+      // Remove the packet we just received from the status list:
+      for (i = 0; i < gPacketStatusList.size(); i++)
+      {
+         if (gPacketStatusList[i].index == packetIndex)
+         {
+            gPacketStatusList.erase(i);
+            break;
+         }
+      }
+   }
+}
+
+//-----------------------------------------------------------------------------
+
 static void handleGameMasterInfoRequest( const NetAddress* address, U32 key, U8 flags )
 {
    if ( GNet->doesAllowConnections() )
@@ -1585,7 +1712,7 @@ static void handleGameMasterInfoRequest( const NetAddress* address, U32 key, U8
       for(U32 i = 0; i < masterList->size(); i++)
       {
          masterAddr = &(*masterList)[i].address;
-         if (*(U32*)(masterAddr->netNum) == *(U32*)(address->netNum))
+         if (masterAddr->isSameAddress(*address))
          {
             fromMaster = true;
             break;
@@ -2098,6 +2225,10 @@ void DemoNetInterface::handleInfoPacket( const NetAddress* address, U8 packetTyp
       case GameMasterInfoRequest:
          handleGameMasterInfoRequest( address, key, flags );
          break;
+
+      case MasterServerExtendedListResponse:
+         handleExtendedMasterServerListResponse(stream, key, flags);
+         break;
    }
 }
 

+ 16 - 16
Engine/source/app/net/tcpObject.cpp

@@ -170,8 +170,8 @@ IMPLEMENT_CALLBACK(TCPObject, onDisconnect, void, (),(),
 
 TCPObject *TCPObject::find(NetSocket tag)
 {
-   for(TCPObject *walk = table[U32(tag) & TableMask]; walk; walk = walk->mNext)
-      if(walk->mTag == tag)
+   for(TCPObject *walk = table[tag.getHash() & TableMask]; walk; walk = walk->mNext)
+      if(walk->mTag.getHash() == tag.getHash())
          return walk;
    return NULL;
 }
@@ -180,13 +180,13 @@ void TCPObject::addToTable(NetSocket newTag)
 {
    removeFromTable();
    mTag = newTag;
-   mNext = table[U32(mTag) & TableMask];
-   table[U32(mTag) & TableMask] = this;
+   mNext = table[mTag.getHash() & TableMask];
+   table[mTag.getHash() & TableMask] = this;
 }
 
 void TCPObject::removeFromTable()
 {
-   for(TCPObject **walk = &table[U32(mTag) & TableMask]; *walk; walk = &((*walk)->mNext))
+   for(TCPObject **walk = &table[mTag.getHash() & TableMask]; *walk; walk = &((*walk)->mNext))
    {
       if(*walk == this)
       {
@@ -207,7 +207,7 @@ TCPObject::TCPObject()
    mBuffer = NULL;
    mBufferSize = 0;
    mPort = 0;
-   mTag = InvalidSocket;
+   mTag = NetSocket::INVALID;
    mNext = NULL;
    mState = Disconnected;
 
@@ -215,9 +215,9 @@ TCPObject::TCPObject()
 
    if(gTCPCount == 1)
    {
-      Net::smConnectionAccept.notify(processConnectedAcceptEvent);
-      Net::smConnectionReceive.notify(processConnectedReceiveEvent);
-      Net::smConnectionNotify.notify(processConnectedNotifyEvent);
+      Net::getConnectionAcceptedEvent().notify(processConnectedAcceptEvent);
+      Net::getConnectionReceiveEvent().notify(processConnectedReceiveEvent);
+      Net::getConnectionNotifyEvent().notify(processConnectedNotifyEvent);
    }
 }
 
@@ -230,9 +230,9 @@ TCPObject::~TCPObject()
 
    if(gTCPCount == 0)
    {
-      Net::smConnectionAccept.remove(processConnectedAcceptEvent);
-      Net::smConnectionReceive.remove(processConnectedReceiveEvent);
-      Net::smConnectionNotify.remove(processConnectedNotifyEvent);
+      Net::getConnectionAcceptedEvent().remove(processConnectedAcceptEvent);
+      Net::getConnectionReceiveEvent().remove(processConnectedReceiveEvent);
+      Net::getConnectionNotifyEvent().remove(processConnectedNotifyEvent);
    }
 }
 
@@ -242,7 +242,7 @@ bool TCPObject::processArguments(S32 argc, ConsoleValueRef *argv)
       return true;
    else if(argc == 1)
    {
-      addToTable(U32(dAtoi(argv[0])));
+      addToTable(NetSocket::fromHandle(dAtoi(argv[0])));
       return true;
    }
    return false;
@@ -406,7 +406,7 @@ void TCPObject::onDisconnect()
 void TCPObject::listen(U16 port)
 {
    mState = Listening;
-   U32 newTag = Net::openListenPort(port);
+   NetSocket newTag = Net::openListenPort(port);
    addToTable(newTag);
 }
 
@@ -418,7 +418,7 @@ void TCPObject::connect(const char *address)
 
 void TCPObject::disconnect()
 {
-   if( mTag != InvalidSocket ) {
+   if( mTag != NetSocket::INVALID ) {
       Net::closeConnectTo(mTag);
    }
    removeFromTable();
@@ -592,7 +592,7 @@ void processConnectedAcceptEvent(NetSocket listeningPort, NetSocket newConnectio
    if(!tcpo)
       return;
 
-   tcpo->onConnectionRequest(&originatingAddress, newConnection);
+   tcpo->onConnectionRequest(&originatingAddress, (U32)newConnection.getHandle());
 }
 
 void processConnectedNotifyEvent( NetSocket sock, U32 state )

+ 18 - 13
Engine/source/console/telnetConsole.cpp

@@ -84,7 +84,7 @@ TelnetConsole::TelnetConsole()
 {
    Con::addConsumer(telnetCallback);
 
-   mAcceptSocket = InvalidSocket;
+   mAcceptSocket = NetSocket::INVALID;
    mAcceptPort = -1;
    mClientList = NULL;
    mRemoteEchoEnabled = false;
@@ -93,13 +93,13 @@ TelnetConsole::TelnetConsole()
 TelnetConsole::~TelnetConsole()
 {
    Con::removeConsumer(telnetCallback);
-   if(mAcceptSocket != InvalidSocket)
+   if(mAcceptSocket != NetSocket::INVALID)
       Net::closeSocket(mAcceptSocket);
    TelnetClient *walk = mClientList, *temp;
    while(walk)
    {
       temp = walk->nextClient;
-      if(walk->socket != InvalidSocket)
+      if(walk->socket != NetSocket::INVALID)
          Net::closeSocket(walk->socket);
       delete walk;
       walk = temp;
@@ -113,16 +113,20 @@ void TelnetConsole::setTelnetParameters(S32 port, const char *telnetPassword, co
 
    mRemoteEchoEnabled = remoteEcho;
 
-   if(mAcceptSocket != InvalidSocket)
+   if(mAcceptSocket != NetSocket::INVALID)
    {
       Net::closeSocket(mAcceptSocket);
-      mAcceptSocket = InvalidSocket;
+      mAcceptSocket = NetSocket::INVALID;
    }
    mAcceptPort = port;
    if(mAcceptPort != -1 && mAcceptPort != 0)
    {
+	  NetAddress address;
+	  Net::getIdealListenAddress(&address);
+	  address.port = mAcceptPort;
+
       mAcceptSocket = Net::openSocket();
-      Net::bind(mAcceptSocket, mAcceptPort);
+      Net::bindAddress(address, mAcceptSocket);
       Net::listen(mAcceptSocket, 4);
 
       Net::setBlocking(mAcceptSocket, false);
@@ -151,16 +155,17 @@ void TelnetConsole::process()
 {
    NetAddress address;
 
-   if(mAcceptSocket != InvalidSocket)
+   if(mAcceptSocket != NetSocket::INVALID)
    {
       // ok, see if we have any new connections:
       NetSocket newConnection;
       newConnection = Net::accept(mAcceptSocket, &address);
 
-      if(newConnection != InvalidSocket)
+      if(newConnection != NetSocket::INVALID)
       {
-   		Con::printf ("Telnet connection from %i.%i.%i.%i",
-   				address.netNum[0], address.netNum[1], address.netNum[2], address.netNum[3]);
+         char buffer[256];
+         Net::addressToString(&address, buffer);
+         Con::printf("Telnet connection from %s", buffer);
 
          TelnetClient *cl = new TelnetClient;
          cl->socket = newConnection;
@@ -201,7 +206,7 @@ void TelnetConsole::process()
       if((err != Net::NoError && err != Net::WouldBlock) || numBytes == 0)
       {
          Net::closeSocket(client->socket);
-         client->socket = InvalidSocket;
+         client->socket = NetSocket::INVALID;
          continue;
       }
 
@@ -274,7 +279,7 @@ void TelnetConsole::process()
                   if(client->state == DisconnectThisDude)
                   {
                      Net::closeSocket(client->socket);
-                     client->socket = InvalidSocket;
+                     client->socket = NetSocket::INVALID;
                   }
                }
             }
@@ -312,7 +317,7 @@ void TelnetConsole::process()
    TelnetClient *cl;
    while((cl = *walk) != NULL)
    {
-      if(cl->socket == InvalidSocket)
+      if(cl->socket == NetSocket::INVALID)
       {
          *walk = cl->nextClient;
          delete cl;

+ 22 - 17
Engine/source/console/telnetDebugger.cpp

@@ -151,8 +151,8 @@ TelnetDebugger::TelnetDebugger()
    Con::addConsumer(debuggerConsumer);
 
    mAcceptPort = -1;
-   mAcceptSocket = InvalidSocket;
-   mDebugSocket = InvalidSocket;
+   mAcceptSocket = NetSocket::INVALID;
+   mDebugSocket = NetSocket::INVALID;
 
    mState = NotConnected;
    mCurPos = 0;
@@ -189,9 +189,9 @@ TelnetDebugger::~TelnetDebugger()
 {
    Con::removeConsumer(debuggerConsumer);
 
-   if(mAcceptSocket != InvalidSocket)
+   if(mAcceptSocket != NetSocket::INVALID)
       Net::closeSocket(mAcceptSocket);
-   if(mDebugSocket != InvalidSocket)
+   if(mDebugSocket != NetSocket::INVALID)
       Net::closeSocket(mDebugSocket);
 }
 
@@ -217,10 +217,10 @@ void TelnetDebugger::send(const char *str)
 
 void TelnetDebugger::disconnect()
 {
-   if ( mDebugSocket != InvalidSocket )
+   if ( mDebugSocket != NetSocket::INVALID )
    {
       Net::closeSocket(mDebugSocket);
-      mDebugSocket = InvalidSocket;
+      mDebugSocket = NetSocket::INVALID;
    }
 
    removeAllBreakpoints();
@@ -236,16 +236,20 @@ void TelnetDebugger::setDebugParameters(S32 port, const char *password, bool wai
 //   if(port == mAcceptPort)
 //      return;
 
-   if(mAcceptSocket != InvalidSocket)
+   if(mAcceptSocket != NetSocket::INVALID)
    {
       Net::closeSocket(mAcceptSocket);
-      mAcceptSocket = InvalidSocket;
+      mAcceptSocket = NetSocket::INVALID;
    }
    mAcceptPort = port;
    if(mAcceptPort != -1 && mAcceptPort != 0)
    {
+	  NetAddress address;
+	  Net::getIdealListenAddress(&address);
+	  address.port = mAcceptPort;
+
       mAcceptSocket = Net::openSocket();
-      Net::bind(mAcceptSocket, mAcceptPort);
+      Net::bindAddress(address, mAcceptSocket);
       Net::listen(mAcceptSocket, 4);
 
       Net::setBlocking(mAcceptSocket, false);
@@ -279,32 +283,33 @@ void TelnetDebugger::process()
 {
    NetAddress address;
 
-   if(mAcceptSocket != InvalidSocket)
+   if(mAcceptSocket != NetSocket::INVALID)
    {
       // ok, see if we have any new connections:
       NetSocket newConnection;
       newConnection = Net::accept(mAcceptSocket, &address);
 
-      if(newConnection != InvalidSocket && mDebugSocket == InvalidSocket)
+      if(newConnection != NetSocket::INVALID && mDebugSocket == NetSocket::INVALID)
       {
-   		Con::printf ("Debugger connection from %i.%i.%i.%i",
-   				address.netNum[0], address.netNum[1], address.netNum[2], address.netNum[3]);
+         char buffer[256];
+         Net::addressToString(&address, buffer);
+         Con::printf("Debugger connection from %s", buffer);
 
          mState = PasswordTry;
          mDebugSocket = newConnection;
 
          Net::setBlocking(newConnection, false);
       }
-      else if(newConnection != InvalidSocket)
+      else if(newConnection != NetSocket::INVALID)
          Net::closeSocket(newConnection);
    }
    // see if we have any input to process...
 
-   if(mDebugSocket == InvalidSocket)
+   if(mDebugSocket == NetSocket::INVALID)
       return;
 
    checkDebugRecv();
-   if(mDebugSocket == InvalidSocket)
+   if(mDebugSocket == NetSocket::INVALID)
       removeAllBreakpoints();
 }
 
@@ -434,7 +439,7 @@ void TelnetDebugger::breakProcess()
    {
       Platform::sleep(10);
       checkDebugRecv();
-      if(mDebugSocket == InvalidSocket)
+      if(mDebugSocket == NetSocket::INVALID)
       {
          mProgramPaused = false;
          removeAllBreakpoints();

+ 15 - 20
Engine/source/core/stream/stream.cpp

@@ -300,16 +300,7 @@ bool Stream::write(const NetAddress &na)
 {
    bool success = write(na.type);
    success &= write(na.port);
-   success &= write(na.netNum[0]);
-   success &= write(na.netNum[1]);
-   success &= write(na.netNum[2]);
-   success &= write(na.netNum[3]);
-   success &= write(na.nodeNum[0]);
-   success &= write(na.nodeNum[1]);
-   success &= write(na.nodeNum[2]);
-   success &= write(na.nodeNum[3]);
-   success &= write(na.nodeNum[4]);
-   success &= write(na.nodeNum[5]);
+   success &= write(sizeof(na.address), &na.address);
    return success;
 }
 
@@ -317,16 +308,20 @@ bool Stream::read(NetAddress *na)
 {
    bool success = read(&na->type);
    success &= read(&na->port);
-   success &= read(&na->netNum[0]);
-   success &= read(&na->netNum[1]);
-   success &= read(&na->netNum[2]);
-   success &= read(&na->netNum[3]);
-   success &= read(&na->nodeNum[0]);
-   success &= read(&na->nodeNum[1]);
-   success &= read(&na->nodeNum[2]);
-   success &= read(&na->nodeNum[3]);
-   success &= read(&na->nodeNum[4]);
-   success &= read(&na->nodeNum[5]);
+   success &= read(sizeof(na->address), &na->address);
+   return success;
+}
+
+bool Stream::write(const NetSocket &so)
+{
+   return write(so.getHandle());
+}
+
+bool Stream::read(NetSocket* so)
+{
+   S32 handle = -1;
+   bool success = read(&handle);
+   *so = NetSocket::fromHandle(handle);
    return success;
 }
 

+ 6 - 0
Engine/source/core/stream/stream.h

@@ -45,6 +45,7 @@ class ColorF;
 struct NetAddress;
 class RawData;
 class String;
+class NetSocket;
 
 namespace Torque {
    class ByteBuffer;
@@ -165,6 +166,11 @@ public:
    /// Read a network address from the stream.
    bool read(NetAddress*);
 
+   /// Write a network socket to the stream.
+   bool write(const NetSocket &);
+   /// Read a network socket from the stream.
+   bool read(NetSocket*);
+
    /// Write some raw data onto the stream.
    bool write(const RawData &);
    /// Read some raw data from the stream.

文件差异内容过多而无法显示
+ 713 - 194
Engine/source/platform/platformNet.cpp


+ 148 - 23
Engine/source/platform/platformNet.h

@@ -31,6 +31,8 @@
 #define MAXPACKETSIZE 1500
 #endif
 
+#define TORQUE_NET_DEFAULT_MULTICAST_ADDRESS "ff04::7467::656E::6574::776B"
+
 typedef S32 NetConnectionId;
 
 /// Generic network address
@@ -41,18 +43,130 @@ struct NetAddress
    S32 type;        ///< Type of address (IPAddress currently)
 
    /// Acceptable NetAddress types.
-   enum 
+   enum Type
    {
       IPAddress,
+      IPV6Address,
+
+      IPBroadcastAddress,
+      IPV6MulticastAddress
    };
 
-   U8 netNum[4];    ///< For IP:  sin_addr<br>
-   U8 nodeNum[6];   ///< For IP:  Not used.<br>
-   U16  port;       ///< For IP:  sin_port<br>
+   union
+   {
+      struct {
+         U8 netNum[4];
+      } ipv4;
+
+      struct {
+         U8 netNum[16];
+         U32 netFlow;
+         U32 netScope;
+      } ipv6;
+
+      struct {
+         U8 netNum[16];
+         U8 netFlow[4];
+         U8 netScope[4];
+      } ipv6_raw;
+
+   } address;
+
+   U16 port;
+
+   bool isSameAddress(const NetAddress &other) const
+   {
+	   if (type != other.type)
+		   return false;
+
+      switch (type)
+      {
+      case NetAddress::IPAddress:
+         return (dMemcmp(other.address.ipv4.netNum, address.ipv4.netNum, 4) == 0);
+         break;
+      case NetAddress::IPV6Address:
+         return (dMemcmp(other.address.ipv6.netNum, address.ipv6.netNum, 16) == 0);
+         break;
+      case NetAddress::IPBroadcastAddress:
+         return true;
+         break;
+      case NetAddress::IPV6MulticastAddress:
+         return true;
+         break;
+      }
+
+      return false;
+   }
+
+   bool isSameAddressAndPort(const NetAddress &other) const
+   {
+	   if (type != other.type)
+		   return false;
+
+	   switch (type)
+	   {
+	   case NetAddress::IPAddress:
+		   return (dMemcmp(other.address.ipv4.netNum, address.ipv4.netNum, 4) == 0) && other.port == port;
+		   break;
+	   case NetAddress::IPV6Address:
+		   return (dMemcmp(other.address.ipv6.netNum, address.ipv6.netNum, 16) == 0) && other.port == port;
+		   break;
+	   case NetAddress::IPBroadcastAddress:
+		   return true;
+		   break;
+	   case NetAddress::IPV6MulticastAddress:
+		   return true;
+		   break;
+	   }
+
+	   return false;
+   }
+
+   bool isEqual(const NetAddress &other) const
+   {
+	   if (type != other.type)
+		   return false;
+
+      switch (type)
+      {
+      case NetAddress::IPAddress:
+         return other.port == port && (dMemcmp(other.address.ipv4.netNum, address.ipv4.netNum, 4) == 0);
+         break;
+      case NetAddress::IPV6Address:
+         return other.port == port && other.address.ipv6.netFlow == address.ipv6.netFlow && other.address.ipv6.netScope == address.ipv6.netScope && (dMemcmp(other.address.ipv6.netNum, address.ipv6.netNum, 16) == 0);
+         break;
+      case NetAddress::IPBroadcastAddress:
+         return other.port == port;
+         break;
+      case NetAddress::IPV6MulticastAddress:
+         return other.port == port;
+         break;
+      }
+
+      return false;
+   }
+
+   U32 getHash() const;
 };
 
-typedef S32 NetSocket;
-const NetSocket InvalidSocket = -1;
+class NetSocket
+{
+protected:
+   S32 mHandle;
+
+public:
+   NetSocket() : mHandle(-1) { ; }
+
+   inline void setHandle(S32 handleId) { mHandle = handleId; }
+   inline S32 getHandle() const { return mHandle;  }
+   inline U32 getHash() const { return mHandle; }
+
+   bool operator==(const NetSocket &other) const { return mHandle == other.mHandle; }
+   bool operator!=(const NetSocket &other) const { return mHandle != other.mHandle; }
+
+   static NetSocket fromHandle(S32 handleId) { NetSocket ret; ret.mHandle = handleId; return ret; }
+   static NetSocket INVALID;
+};
 
 /// void event(NetSocket sock, U32 state) 
 typedef JournaledSignal<void(NetSocket,U32)> ConnectionNotifyEvent;
@@ -76,7 +190,8 @@ struct Net
       InvalidPacketProtocol,
       WouldBlock,
       NotASocket,
-      UnknownError
+      UnknownError,
+	  NeedHostLookup
    };
 
    enum ConnectionState {
@@ -87,18 +202,16 @@ struct Net
       Disconnected
    };
 
-   enum Protocol
-   {
-      UDPProtocol,
-      TCPProtocol
-   };
-
    static const S32 MaxPacketDataSize = MAXPACKETSIZE;
 
-   static ConnectionNotifyEvent   smConnectionNotify;
-   static ConnectionAcceptedEvent smConnectionAccept;
-   static ConnectionReceiveEvent  smConnectionReceive;
-   static PacketReceiveEvent      smPacketReceive;
+   static ConnectionNotifyEvent&   getConnectionNotifyEvent();
+   static ConnectionAcceptedEvent& getConnectionAcceptedEvent();
+   static ConnectionReceiveEvent&  getConnectionReceiveEvent();
+   static PacketReceiveEvent&      getPacketReceiveEvent();
+
+   static bool smMulticastEnabled;
+   static bool smIpv4Enabled;
+   static bool smIpv6Enabled;
 
    static bool init();
    static void shutdown();
@@ -116,35 +229,47 @@ struct Net
 
    // Reliable net functions (TCP)
    // all incoming messages come in on the Connected* events
-   static NetSocket openListenPort(U16 port);
+   static NetSocket openListenPort(U16 port, NetAddress::Type = NetAddress::IPAddress);
    static NetSocket openConnectTo(const char *stringAddress); // does the DNS resolve etc.
    static void closeConnectTo(NetSocket socket);
-   static Error sendtoSocket(NetSocket socket, const U8 *buffer, S32 bufferSize);
+   static Error sendtoSocket(NetSocket socket, const U8 *buffer, S32 bufferSize, S32 *bytesWritten=NULL);
 
    static bool compareAddresses(const NetAddress *a1, const NetAddress *a2);
-   static bool stringToAddress(const char *addressString, NetAddress *address);
+   static Net::Error stringToAddress(const char *addressString, NetAddress *address, bool hostLookup=true, int family=0);
    static void addressToString(const NetAddress *address, char addressString[256]);
 
    // lower level socked based network functions
    static NetSocket openSocket();
    static Error closeSocket(NetSocket socket);
 
-   static Error send(NetSocket socket, const U8 *buffer, S32 bufferSize);
+   static Error send(NetSocket socket, const U8 *buffer, S32 bufferSize, S32 *outBytesWritten=NULL);
    static Error recv(NetSocket socket, U8 *buffer, S32 bufferSize, S32 *bytesRead);
 
    static Error connect(NetSocket socket, const NetAddress *address);
    static Error listen(NetSocket socket, S32 maxConcurrentListens);
    static NetSocket accept(NetSocket acceptSocket, NetAddress *remoteAddress);
 
-   static Error bind(NetSocket socket, U16 port);
+   static Error bindAddress(const NetAddress &address, NetSocket socket, bool useUDP=false);
    static Error setBufferSize(NetSocket socket, S32 bufferSize);
    static Error setBroadcast(NetSocket socket, bool broadcastEnable);
    static Error setBlocking(NetSocket socket, bool blockingIO);
 
+   /// Gets the desired default listen address for a specified address type
+   static Net::Error getListenAddress(const NetAddress::Type type, NetAddress *address, bool forceDefaults=false);
+   static void getIdealListenAddress(NetAddress *address);
+
+   // Multicast for ipv6 local net browsing
+   static void enableMulticast();
+   static void disableMulticast();
+   static bool isMulticastEnabled();
+
+   // Protocol state
+   static bool isAddressTypeAvailable(NetAddress::Type addressType);
 
 private:
    static void process();
+   static void processListenSocket(NetSocket socket);
 
 };
 
-#endif
+#endif

+ 9 - 6
Engine/source/platform/platformNetAsync.cpp

@@ -53,7 +53,7 @@ struct NetAsync::NameLookupRequest
 
       NameLookupRequest()
       {
-         sock = InvalidSocket;
+         sock = NetSocket::INVALID;
          remoteAddr[0] = 0;
          out_h_addr[0] = 0;
          out_h_length = -1;
@@ -81,9 +81,12 @@ protected:
    virtual void execute()
    {
 #ifndef TORQUE_OS_XENON
+
+	  NetAddress address;
+	  Net::Error error = Net::stringToAddress(mRequest.remoteAddr, &address, true);
+
       // do it
-      struct hostent* hostent = gethostbyname(mRequest.remoteAddr);
-      if (hostent == NULL)
+      if (error != Net::NoError)
       {
          // oh well!  leave the lookup data unmodified (h_length) should
          // still be -1 from initialization
@@ -94,9 +97,9 @@ protected:
          // copy the stuff we need from the hostent 
          dMemset(mRequest.out_h_addr, 0, 
             sizeof(mRequest.out_h_addr));
-         dMemcpy(mRequest.out_h_addr, hostent->h_addr, hostent->h_length);
+         dMemcpy(mRequest.out_h_addr, &address, sizeof(address));
 
-         mRequest.out_h_length = hostent->h_length;
+		 mRequest.out_h_length = sizeof(address);
          mRequest.complete = true;
       }
 #else
@@ -159,7 +162,7 @@ void NetAsync::queueLookup(const char* remoteAddr, NetSocket socket)
    ThreadPool::GLOBAL().queueWorkItem( workItem );
 }
 
-bool NetAsync::checkLookup(NetSocket socket, char* out_h_addr, 
+bool NetAsync::checkLookup(NetSocket socket, void* out_h_addr, 
                            S32* out_h_length, S32 out_h_addr_size)
 {
    bool found = false;

+ 1 - 1
Engine/source/platform/platformNetAsync.h

@@ -54,7 +54,7 @@ class NetAsync
       // out_h_length will be set appropriately.  if out_h_length is -1, then
       // name could not be resolved.  otherwise, it provides the number of
       // address bytes copied into out_h_addr.
-      bool checkLookup(NetSocket socket, char* out_h_addr, int* out_h_length, S32 out_h_addr_size);
+      bool checkLookup(NetSocket socket, void* out_h_addr, int* out_h_length, S32 out_h_addr_size);
 };
 
 // the global net async object

+ 5 - 5
Engine/source/platform/test/netTest.cpp

@@ -52,7 +52,7 @@ struct TcpHandle
       else
       {
          Process::requestShutdown();
-         mSocket = NULL;
+         mSocket = NetSocket::INVALID;
          ASSERT_EQ(Net::Disconnected, state)
             << "Ended with a network error!";
       }
@@ -72,7 +72,7 @@ TEST(Net, TCPRequest)
 {
    TcpHandle handler;
 
-   handler.mSocket = InvalidSocket;
+   handler.mSocket = NetSocket::INVALID;
    handler.mDataReceived = 0;
 
    // Hook into the signals.
@@ -119,7 +119,7 @@ struct JournalHandle
       else
       {
          Process::requestShutdown();
-         mSocket = NULL;
+         mSocket = NetSocket::INVALID;
          ASSERT_EQ(Net::Disconnected, state)
             << "Ended with a network error!";
       }
@@ -135,7 +135,7 @@ struct JournalHandle
 
    void makeRequest()
    {
-      mSocket = InvalidSocket;
+      mSocket = NetSocket::INVALID;
       mDataReceived = 0;
 
       // Hook into the signals.
@@ -175,4 +175,4 @@ TEST(Net, JournalTCPRequest)
       << "Didn't get same data back from journal playback.";
 }
 
-#endif
+#endif

+ 2 - 2
Engine/source/sim/netConnection.cpp

@@ -157,7 +157,7 @@ bool NetConnection::mFilesWereDownloaded = false;
 
 static inline U32 HashNetAddress(const NetAddress *addr)
 {
-   return *((U32 *)addr->netNum) % NetConnection::HashTableSize;
+   return addr->getHash() % NetConnection::HashTableSize;
 }
 
 NetConnection *NetConnection::lookup(const NetAddress *addr)
@@ -1421,7 +1421,7 @@ DefineEngineMethod( NetConnection, connect, void, (const char* remoteAddress),,
    )
 {
    NetAddress addr;
-   if(!Net::stringToAddress(remoteAddress, &addr))
+   if (Net::stringToAddress(remoteAddress, &addr) != Net::NoError)
    {
       Con::errorf("NetConnection::connect: invalid address - %s", remoteAddress);
       return;

+ 3 - 6
Engine/source/sim/netInterface.cpp

@@ -41,7 +41,7 @@ NetInterface::NetInterface()
    GNet = this;
 
    mLastTimeoutCheckTime = 0;
-   mAllowConnections = true;
+   mAllowConnections = false;
 
 }
 
@@ -109,7 +109,7 @@ void NetInterface::processPacketReceiveEvent(NetAddress srcAddress, RawData pack
       pStream.read(&packetType);
       NetAddress *addr = &srcAddress;
 
-      if(packetType <= GameHeartbeat)
+      if(packetType <= GameHeartbeat || packetType == MasterServerExtendedListResponse)
          handleInfoPacket(addr, packetType, &pStream);
 #ifdef GGC_PLUGIN
       else if (packetType == GGCPacket)
@@ -556,10 +556,7 @@ void NetInterface::computeNetMD5(const NetAddress *address, U32 connectSequence,
 
    U32 in[16];
    in[0] = address->type;
-   in[1] = (U32(address->netNum[0]) << 24) |
-           (U32(address->netNum[1]) << 16) |
-           (U32(address->netNum[2]) << 8)  |
-           (U32(address->netNum[3]));
+   in[1] = address->getHash();
    in[2] = address->port;
    in[3] = connectSequence;
    for(U32 i = 0; i < 12; i++)

+ 4 - 1
Engine/source/sim/netInterface.h

@@ -46,7 +46,7 @@ public:
       GameInfoRequest               = 18,
       GameInfoResponse              = 20,
       GameHeartbeat                 = 22,
-	  GGCPacket                     = 24,
+      GGCPacket                     = 24,
       ConnectChallengeRequest       = 26,
       ConnectChallengeReject        = 28,
       ConnectChallengeResponse      = 30,
@@ -54,6 +54,9 @@ public:
       ConnectReject                 = 34,
       ConnectAccept                 = 36,
       Disconnect                    = 38,
+      MasterServerExtendedListResponse = 40,
+      MasterServerChallenge            = 42,
+      MasterServerExtendedListRequest  = 44,
    };
 protected:
 

+ 1 - 1
Templates/Empty/buildFiles/config/torque3D_dedicated.conf

@@ -81,7 +81,7 @@
         addProjectLibInput('ADVAPI32.LIB');
         addProjectLibInput('GDI32.LIB');
         addProjectLibInput('WINMM.LIB');
-        addProjectLibInput('WSOCK32.LIB');
+        addProjectLibInput('WS2_32.LIB.LIB');
         addProjectLibInput('vfw32.lib');
         addProjectLibInput('Imm32.lib');
         addProjectLibInput('d3d9.lib');

+ 1 - 1
Templates/Full/buildFiles/config/torque3D_dedicated.conf

@@ -81,7 +81,7 @@
         addProjectLibInput('ADVAPI32.LIB');
         addProjectLibInput('GDI32.LIB');
         addProjectLibInput('WINMM.LIB');
-        addProjectLibInput('WSOCK32.LIB');
+        addProjectLibInput('WS2_32.LIB');
         addProjectLibInput('vfw32.lib');
         addProjectLibInput('Imm32.lib');
         addProjectLibInput('d3d9.lib');

+ 2 - 0
Templates/Full/source/torqueConfig.h

@@ -34,6 +34,8 @@
 /// What's the name of your application? Used in a variety of places.
 #define TORQUE_APP_NAME            "Full"
 
+#define TORQUE_NET_DEFAULT_MULTICAST_ADDRESS "ff04::7467:656E:6574:776B"
+
 /// What version of the application specific source code is this?
 ///
 /// Version number is major * 1000 + minor * 100 + revision * 10.

+ 1 - 1
Tools/CMake/torque3d.cmake

@@ -616,7 +616,7 @@ endif()
 
 if(WIN32)
     # copy pasted from T3D build system, some might not be needed
-    set(TORQUE_EXTERNAL_LIBS "COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;d3d9.lib;d3dx9.lib;DxErr.lib;ole32.lib;shell32.lib;oleaut32.lib;version.lib" CACHE STRING "external libs to link against")
+    set(TORQUE_EXTERNAL_LIBS "COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WS2_32.LIB;vfw32.lib;Imm32.lib;d3d9.lib;d3dx9.lib;DxErr.lib;ole32.lib;shell32.lib;oleaut32.lib;version.lib" CACHE STRING "external libs to link against")
     mark_as_advanced(TORQUE_EXTERNAL_LIBS)
     addLib("${TORQUE_EXTERNAL_LIBS}")
 

+ 1 - 1
Tools/projectGenerator/classes/NPWebPlugin.php

@@ -118,7 +118,7 @@ class NPWebPlugin
       addProjectLibInput('ADVAPI32.LIB');
       addProjectLibInput('GDI32.LIB');
       addProjectLibInput('WINMM.LIB');
-      addProjectLibInput('WSOCK32.LIB');
+      addProjectLibInput('WS2_32.LIB');
       addProjectLibInput('vfw32.lib');
       addProjectLibInput('Imm32.lib');
       addProjectLibInput('UnicoWS.lib');

+ 1 - 1
Tools/projectGenerator/classes/Torque3D.php

@@ -173,7 +173,7 @@ class Torque3D
             addProjectLibInput('ADVAPI32.LIB');
             addProjectLibInput('GDI32.LIB');
             addProjectLibInput('WINMM.LIB');
-            addProjectLibInput('WSOCK32.LIB');
+            addProjectLibInput('WS2_32.LIB');
             addProjectLibInput('vfw32.lib');
             addProjectLibInput('Imm32.lib');
             addProjectLibInput('d3d9.lib');

+ 1 - 1
Tools/projectGenerator/libs/Torque3D.conf

@@ -183,7 +183,7 @@ else
         addProjectLibInput('ADVAPI32.LIB');
         addProjectLibInput('GDI32.LIB');
         addProjectLibInput('WINMM.LIB');
-        addProjectLibInput('WSOCK32.LIB');
+        addProjectLibInput('WS2_32.LIB');
         addProjectLibInput('vfw32.lib');
         addProjectLibInput('Imm32.lib');
         addProjectLibInput('d3d9.lib');

部分文件因为文件数量过多而无法显示