Merge pull request #1817 from jamesu/ipv6_pr

Preliminary IPV6 Support
This commit is contained in:
Areloch 2016-12-04 16:22:42 -06:00 committed by GitHub
commit a3740719b1
23 changed files with 1852 additions and 620 deletions

View file

@ -162,6 +162,13 @@ DefineConsoleFunction( setNetPort, bool, (int port, bool bind), (true), "(int po
return Net::openPort((S32)port, bind); 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, (), , "()" DefineConsoleFunction( closeNetPort, void, (), , "()"
"@brief Closes the current network port\n\n" "@brief Closes the current network port\n\n"
"@ingroup Networking") "@ingroup Networking")

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -31,6 +31,8 @@
#define MAXPACKETSIZE 1500 #define MAXPACKETSIZE 1500
#endif #endif
#define TORQUE_NET_DEFAULT_MULTICAST_ADDRESS "ff04::7467::656E::6574::776B"
typedef S32 NetConnectionId; typedef S32 NetConnectionId;
/// Generic network address /// Generic network address
@ -41,18 +43,130 @@ struct NetAddress
S32 type; ///< Type of address (IPAddress currently) S32 type; ///< Type of address (IPAddress currently)
/// Acceptable NetAddress types. /// Acceptable NetAddress types.
enum enum Type
{ {
IPAddress, IPAddress,
IPV6Address,
IPBroadcastAddress,
IPV6MulticastAddress
}; };
U8 netNum[4]; ///< For IP: sin_addr<br> union
U8 nodeNum[6]; ///< For IP: Not used.<br> {
U16 port; ///< For IP: sin_port<br> 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; class NetSocket
const NetSocket InvalidSocket = -1; {
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) /// void event(NetSocket sock, U32 state)
typedef JournaledSignal<void(NetSocket,U32)> ConnectionNotifyEvent; typedef JournaledSignal<void(NetSocket,U32)> ConnectionNotifyEvent;
@ -76,7 +190,8 @@ struct Net
InvalidPacketProtocol, InvalidPacketProtocol,
WouldBlock, WouldBlock,
NotASocket, NotASocket,
UnknownError UnknownError,
NeedHostLookup
}; };
enum ConnectionState { enum ConnectionState {
@ -87,18 +202,16 @@ struct Net
Disconnected Disconnected
}; };
enum Protocol
{
UDPProtocol,
TCPProtocol
};
static const S32 MaxPacketDataSize = MAXPACKETSIZE; static const S32 MaxPacketDataSize = MAXPACKETSIZE;
static ConnectionNotifyEvent smConnectionNotify; static ConnectionNotifyEvent& getConnectionNotifyEvent();
static ConnectionAcceptedEvent smConnectionAccept; static ConnectionAcceptedEvent& getConnectionAcceptedEvent();
static ConnectionReceiveEvent smConnectionReceive; static ConnectionReceiveEvent& getConnectionReceiveEvent();
static PacketReceiveEvent smPacketReceive; static PacketReceiveEvent& getPacketReceiveEvent();
static bool smMulticastEnabled;
static bool smIpv4Enabled;
static bool smIpv6Enabled;
static bool init(); static bool init();
static void shutdown(); static void shutdown();
@ -116,35 +229,47 @@ struct Net
// Reliable net functions (TCP) // Reliable net functions (TCP)
// all incoming messages come in on the Connected* events // 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 NetSocket openConnectTo(const char *stringAddress); // does the DNS resolve etc.
static void closeConnectTo(NetSocket socket); 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 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]); static void addressToString(const NetAddress *address, char addressString[256]);
// lower level socked based network functions // lower level socked based network functions
static NetSocket openSocket(); static NetSocket openSocket();
static Error closeSocket(NetSocket socket); 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 recv(NetSocket socket, U8 *buffer, S32 bufferSize, S32 *bytesRead);
static Error connect(NetSocket socket, const NetAddress *address); static Error connect(NetSocket socket, const NetAddress *address);
static Error listen(NetSocket socket, S32 maxConcurrentListens); static Error listen(NetSocket socket, S32 maxConcurrentListens);
static NetSocket accept(NetSocket acceptSocket, NetAddress *remoteAddress); 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 setBufferSize(NetSocket socket, S32 bufferSize);
static Error setBroadcast(NetSocket socket, bool broadcastEnable); static Error setBroadcast(NetSocket socket, bool broadcastEnable);
static Error setBlocking(NetSocket socket, bool blockingIO); 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: private:
static void process(); static void process();
static void processListenSocket(NetSocket socket);
}; };
#endif #endif

View file

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

View file

@ -54,7 +54,7 @@ class NetAsync
// out_h_length will be set appropriately. if out_h_length is -1, then // 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 // name could not be resolved. otherwise, it provides the number of
// address bytes copied into out_h_addr. // 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 // the global net async object

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -34,6 +34,8 @@
/// What's the name of your application? Used in a variety of places. /// What's the name of your application? Used in a variety of places.
#define TORQUE_APP_NAME "Full" #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? /// What version of the application specific source code is this?
/// ///
/// Version number is major * 1000 + minor * 100 + revision * 10. /// Version number is major * 1000 + minor * 100 + revision * 10.

View file

@ -616,7 +616,7 @@ endif()
if(WIN32) if(WIN32)
# copy pasted from T3D build system, some might not be needed # 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) mark_as_advanced(TORQUE_EXTERNAL_LIBS)
addLib("${TORQUE_EXTERNAL_LIBS}") addLib("${TORQUE_EXTERNAL_LIBS}")

View file

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

View file

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

View file

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