inline
 void UserInfoCache::removeUser(int userId)
 {
     d_lock.lockWrite();
     d_infoMap.erase(userId);
     d_lock.unlock();
 }
示例#2
0
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);
}
示例#3
0
/*
==================
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();
	}
}