NetRetCode NetSocketListener::Bind() { if (int(m_sockfd) >= 0) return NetOk; if ((m_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { return NetFailed; } // We are starting the binding process (should really get this atomically) // The whole point of m_binding and m_listening are flags which can be set // from another thread to help the socket close down gracefully. m_binding = true; // Set up the server address NetIpAddress servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(m_port); // Bind socket to port int bindAttempts = 0; while ((bind(m_sockfd, (sockaddr *)&servaddr, sizeof(servaddr)) == -1) && m_binding) { if ((bindAttempts++ == 5) || (!NetIsAddrInUse)) { m_binding = false; return NetFailed; } else { AppDebugOut("NETLIB: Failed to bind to port %d\n", m_port); NetSleep(bindAttempts * 100); } } // If port was 0, let's see what the system assigned if (m_port == 0) { NetSocketLenType addr_len = sizeof(servaddr); if (getsockname(m_sockfd, (sockaddr *)&servaddr, &addr_len) == -1) { AppDebugOut("NETLIB: Failed to get system assigned port number\n"); return NetFailed; } m_port = ntohs(servaddr.sin_port); } if (m_binding) { m_binding = false; return NetOk; } else return NetFailed; }
void NetSocketListener::StopListening() { m_listening = false; m_binding = false; NetSleep(250); if (int(m_sockfd) >= 0) { shutdown(m_sockfd, 0); } NetCloseSocket(m_sockfd); }
static NetCallBackRetType AuthenticationThread(void *ignored) { #ifdef WAN_PLAY_ENABLED // // Every few seconds request the next key to be authenticated while( true ) { NetSleep( PERIOD_AUTHENTICATION_RETRY ); if( MetaServer_IsConnected() ) { char unknownKey[256]; char clientIp[256]; int keyId = -1; bool unknownKeyFound = false; // // Look for a key that isnt yet authenticated s_authResultsMutex.Lock(); for( int i = 0; i < s_authResults.Size(); ++i ) { AuthenticationResult *authResult = s_authResults[i]; if( authResult->m_authResult == AuthenticationUnknown && authResult->m_numTries < 5 ) { strcpy( unknownKey, authResult->m_authKey ); strcpy( clientIp, authResult->m_ip ); keyId = authResult->m_keyId; authResult->m_numTries++; unknownKeyFound = true; break; } } s_authResultsMutex.Unlock(); // // Check the key out if( unknownKeyFound ) { int basicResult = Authentication_SimpleKeyCheck(unknownKey); if( basicResult < 0 ) { // The key is in the wrong format Authentication_SetStatus( unknownKey, keyId, basicResult ); char *resultString = Authentication_GetStatusString(basicResult); AppDebugOut( "Key failed basic check : %s (result=%s)\n", unknownKey, resultString ); } else if( Authentication_IsDemoKey(unknownKey) ) { // This is a demo key, and has passed the simple check // Assume its valid from now on Authentication_SetStatus( unknownKey, -1, AuthenticationAccepted ); AppDebugOut( "Auth Key accepted as DEMOKEY : %s\n", unknownKey ); } else { // Request a proper auth check from the metaserver Directory directory; directory.SetName( NET_METASERVER_MESSAGE ); directory.CreateData( NET_METASERVER_COMMAND, NET_METASERVER_REQUEST_AUTH ); directory.CreateData( NET_METASERVER_AUTHKEY, unknownKey ); directory.CreateData( NET_METASERVER_AUTHKEYID, keyId ); directory.CreateData( NET_METASERVER_GAMENAME, APP_NAME ); directory.CreateData( NET_METASERVER_GAMEVERSION, APP_VERSION ); if( strcmp(clientIp, "unknown") != 0 ) { directory.CreateData( NET_METASERVER_IP, clientIp ); } MetaServer_SendToMetaServer( &directory ); AppDebugOut( "Requesting authentication of key %s\n", unknownKey ); } } } } #endif return 0; }
static NetCallBackRetType RequestIdentityThread(void *ignored) { #ifdef WAN_PLAY_ENABLED NetSocketListener *listener = (NetSocketListener *) ignored; int listenerIndex = GetListenerIndex(listener); AppAssert( listenerIndex > -1 ); s_listenersMutex.Lock(); MatchMakerListener *_listener = s_listeners[listenerIndex]; AppAssert(_listener); s_listenersMutex.Unlock(); // // Generate a uniqueID for this request // So we can tell the replies apart s_uniqueRequestMutex.Lock(); int uniqueId = s_uniqueRequestid; ++s_uniqueRequestid; s_uniqueRequestMutex.Unlock(); _listener->m_uniqueId = uniqueId; // // Build our request and convert to a byte stream // (only need to do this once and keep re-sending) Directory request; request.SetName( NET_MATCHMAKER_MESSAGE ); request.CreateData( NET_METASERVER_COMMAND, NET_MATCHMAKER_REQUEST_IDENTITY ); request.CreateData( NET_MATCHMAKER_UNIQUEID, uniqueId ); // // Open a connection to the MatchMaker service // Start sending requests for our ID every few seconds // to ensure the connection stays open in the NAT NetSocketSession socket( *listener, s_matchMakerIp, s_matchMakerPort ); while( true ) { // // Stop if We've been asked to if( _listener->m_shutDown ) { break; } // // Update the request with the latest auth data Directory *clientProps = MetaServer_GetClientProperties(); request.CreateData( NET_METASERVER_GAMENAME, clientProps->GetDataString(NET_METASERVER_GAMENAME) ); request.CreateData( NET_METASERVER_GAMEVERSION, clientProps->GetDataString(NET_METASERVER_GAMEVERSION) ); request.CreateData( NET_METASERVER_AUTHKEY, clientProps->GetDataString(NET_METASERVER_AUTHKEY) ); delete clientProps; int requestSize = 0; char *requestByteStream = request.Write(requestSize); // // Send the request int numBytesWritten = 0; NetRetCode result = socket.WriteData( requestByteStream, requestSize, &numBytesWritten ); delete [] requestByteStream; if( result != NetOk || numBytesWritten != requestSize ) { AppDebugOut( "MatchMaker encountered error sending data\n" ); break; } NetSleep( PERIOD_MATCHMAKER_REQUESTID ); } // // Shut down the request s_listenersMutex.Lock(); if( s_listeners.ValidIndex(listenerIndex) && s_listeners[listenerIndex] == _listener ) { s_listeners.RemoveData(listenerIndex); } s_listenersMutex.Unlock(); delete _listener; #endif return 0; }
NetRetCode NetSocket::Connect() { NetRetCode ret = NetOk; unsigned long timeout = 0; int err = 0; struct sockaddr_in *servaddr = &m_to; int sockType = SOCK_DGRAM; m_sockfd = socket(AF_INET, sockType, 0); if (!m_sockfd) { return NetFailed; } memset(servaddr, 0, sizeof(struct sockaddr_in)); servaddr->sin_family = AF_INET; servaddr->sin_port = htons(m_port); // Resolve dotted IP address /* Removed, didn't seem to work for addresses like 127.0.0.1 and 90.0.0.3 */ // if (!ncValidInetAddr(ncGetInetAddr(m_hostname,&servaddr->sin_addr.s_addr))) // { // Otherwise, resolve host name NetHostDetails *pHostent = NetGetHostByName(m_hostname); if (!pHostent) { NetDebugOut("Host address resolution failed for %s", m_hostname); return NetFailed; } else { servaddr->sin_addr.s_addr = * ((unsigned long *)pHostent->h_addr_list[0]); } // } // Stash the IP address as an unsigned long in host byte order m_ipaddr = servaddr->sin_addr.s_addr; // Set socket to non - blocking mode NetSetSocketNonBlocking(m_sockfd); // Attempt the connect until we timeout while (::connect(m_sockfd, (struct sockaddr *)servaddr, sizeof(*servaddr)) < 0) { NetDebugOut("Connection error"); if (NetIsBlockingError(err)) { timeout += 100; if (timeout > m_timeout) { NetDebugOut("Time out connecting to host"); ret = NetTimedout; break; } } else if (NetIsConnected(err)) { NetDebugOut("Already connected"); break; } else { NetDebugOut("Connect to host failed: %d", err); ret = NetFailed; break; } NetSleep(100); } return ret; }
int _tmain(int argc, _TCHAR* argv[]) { _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); srand(NetGetTime()); Peer* sender; int size; NetConnection connection; connection.Open(5008); NetConnection server; server.Open(5007); connection.connection.SetRTT(0); connection.connection.SetDrop(0); connection.connection.SetVariance(0); printf("Doing Connection Security Test\n"); for (int i = 0; i < 50; i++) { char* buffer = new char[i*6]; for (int in = 0; in < i*6; in++) { buffer[in] = rand(); } connection.connection.Send(Address(127,0,0,1,5007), buffer, i*6); delete[] buffer; } NetSleep(1000);//wait to receive messages //get all messages out char* out; while (out = server.Receive(sender, size)) { delete[] out; } if (server.peers.size() != 0) printf("Connection security test failed!!!\n\n"); else printf("Connection security test passed.\n\n"); auto t = std::thread([](NetConnection* server) { while (true) { Peer* sender; int size; server->Receive(sender, size); if (server->peers.size() > 5) return; } }, &server); int status = connection.Connect(Address(127,0,0,1,5007), "testing", 0); if (status < 0) { printf("Connection Test Failed!!!\n"); } NetConnection cons[5]; for (int i = 0; i < 5; i ++) { cons[i].Open(5010+i); int stat = cons[i].Connect(Address(127,0,0,1,5007), "yo", 0); if (stat < 0) printf("Connection test failed!\n"); } if (t.joinable()) t.join(); printf("Connection Test Successful\n"); for (int i = 0; i < 5; i++) { //cons[i].Disconnect(); cons[i].Close(); } while (server.peers.size() > 1) { Peer* s; int size; server.Receive(s, size); NetSleep(1); } printf("Connections closed successfully\n\n"); printf("Doing Security Test\n"); for (int i = 0; i < 50; i++) { char* buffer = new char[i*6]; for (int in = 0; in < i*6; in++) { buffer[in] = rand(); } connection.connection.Send(connection.peers.begin()->second->connection.remoteaddr, buffer, i*6); delete[] buffer; } NetSleep(1000);//wait to receive messages //get all messages out //char* out; while (out = server.Receive(sender, size)) { delete[] out; } printf("Well, we didnt crash, so security test probably didn't fail...\n\n"); connection.connection.SetRTT(0.05); connection.connection.SetDrop(0.1); connection.connection.SetVariance(0.02); //start testing printf("Testing reliable messages...\n"); int num = 50; while(num-- > 0) { int data[200]; for (int i = 0; i < 200; i++) { data[i] = rand(); } connection.SendReliable((char*)data, sizeof(data)); //ok, now check Peer* sender; int size; while (true) { char* buffer = server.Receive(sender, size); if (buffer) { if (size == sizeof(data)) { for (int i = 0; i < 200; i++) { assert(((int*)buffer)[i] == data[i]); } //printf("one good\n"); } else { printf("Bad message size!!!\n"); } delete[] buffer; break; } } } printf("Reliable message sending passed!\n\n"); printf("Testing reliable ordered messages...\n"); num = 50; int data[20][200]; for (int i = 0; i < 20; i++) { for (int i2 = 0; i2 < 200; i2++) { data[i][i2] = rand(); } data[i][0] = i; connection.peers.begin()->second->connection.SendReliableOrdered((char*)data[i], sizeof(data[i]), 5); } //ok, now check num = 0; while (num < 20) { char* buffer = server.Receive(sender, size); if (buffer) { if (size == sizeof(data[0])) { for (int i = 0; i < 200; i++) { assert(((int*)buffer)[i] == data[num][i]); } //printf("one good\n"); } else { printf("Bad message size!!!\n"); } num++; delete[] buffer; } } printf("Ordered Reliable Message Sending Passed!\n\n"); printf("Testing Split Reliable Ordered Messages...\n"); num = 50; int data2[20][500]; for (int i = 0; i < 20; i++) { for (int i2 = 0; i2 < 500; i2++) { data2[i][i2] = rand(); } data2[i][0] = i; connection.peers.begin()->second->connection.SendReliableOrdered((char*)data2[i], sizeof(data2[i]), 5); } //ok, now check //Peer* sender; int size; num = 0; while (num < 20) { char* buffer = server.Receive(sender, size); if (buffer) { if (size == sizeof(data2[0])) { for (int i = 0; i < 500; i++) { assert(((int*)buffer)[i] == data2[num][i]); } } else { printf("Bad message size!!!\n"); } num++; delete[] buffer; } } printf("Ordered Split Reliable Message Sending Passed!\n\n"); printf("Testing Reliable Message Splitting...\n"); //test splitting num = 50; while(num-- > 0) { int data[800]; for (int i = 0; i < 800; i++) { data[i] = rand(); } connection.SendReliable((char*)data, sizeof(data)); //ok, now check Peer* sender; int size; while (true) { char* buffer = server.Receive(sender, size); if (buffer) { if (size == sizeof(data)) { for (int i = 0; i < 800; i++) { assert(((int*)buffer)[i] == data[i]); } } else { printf("Bad message size!!!\n"); } delete[] buffer; break; } } } printf("Reliable Message Splitting Sending Passed!\n\n"); connection.connection.SetRTT(0); connection.connection.SetDrop(0); connection.connection.SetVariance(0); //test unreliable printf("Testing unreliable message sending...\n"); //test splitting num = 50; while(num-- > 0) { int data[200]; for (int i = 0; i < 200; i++) { data[i] = rand(); } connection.Send((char*)data, sizeof(data)); //ok, now check Peer* sender; int size; while (true) { char* buffer = server.Receive(sender, size); if (buffer) { if (size == sizeof(data)) { for (int i = 0; i < 200; i++) { assert(((int*)buffer)[i] == data[i]); } } else { printf("Bad message size!!!\n"); } delete[] buffer; break; } } } printf("Unreliable message sending passed!\n\n"); //test unreliable splitting printf("Testing unreliable message splitting...\n"); num = 50; while(num-- > 0) { int data[800]; for (int i = 0; i < 800; i++) { data[i] = rand(); } connection.Send((char*)data, sizeof(data)); //ok, now check Peer* sender; int size; while (true) { char* buffer = server.Receive(sender, size); if (buffer) { if (size == sizeof(data)) { for (int i = 0; i < 800; i++) { assert(((int*)buffer)[i] == data[i]); } } else { printf("Bad message size!!!\n"); } delete[] buffer; break; } } } printf("Unreliable message splitting sending passed!\n\n"); //test packet coalesing printf("Testing unreliable message coalescing...\n"); num = 50; while(num-- > 0) { int data[121]; for (int i = 0; i < 121; i++) { data[i] = rand(); } connection.Send((char*)data, sizeof(data)); connection.Send((char*)data, sizeof(data)); connection.Send((char*)data, sizeof(data)); connection.SendPackets();//force send //ok, now check Peer* sender; int size; for (int i = 0; i < 3; i++) { while (true) { char* buffer = server.Receive(sender, size); if (buffer) { if (size == sizeof(data)) { for (int i = 0; i < 121; i++) { assert(((int*)buffer)[i] == data[i]); } } else { printf("Bad message size!!!\n"); } delete[] buffer; break; } } } } printf("Unreliable message coalescing passed!\n\n"); printf("Testing Disconnection...\n"); connection.Disconnect(); while (true) { Peer* sender; int size; server.Receive(sender, size); if (server.peers.size() == 0) break; } printf("Disconnection successful!\n"); //while (true) NetSleep(10000); return 0; }