/* ================ idServerScan::GUIUpdateSelected ================ */ void idServerScan::GUIUpdateSelected( void ) { char screenshot[MAX_STRING_CHARS]; if( !m_pGUI ) { return; } int i = listGUI->GetSelection( NULL, 0 ); if( i == -1 || i >= Num() ) { m_pGUI->SetStateString( "server_name", "" ); m_pGUI->SetStateString( "player1", "" ); m_pGUI->SetStateString( "player2", "" ); m_pGUI->SetStateString( "player3", "" ); m_pGUI->SetStateString( "player4", "" ); m_pGUI->SetStateString( "player5", "" ); m_pGUI->SetStateString( "player6", "" ); m_pGUI->SetStateString( "player7", "" ); m_pGUI->SetStateString( "player8", "" ); m_pGUI->SetStateString( "server_map", "" ); m_pGUI->SetStateString( "browser_levelshot", "" ); m_pGUI->SetStateString( "server_gameType", "" ); m_pGUI->SetStateString( "server_IP", "" ); m_pGUI->SetStateString( "server_passworded", "" ); } else { m_pGUI->SetStateString( "server_name", ( *this ) [i].serverInfo.GetString( "si_name" ) ); for( int j = 0; j < 8; j++ ) { if( ( *this ) [i].clients > j ) { m_pGUI->SetStateString( va( "player%i", j + 1 ) , ( *this ) [i].nickname[j] ); } else { m_pGUI->SetStateString( va( "player%i", j + 1 ) , "" ); } } m_pGUI->SetStateString( "server_map", ( *this ) [i].serverInfo.GetString( "si_mapName" ) ); fileSystem->FindMapScreenshot( ( *this ) [i].serverInfo.GetString( "si_map" ), screenshot, MAX_STRING_CHARS ); m_pGUI->SetStateString( "browser_levelshot", screenshot ); m_pGUI->SetStateString( "server_gameType", ( *this ) [i].serverInfo.GetString( "si_gameType" ) ); m_pGUI->SetStateString( "server_IP", Sys_NetAdrToString( ( *this ) [i].adr ) ); if( ( *this ) [i].serverInfo.GetBool( "si_usePass" ) ) { m_pGUI->SetStateString( "server_passworded", "PASSWORD REQUIRED" ); } else { m_pGUI->SetStateString( "server_passworded", "" ); } } }
/* ================ idServerScan::NetScan ================ */ void idServerScan::NetScan( ) { if ( !idAsyncNetwork::client.IsPortInitialized() ) { // if the port isn't open, initialize it, but wait for a short // time to let the OS do whatever magic things it needs to do... idAsyncNetwork::client.InitPort(); // start the scan one second from now... scan_state = WAIT_ON_INIT; endWaitTime = Sys_Milliseconds() + 1000; return; } // make sure the client port is open idAsyncNetwork::client.InitPort(); scan_state = NET_SCAN; challenge++; idList<networkServer_t>::Clear(); m_sortedServers.Clear(); cur_info = 0; net_info.Clear(); listGUI->Clear(); GUIUpdateSelected(); common->DPrintf( "NetScan with challenge %d\n", challenge ); while ( cur_info < Min( net_servers.Num(), MAX_PINGREQUESTS ) ) { netadr_t serv = net_servers[ cur_info ].adr; EmitGetInfo( serv ); net_servers[ cur_info ].time = Sys_Milliseconds(); net_info.SetInt( Sys_NetAdrToString( serv ), cur_info ); cur_info++; } }
/* ================ idServerScan::InfoResponse ================ */ int idServerScan::InfoResponse( networkServer_t &server ) { if ( scan_state == IDLE ) { return false; } idStr serv = Sys_NetAdrToString( server.adr ); if ( server.challenge != challenge ) { common->DPrintf( "idServerScan::InfoResponse - ignoring response from %s, wrong challenge %d.", serv.c_str(), server.challenge ); return false; } if ( scan_state == NET_SCAN ) { const idKeyValue *info = net_info.FindKey( serv.c_str() ); if ( !info ) { common->DPrintf( "idServerScan::InfoResponse NET_SCAN: reply from unknown %s\n", serv.c_str() ); return false; } int id = atoi( info->GetValue() ); net_info.Delete( serv.c_str() ); inServer_t iserv = net_servers[ id ]; server.ping = Sys_Milliseconds() - iserv.time; server.id = iserv.id; } else { server.ping = Sys_Milliseconds() - lan_pingtime; server.id = 0; // check for duplicate servers for ( int i = 0; i < Num() ; i++ ) { if ( memcmp( &(*this)[ i ].adr, &server.adr, sizeof(netadr_t) ) == 0 ) { common->DPrintf( "idServerScan::InfoResponse LAN_SCAN: duplicate server %s\n", serv.c_str() ); return true; } } } const char *si_map = server.serverInfo.GetString( "si_map" ); const idDecl *mapDecl = declManager->FindType( DECL_MAPDEF, si_map, false ); const idDeclEntityDef *mapDef = static_cast< const idDeclEntityDef * >( mapDecl ); if ( mapDef ) { const char *mapName = common->GetLanguageDict()->GetString( mapDef->dict.GetString( "name", si_map ) ); server.serverInfo.Set( "si_mapName", mapName ); } else { server.serverInfo.Set( "si_mapName", si_map ); } int index = Append( server ); // for now, don't maintain sorting when adding new info response servers m_sortedServers.Append( Num()-1 ); if ( listGUI->IsConfigured( ) && !IsFiltered( server ) ) { GUIAdd( Num()-1, server ); } if ( listGUI->GetSelection( NULL, 0 ) == ( Num()-1 ) ) { GUIUpdateSelected(); } return index; }
/* ================== Net_GetUDPPacket ================== */ bool Net_GetUDPPacket( int netSocket, netadr_t &net_from, char *data, int &size, int maxSize ) { int ret; struct sockaddr from; int fromlen; int err; if( !netSocket ) { return false; } fromlen = sizeof(from); ret = recvfrom( netSocket, data, maxSize, 0, (struct sockaddr *)&from, &fromlen ); if ( ret == SOCKET_ERROR ) { err = WSAGetLastError(); if( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) { return false; } char buf[1024]; sprintf( buf, "Net_GetUDPPacket: %s\n", NET_ErrorString() ); OutputDebugString( buf ); return false; } if ( netSocket == ip_socket ) { memset( ((struct sockaddr_in *)&from)->sin_zero, 0, 8 ); } if ( usingSocks && netSocket == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) { if ( ret < 10 || data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 1 ) { return false; } net_from.type = NA_IP; net_from.ip[0] = data[4]; net_from.ip[1] = data[5]; net_from.ip[2] = data[6]; net_from.ip[3] = data[7]; net_from.port = *(short *)&data[8]; memmove( data, &data[10], ret - 10 ); } else { Net_SockadrToNetadr( &from, &net_from ); } if( ret == maxSize ) { char buf[1024]; sprintf( buf, "Net_GetUDPPacket: oversize packet from %s\n", Sys_NetAdrToString( net_from ) ); OutputDebugString( buf ); return false; } size = ret; return true; }
/* =============== idServerScan::ServerScanFrame =============== */ void idServerScan::RunFrame( ) { if ( scan_state == IDLE ) { return; } if ( scan_state == WAIT_ON_INIT ) { if ( Sys_Milliseconds() >= endWaitTime ) { scan_state = IDLE; NetScan(); } return; } int timeout_limit = Sys_Milliseconds() - REPLY_TIMEOUT; if ( scan_state == LAN_SCAN ) { if ( timeout_limit > lan_pingtime ) { common->Printf( "Scanned for servers on the LAN\n" ); scan_state = IDLE; } return; } // if scan_state == NET_SCAN // check for timeouts int i = 0; while ( i < net_info.GetNumKeyVals() ) { if ( timeout_limit > net_servers[ atoi( net_info.GetKeyVal( i )->GetValue().c_str() ) ].time ) { common->DPrintf( "timeout %s\n", net_info.GetKeyVal( i )->GetKey().c_str() ); net_info.Delete( net_info.GetKeyVal( i )->GetKey().c_str() ); } else { i++; } } // possibly send more queries while ( cur_info < net_servers.Num() && net_info.GetNumKeyVals() < MAX_PINGREQUESTS ) { netadr_t serv = net_servers[ cur_info ].adr; EmitGetInfo( serv ); net_servers[ cur_info ].time = Sys_Milliseconds(); net_info.SetInt( Sys_NetAdrToString( serv ), cur_info ); cur_info++; } // update state if ( ( !incoming_net || ( incoming_useTimeout && Sys_Milliseconds() > incoming_lastTime ) ) && net_info.GetNumKeyVals() == 0 ) { EndServers(); // the list is complete, we are no longer waiting for any getInfo replies common->Printf( "Scanned %d servers.\n", cur_info ); scan_state = IDLE; } }
/* ======================== idLobbyBackendDirect::JoinFromConnectInfo ======================== */ void idLobbyBackendDirect::JoinFromConnectInfo( const lobbyConnectInfo_t& connectInfo ) { if( lobbyToSessionCB->CanJoinLocalHost() ) { // TODO: "CanJoinLocalHost" == *must* join LocalHost ?! Sys_StringToNetAdr( "localhost", &address, true ); address.port = net_port.GetInteger(); NET_VERBOSE_PRINT( "NET: idLobbyBackendDirect::JoinFromConnectInfo(): canJoinLocalHost\n" ); } else { address = connectInfo.netAddr; NET_VERBOSE_PRINT( "NET: idLobbyBackendDirect::JoinFromConnectInfo(): %s\n", Sys_NetAdrToString( address ) ); } state = STATE_READY; isLocal = false; isHost = false; }
/* ================== idPort::SendPacket ================== */ void idPort::SendPacket( const netadr_t to, const void *data, int size ) { int ret; struct sockaddr_in addr; if ( to.type == NA_BAD ) { common->Warning( "idPort::SendPacket: bad address type NA_BAD - ignored" ); return; } if ( !netSocket ) { return; } NetadrToSockadr( &to, &addr ); ret = sendto( netSocket, data, size, 0, (struct sockaddr *) &addr, sizeof(addr) ); if ( ret == -1 ) { common->Printf( "idPort::SendPacket ERROR: to %s: %s\n", Sys_NetAdrToString( to ), strerror( errno ) ); } }
/* ======================== Net_GetUDPPacket ======================== */ bool Net_GetUDPPacket( int netSocket, netadr_t& net_from, char* data, int& size, int maxSize ) { int ret; sockaddr_in from; socklen_t fromlen; int err; if( !netSocket ) { return false; } fromlen = sizeof( from ); ret = recvfrom( netSocket, data, maxSize, 0, ( sockaddr* )&from, &fromlen ); if( ret == SOCKET_ERROR ) { err = Net_GetLastError(); if( err == D3_NET_EWOULDBLOCK || err == D3_NET_ECONNRESET ) { return false; } idLib::Printf( "Net_GetUDPPacket: %s\n", NET_ErrorString() ); return false; } #if 0 // TODO: WTF was this about? // DG: ip_socket is never initialized, so this is dead code // - and if netSocket is 0 (so this would be true) recvfrom above will already fail if( static_cast<unsigned int>( netSocket ) == ip_socket ) { memset( from.sin_zero, 0, sizeof( from.sin_zero ) ); } if( usingSocks && static_cast<unsigned int>( netSocket ) == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) { if( ret < 10 || data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 1 ) { return false; } net_from.type = NA_IP; net_from.ip[0] = data[4]; net_from.ip[1] = data[5]; net_from.ip[2] = data[6]; net_from.ip[3] = data[7]; net_from.port = *( short* )&data[8]; memmove( data, &data[10], ret - 10 ); } else { #endif // 0 Net_SockadrToNetadr( &from, &net_from ); #if 0 // this is ugly, but else astyle is confused } #endif if( ret > maxSize ) { idLib::Printf( "Net_GetUDPPacket: oversize packet from %s\n", Sys_NetAdrToString( net_from ) ); return false; } size = ret; return true; }