inline void UserInfoCache::removeUser(int userId) { d_lock.lockWrite(); d_infoMap.erase(userId); d_lock.unlock(); }
void MediaAddonServer::_AddOnRemoved(ino_t fileNode) { // TODO: locking? FileMap::iterator foundFile = fFileMap.find(fileNode); if (foundFile == fFileMap.end()) { ERROR("MediaAddonServer::_AddOnRemoved: inode %Ld removed, but no " "media add-on found\n", fileNode); return; } media_addon_id id = foundFile->second; fFileMap.erase(foundFile); int32 oldFlavorCount; InfoMap::iterator foundInfo = fInfoMap.find(id); if (foundInfo == fInfoMap.end()) { ERROR("MediaAddonServer::_AddOnRemoved: couldn't get addon info for " "add-on %ld\n", id); oldFlavorCount = 1000; } else { AddOnInfo& info = foundInfo->second; oldFlavorCount = info.flavor_count; _DestroyInstantiatedFlavors(info); _PutAddonIfPossible(info); if (info.addon) { ERROR("MediaAddonServer::_AddOnRemoved: couldn't unload addon " "%ld since flavors are in use\n", id); } fInfoMap.erase(foundInfo); } gDormantNodeManager->UnregisterAddOn(id); BPrivate::media::notifications::FlavorsChanged(id, 0, oldFlavorCount); }
/* ================== SV_DirectConnect A "connect" OOB command has been received ================== */ void SV_DirectConnect( netadr_t from, const Cmd::Args& args ) { if ( args.Argc() < 2 ) { return; } Log::Debug( "SVC_DirectConnect ()" ); InfoMap userinfo = InfoStringToMap(args.Argv(1)); // DHM - Nerve :: Update Server allows any protocol to connect // NOTE TTimo: but we might need to store the protocol around for potential non http/ftp clients int version = atoi( userinfo["protocol"].c_str() ); if ( version != PROTOCOL_VERSION ) { Net::OutOfBandPrint( netsrc_t::NS_SERVER, from, "print\nServer uses protocol version %i (yours is %i).", PROTOCOL_VERSION, version ); Log::Debug( " rejected connect from version %i", version ); return; } int qport = atoi( userinfo["qport"].c_str() ); auto clients_begin = svs.clients; auto clients_end = clients_begin + sv_maxclients->integer; client_t* reconnecting = std::find_if(clients_begin, clients_end, [&from, qport](const client_t& client) { return NET_CompareBaseAdr( from, client.netchan.remoteAddress ) && ( client.netchan.qport == qport || from.port == client.netchan.remoteAddress.port ); } ); if ( reconnecting != clients_end && svs.time - reconnecting->lastConnectTime < sv_reconnectlimit->integer * 1000 ) { Log::Debug( "%s: reconnect rejected: too soon", NET_AdrToString( from ) ); return; } if ( NET_IsLocalAddress( from ) ) { userinfo["ip"] = "loopback"; } else { // see if the challenge is valid (local clients don't need to challenge) Challenge::Duration ping_duration; if ( !ChallengeManager::MatchString( from, userinfo["challenge"], &ping_duration ) ) { Net::OutOfBandPrint( netsrc_t::NS_SERVER, from, "print\n[err_dialog]No or bad challenge for address." ); return; } userinfo["ip"] = NET_AdrToString( from ); } client_t *new_client = nullptr; // if there is already a slot for this IP address, reuse it if ( reconnecting != clients_end ) { Log::Notice( "%s:reconnect\n", NET_AdrToString( from ) ); new_client = reconnecting; } else { // find a client slot // if "sv_privateClients" is set > 0, then that number // of client slots will be reserved for connections that // have "password" set to the value of "sv_privatePassword" // Info requests will report the maxclients as if the private // slots didn't exist, to prevent people from trying to connect // to a full server. // This is to allow us to reserve a couple slots here on our // servers so we can play without having to kick people. // check for privateClient password int startIndex = 0; if ( userinfo["password"] != sv_privatePassword->string ) { // skip past the reserved slots startIndex = sv_privateClients->integer; } new_client = std::find_if(clients_begin, clients_end, [](const client_t& client) { return client.state == clientState_t::CS_FREE; }); if ( new_client == clients_end ) { if ( NET_IsLocalAddress( from ) ) { int count = std::count_if(clients_begin+startIndex, clients_end, [](const client_t& client) { return SV_IsBot(&client); } ); // if they're all bots if ( count >= sv_maxclients->integer - startIndex ) { SV_DropClient( &svs.clients[ sv_maxclients->integer - 1 ], "only bots on server" ); new_client = &svs.clients[ sv_maxclients->integer - 1 ]; } else { Com_Error( errorParm_t::ERR_FATAL, "server is full on local connect" ); } } else { Net::OutOfBandPrint( netsrc_t::NS_SERVER, from, "print\n%s", sv_fullmsg->string ); Log::Debug( "Rejected a connection." ); return; } } } // build a new connection // accept the new client // this is the only place a client_t is ever initialized memset( new_client, 0, sizeof( client_t ) ); int clientNum = new_client - svs.clients; #ifdef HAVE_GEOIP const char * country = NET_GeoIP_Country( &from ); if ( country ) { Log::Notice( "Client %i connecting from %s\n", clientNum, country ); userinfo["geoip"] = country; } else { Log::Notice( "Client %i connecting from somewhere unknown\n", clientNum ); } #else Log::Notice( "Client %i connecting\n", clientNum ); #endif new_client->gentity = SV_GentityNum( clientNum ); new_client->gentity->r.svFlags = 0; // save the address Netchan_Setup( netsrc_t::NS_SERVER, &new_client->netchan, from, qport ); // init the netchan queue // Save the pubkey Q_strncpyz( new_client->pubkey, userinfo["pubkey"].c_str(), sizeof( new_client->pubkey ) ); userinfo.erase("pubkey"); // save the userinfo Q_strncpyz( new_client->userinfo, InfoMapToString(userinfo).c_str(), sizeof( new_client->userinfo ) ); // get the game a chance to reject this connection or modify the userinfo char reason[ MAX_STRING_CHARS ]; if ( gvm.GameClientConnect( reason, sizeof( reason ), clientNum, true, false ) ) { Net::OutOfBandPrint( netsrc_t::NS_SERVER, from, "print\n[err_dialog]%s", reason ); Log::Debug( "Game rejected a connection: %s.", reason ); return; } SV_UserinfoChanged( new_client ); // send the connect packet to the client Net::OutOfBandPrint( netsrc_t::NS_SERVER, from, "connectResponse" ); Log::Debug( "Going from CS_FREE to CS_CONNECTED for %s", new_client->name ); new_client->state = clientState_t::CS_CONNECTED; new_client->nextSnapshotTime = svs.time; new_client->lastPacketTime = svs.time; new_client->lastConnectTime = svs.time; // when we receive the first packet from the client, we will // notice that it is from a different serverid and that the // gamestate message was not just sent, forcing a retransmit new_client->gamestateMessageNum = -1; // if this was the first client on the server, or the last client // the server can hold, send a heartbeat to the master. int count = std::count_if(clients_begin, clients_end, [](const client_t& client) { return client.state >= clientState_t::CS_CONNECTED; }); if ( count == 1 || count == sv_maxclients->integer ) { SV_Heartbeat_f(); } }