/* ======================== idLobby::RemoveSessionUsersByIDList This is the choke point for removing users from a session. It will handle all the housekeeping of removing from various platform lists (xsession user tracking, etc). Called from both host and client. ======================== */ void idLobby::RemoveSessionUsersByIDList( idList< lobbyUserID_t > & usersToRemoveByID ) { assert( lobbyBackend != NULL || usersToRemoveByID.Num() == 0 ); for ( int i = 0; i < usersToRemoveByID.Num(); i++ ) { for ( int u = 0; u < GetNumLobbyUsers(); u++ ) { lobbyUser_t * user = GetLobbyUser( u ); if ( user->IsDisconnected() ) { // User already disconnected from session but not removed from the list. // This will happen when users are removed during the game. continue; } if ( user->lobbyUserID == usersToRemoveByID[i] ) { if ( lobbyType == TYPE_GAME ) { idLib::Printf( "NET: %s left the game.\n", user->gamertag ); } else if ( lobbyType == TYPE_PARTY ) { idLib::Printf( "NET: %s left the party.\n", user->gamertag ); } UnregisterUser( user ); // Save the user so we can still get his gamertag, which may be needed for // a disconnection HUD message. SaveDisconnectedUser( *user ); FreeUser( user ); break; } } } if ( usersToRemoveByID.Num() > 0 && IsHost() ) { if ( lobbyBackend != NULL ) { lobbyBackend->UpdateLobbySkill( GetAverageSessionLevel() ); } // If we are the host, send a message to all peers with a list of users who have disconnected byte buffer[ idPacketProcessor::MAX_MSG_SIZE ]; idBitMsg msg( buffer, sizeof( buffer ) ); msg.WriteByte( usersToRemoveByID.Num() ); for ( int i = 0; i < usersToRemoveByID.Num(); i++ ) { usersToRemoveByID[i].WriteToMsg( msg ); } for ( int p = 0; p < peers.Num(); p++ ) { QueueReliableMessage( p, RELIABLE_USER_DISCONNECTED, msg.GetReadData(), msg.GetSize() ); } } }
/* ======================== idLobby::RequestSessionUserDisconnect Sends a request to the host to remove a session user from the session. If we are the host, we will do it immediately. ======================== */ void idLobby::RequestSessionUserDisconnect( int sessionUserIndex ) { if ( !IsRunningAsHostOrPeer() ) { // If we are not in an actual running session, just remove it. // This is so we accurately reflect the local user list through the session users in the menus, etc. // FIXME: // This is a total hack, and we should really look at better separation of local users/session users // and not rely on session users while in the menus. FreeUser( GetLobbyUser( sessionUserIndex ) ); return; } lobbyUser_t * lobbyUser = GetLobbyUser( sessionUserIndex ); if ( !verify( lobbyUser != NULL ) ) { return; } if ( lobbyUser->disconnecting == true ) { return; // Already disconnecting } byte buffer[ idPacketProcessor::MAX_PACKET_SIZE ]; idBitMsg msg( buffer, sizeof( buffer ) ); msg.WriteByte( 1 ); // 1 user lobbyUser->lobbyUserID.WriteToMsg( msg ); if ( IsHost() ) { idBitMsg readMsg; readMsg.InitRead( msg.GetReadData(), msg.GetSize() ); // As the host, just disconnect immediately (we'll still send the notification to all peers though) ProcessUserDisconnectMsg( readMsg ); } else { // Send the message QueueReliableMessage( host, RELIABLE_USER_DISCONNECT_REQUEST, msg.GetReadData(), msg.GetSize() ); // Mark user as disconnecting to make sure we don't keep sending the request lobbyUser->disconnecting = true; } }
/* ======================== idLobby::RemoveBotFromLobbyUserList ======================== */ void idLobby::RemoveBotFromLobbyUserList( lobbyUserID_t lobbyUserID ) { const int index = GetLobbyUserIndexByID( lobbyUserID ); lobbyUser_t * botUser = GetLobbyUser( index ); if ( botUser == NULL ) { assert( false ); idLib::Warning( "RemoveBotFromLobbyUserList: Invalid User Index!" ); return; } if ( !botUser->isBot ) { idLib::Warning( "RemoveBotFromLobbyUserList: User Index Is Not A Bot!" ); // don't accidentally disconnect a human player. return; } botUser->isBot = false; botUser->lobbyUserID = lobbyUserID_t(); FreeUser( botUser ); }
/* * Lwt_LsaEnumUsers * * Check that LsaEnumUsers, LsaBeginEnumUsers, LsaEndEnumUsers behave * as expected, mostly by matching information against pUsersCsv. */ DWORD Lwt_LsaEnumUsers( HANDLE hLsaConnection, PTESTDATA pTestData ) { DWORD dwError = LW_ERROR_SUCCESS; DWORD dwLocalError = LW_ERROR_SUCCESS; size_t nCurrentUser; PLWTUSER pUser = NULL; if (!pTestData) { dwError = LW_ERROR_TEST_SKIPPED; goto error; } /* For each user (line), verify the information is correct. */ for ( nCurrentUser = 0; nCurrentUser < pTestData->dwNumUsers; nCurrentUser++) { DWORD dwUserInfoLevel; dwLocalError = GetUser(pTestData, nCurrentUser, &pUser); BAIL_ON_TEST_BROKE(dwLocalError); for ( dwUserInfoLevel = 0; dwUserInfoLevel < 3; dwUserInfoLevel++) { PCSTR pszName = pUser->pszNTName; if ( pUser->pszAlias ) pszName = pUser->pszAlias; if ( pszName ) { dwLocalError = CheckLsaEnumUsers( hLsaConnection, pszName, dwUserInfoLevel, 1); BAIL_ON_TEST_BROKE(dwLocalError); dwLocalError = CheckLsaEnumUsers( hLsaConnection, pszName, dwUserInfoLevel, 100); BAIL_ON_TEST_BROKE(dwLocalError); dwLocalError = CheckLsaEnumUsers( hLsaConnection, pszName, dwUserInfoLevel, 500); BAIL_ON_TEST_BROKE(dwLocalError); } } FreeUser(&pUser); } VerifyErrorConditions(hLsaConnection); cleanup: if ( pUser ) { FreeUser(&pUser); } return dwError; error: goto cleanup; }
DWORD Lwt_LsaFindUserByName( HANDLE hLsaConnection, PTESTDATA pTestData ) { DWORD dwError = LW_ERROR_SUCCESS; DWORD dwLocalError = LW_ERROR_SUCCESS; size_t nCurrentUser; PLWTUSER pUser = NULL; PLSA_USER_INFO_0 pUserInfo0 = NULL; PLSA_USER_INFO_1 pUserInfo1 = NULL; if ( ! pTestData ) { dwError = LW_ERROR_TEST_SKIPPED; goto error; } /* For each user (line), verify the information is correct. */ for ( nCurrentUser = 0; nCurrentUser < pTestData->dwNumUsers; nCurrentUser++ ) { dwLocalError = GetUser( pTestData, nCurrentUser, &pUser); BAIL_ON_TEST_BROKE(dwLocalError); if ( pUser->pszNTName ) { dwLocalError = FindUserByName0( hLsaConnection, pUser, pUser->pszNTName, &pUserInfo0); BAIL_ON_TEST_BROKE(dwLocalError); } if ( pUserInfo0 ) { dwLocalError = MatchUserInfo0( pUser, pUser->pszNTName, pUserInfo0); BAIL_ON_TEST_BROKE(dwLocalError); LsaFreeUserInfo(0, pUserInfo0); pUserInfo0 = NULL; } if ( pUser->pszUserPrincipalName ) { dwLocalError = FindUserByName0( hLsaConnection, pUser, pUser->pszUserPrincipalName, &pUserInfo0); BAIL_ON_TEST_BROKE(dwLocalError); } if ( pUserInfo0 ) { dwLocalError = MatchUserInfo0( pUser, pUser->pszUserPrincipalName, pUserInfo0); BAIL_ON_TEST_BROKE(dwLocalError); LsaFreeUserInfo(0, pUserInfo0); pUserInfo0 = NULL; } if ( pUser->pszNTName ) { dwLocalError = FindUserByName1( hLsaConnection, pUser, pUser->pszNTName, &pUserInfo1); BAIL_ON_TEST_BROKE(dwLocalError); } if ( pUserInfo1 ) { LsaFreeUserInfo(1, pUserInfo1); pUserInfo1 = NULL; } FreeUser(&pUser); } dwLocalError = VerifyNullHandling(hLsaConnection); BAIL_ON_TEST_BROKE(dwLocalError); dwLocalError = ValidateForInvalidParams(hLsaConnection, pTestData); BAIL_ON_TEST_BROKE(dwLocalError); cleanup: if ( pUserInfo0 ) { LsaFreeUserInfo(0, pUserInfo0); pUserInfo0 = NULL; } if ( pUserInfo1 ) { LsaFreeUserInfo(1, pUserInfo1); pUserInfo1 = NULL; } if ( pUser ) { FreeUser(&pUser); } return dwError; error: goto cleanup; }