⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sessionmanager.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// Purpose: Callback for receiving data blocks from the network
//-----------------------------------------------------------------------------
bool CSessionManager::ReceivedData(IReceiveMessage *dataBlock)
{
	if (m_bLockedDown)
	{
		// don't accept any more messages when locked down
		return true;
	}

	// if it's a login message, allocate a new session
	switch (dataBlock->GetMsgID())
	{
		case TCLS_LOGIN:
		{
			// if it's a login message, allocate a new session
			LoginNewUser(dataBlock);
			return true;
		}

		case TCLS_CREATEUSER:
		{
			CreateNewUser(dataBlock);
			return true;
		}

		case TCLS_VALIDATEUSER:
		{
			ValidateUser(dataBlock);
			return true;
		}

		case TCLS_PING:
		{
			AcknowledgeUserPing(dataBlock);
			return true;
		}
		default:
		{
			// try and match the message with an existing session
			DispatchMessageToUserSession(dataBlock);
			break;
		}
	}
	return true;
}

//-----------------------------------------------------------------------------
// Purpose: We have had a network message to a user fail, force them off
//-----------------------------------------------------------------------------
void CSessionManager::OnFailedMessage(IReceiveMessage *failedMsg)
{
	// try and find the user
	unsigned int sessionID = failedMsg->SessionID();
	unsigned short sessionIndex = SESSION_INDEX(sessionID);

	if (sessionIndex >= m_UserSessions.Size())
	{
		// bad packet, throw away
		return;
	}

	if (m_UserSessions[sessionIndex].State() == USERSESSION_ACTIVE && m_UserSessions[sessionIndex].Status())
	{
		// they failed a general message, either a firewall issue or the user has crashed
		m_UserSessions[sessionIndex].OnFailedMessage(failedMsg);
	}
	else if (m_UserSessions[sessionIndex].State() == USERSESSION_CONNECTING)
	{
		// challenge message failed, disconnect user
		FreeUserSession(&m_UserSessions[sessionIndex]);
	}
}


//-----------------------------------------------------------------------------
// Purpose: Flushes all logged in users out of the database
//-----------------------------------------------------------------------------
void CSessionManager::FlushUsers(bool force)
{
	if (force)
	{
		// issue general flush of any user logged on to this machine
		for (int i = 0; i < g_pDataManager->TrackerUserCount(); i++)
		{
			g_pDataManager->TrackerUserByIndex(i).db->Users_Flush();
		}
	}
	else
	{
		// log out all users
		for (int i = 0; i < m_UserSessions.Size(); i++)
		{
			if (m_UserSessions[i].State() == USERSESSION_ACTIVE)
			{
				m_UserSessions[i].Logoff(true, false, false);
			}
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: Attempts to log a user onto the server
// Input  : *loginMsg - network message 
//-----------------------------------------------------------------------------
void CSessionManager::LoginNewUser(IReceiveMessage *loginMsg)
{
	// get the userID
	unsigned int userID;
	loginMsg->ReadUInt("uid", userID);

	if (userID >= m_iLockedUserLowerRange && userID <= m_iLockedUserUpperRange)
	{
		// we can't log the user in since they're in the locked range - tell them to stay disconnected
		g_pConsole->Print(6, "Locked range, sending disconnected message to %d\n", userID);

		ISendMessage *msg = net()->CreateReply(TSVC_DISCONNECT, loginMsg);
		msg->WriteInt("minTime", 1);
		msg->WriteInt("maxTime", 4);
		net()->SendMessage(msg, NET_RELIABLE);
	}
	else
	{
		// allocate a new user session
		CUserSession *session = GetNewUserSession();
		
		if (session->ReceivedMsg_Login(loginMsg))
		{
			// user login success; map in their user id
			MapUserIDToUserSession(session->UID(), session);
		}
		else 
		{
			// bad login attempt, clear user session
			FreeUserSession(session);
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: inserts a mapping of userID -> CUserSession
//-----------------------------------------------------------------------------
void CSessionManager::MapUserIDToUserSession(unsigned int userID, CUserSession *userSession)
{
	SessionMapItem_t searchItem = { userID, userSession };
	m_IDMap.Insert(searchItem);
}

//-----------------------------------------------------------------------------
// Purpose: removes a userID -> CUserSession mapping
//-----------------------------------------------------------------------------
void CSessionManager::UnmapUserID(unsigned int userID)
{
	SessionMapItem_t searchItem = { userID, NULL };
	int index = m_IDMap.Find(searchItem);
	if (m_IDMap.IsValidIndex(index))
	{
		m_IDMap.RemoveAt(index);
	}
}

//-----------------------------------------------------------------------------
// Purpose: Tries to create a new user
//			Does not log them on
//-----------------------------------------------------------------------------
void CSessionManager::CreateNewUser(IReceiveMessage *msg)
{
	// temporarily store the new new user
	int newIndex = m_CreateUsers.AddToTail();
	CreateUser_t &user = m_CreateUsers[newIndex];

	msg->ReadString("username", user.userName, 32);
	msg->ReadString("firstname", user.firstName, 32);
	msg->ReadString("lastname", user.lastName, 32);
	msg->ReadString("email", user.email, 128);
	msg->ReadString("password", user.password, 32);

	// make sure the user doesn't exist on any of the servers
	user.resultsNeeded = g_pDataManager->TrackerUserCount();
	user.failed = false;

	user.ip = msg->NetAddress().IP();
	user.port = msg->NetAddress().Port();
	user.requestTime = GetCurrentTime();

	// ask all the servers whether they've seen this user
	for (int i = 0; i < g_pDataManager->TrackerUserCount(); i++)
	{
		ITrackerDatabaseManager::db_t &db = g_pDataManager->TrackerUserByIndex(i);
		db.db->User_Validate(this, user.email, user.password, user.ip, user.port, newIndex);
	}
}

//-----------------------------------------------------------------------------
// Purpose: Checks to see if the specified user exists, and replies to the message
//			with the users userID
// Input  : *validateMsg - 
//-----------------------------------------------------------------------------
void CSessionManager::ValidateUser(IReceiveMessage *msg)
{
	char email[128];
	char password[32];

	// parse out the createUserMsg
	msg->ReadString("email", email, 128);
	msg->ReadString("password", password, 32);

	// check to see if the user exists on any server
	for (int i = 0; i < g_pDataManager->TrackerUserCount(); i++)
	{
		g_pDataManager->TrackerUserByIndex(i).db->User_Validate(this, email, password, msg->NetAddress().IP(), msg->NetAddress().Port(), (unsigned int)~0);
	}
}

//-----------------------------------------------------------------------------
// Purpose: Handles a simple ping message from a user, and replies with an 'Ack'
//-----------------------------------------------------------------------------
void CSessionManager::AcknowledgeUserPing(IReceiveMessage *pingMsg)
{
	ISendMessage *ackMsg = net()->CreateReply(TSVC_PINGACK, pingMsg);
	net()->SendMessage(ackMsg, NET_UNRELIABLE);
}

//-----------------------------------------------------------------------------
// Purpose: Returns the current time, in seconds
//-----------------------------------------------------------------------------
float CSessionManager::GetCurrentTime()
{
	//!! need to use a higher res timer
	static long timeBase = 0;
	time_t timer;
	::time(&timer);

	// hack: normalize the timebase so the float isn't so inaccurate
	if (!timeBase)
	{
		timeBase = (long)timer;
	}
	return (float)((long)timer - timeBase);
}

//-----------------------------------------------------------------------------
// Purpose: causes the main thread to sleep until it's signalled
//-----------------------------------------------------------------------------
void CSessionManager::WaitForEvent(unsigned long timeoutMillis)
{
	Event_WaitForEvent(m_hEvent, timeoutMillis);
}

//-----------------------------------------------------------------------------
// Purpose: returns the sleep event
//-----------------------------------------------------------------------------
unsigned long CSessionManager::GetWindowsEvent()
{
	return m_hEvent;
}

//-----------------------------------------------------------------------------
// Purpose: Wakes up the main thread
//-----------------------------------------------------------------------------
void CSessionManager::WakeUp()
{
	Event_SignalEvent(m_hEvent);
}

//-----------------------------------------------------------------------------
// Purpose: handles a response from the sql database
//-----------------------------------------------------------------------------
void CSessionManager::SQLDBResponse(int cmdID, int returnState, int returnVal, void *data)
{
	if (cmdID == CMD_VALIDATE)
	{
		// response to the Validate command is in
		ITrackerUserDatabase::UserValidate_t *response = (ITrackerUserDatabase::UserValidate_t *)data;

		if (response->temporaryID == -1)
		{
			// reply with the returned state
			ISendMessage *reply = net()->CreateMessage(TSVC_USERVALID);
			CNetAddress addr;
			addr.SetIP(response->IP);
			addr.SetPort(response->Port);
			reply->SetNetAddress(addr);
			reply->SetEncrypted(true);

			unsigned int userID = *((unsigned int *)(&returnVal));
			reply->WriteUInt("userID", userID);

			net()->SendMessage(reply, NET_RELIABLE);
		}
		else
		{
			// user is attempting to be created
			if (!m_CreateUsers.IsValidIndex(response->temporaryID))
				return;

			CreateUser_t &user = m_CreateUsers[response->temporaryID];

			if (returnVal != -1)
			{
				// user already exists; send back a fail message
				user.failed = true;

				// bad ID, write out an error string
				ISendMessage *reply = net()->CreateMessage(TSVC_USERCREATED);
				CNetAddress addr;
				addr.SetIP(user.ip);
				addr.SetPort(user.port);
				reply->SetNetAddress(addr);
				reply->SetEncrypted(true);
				char *msg = "Could not create new account.\nUser with that email address already exists.";
				reply->WriteString("error", msg);

				net()->SendMessage(reply, NET_RELIABLE);
			}

			// check to see if we've received a response from each DB
			user.resultsNeeded--;
			if (user.resultsNeeded == 0)
			{
				if (!user.failed)
				{
					// user is ok, reserve a userID for them
					g_pDataManager->TrackerDistro()->ReserveUserID(this, user.email, user.password, user.userName, user.firstName, user.lastName, user.ip, user.port);
				}

				// remove the user
				m_CreateUsers.Remove(response->temporaryID);
			}
		}
	}
	else if (cmdID == CMD_RESERVEUSERID)
	{
		// we've got a userID back 
		ITrackerDistroDatabase::ReserveUserID_t *user = (ITrackerDistroDatabase::ReserveUserID_t *)data;
		int userID = returnVal;
		if (userID < 1)
		{
			// send back an error message
			ISendMessage *reply = net()->CreateMessage(TSVC_USERCREATED);
			CNetAddress addr;
			addr.SetIP(user->ip);
			addr.SetPort(user->port);
			reply->SetNetAddress(addr);
			reply->SetEncrypted(true);

			reply->WriteUInt("newUID", userID);
			if (returnVal == -1)
			{
				// bad ID, write out an error string
				char *msg = "Could not create new account.\nUser with that email address already exists.";
				reply->WriteString("error", msg);
			}
			else if (returnVal < 1)
			{
				char *msg = "Server could not create user.\nPlease try again at another time.";
				reply->WriteString("error", msg);
			}
			
			net()->SendMessage(reply, NET_RELIABLE);
			return;	// don't continue
		}

		// success, create the user entry in the database in the reserved slot
		g_pDataManager->TrackerUser(userID)->User_Create(this, userID, user->email, user->password, user->username, user->firstname, user->lastname, user->ip, user->port);
	}
	else if (cmdID == CMD_CREATE)
	{
		ITrackerUserDatabase::UserCreate_t *response = (ITrackerUserDatabase::UserCreate_t *)data;

		// build and reply with a create user success message
		ISendMessage *reply = net()->CreateMessage(TSVC_USERCREATED);
		CNetAddress addr;
		addr.SetIP(response->IP);
		addr.SetPort(response->Port);
		reply->SetNetAddress(addr);
		reply->SetEncrypted(true);

		unsigned int newUID = returnVal;
		reply->WriteUInt("newUID", newUID);
		if (returnVal < 1)
		{
			char *msg = "Server could not create user.\nPlease try again at another time.";
			reply->WriteString("error", msg);
		}
		
		net()->SendMessage(reply, NET_RELIABLE);

		g_pConsole->Print( 1, "Sending UserCreated(%d) message to '%s'\n", returnVal, reply->NetAddress().ToStaticString() );
	}
}

//-----------------------------------------------------------------------------
// Purpose: Returns number of active users on server
//-----------------------------------------------------------------------------
int CSessionManager::ActiveUserCount()
{
	return m_IDMap.Count();
}

//-----------------------------------------------------------------------------
// Purpose: Returns maximum number of users holdable
//-----------------------------------------------------------------------------
int CSessionManager::MaxUserCount()
{
	return m_UserSessions.Size();
}

//-----------------------------------------------------------------------------
// Purpose: Displays current list of users on the server
//-----------------------------------------------------------------------------
void CSessionManager::PrintUserList()
{
	g_pConsole->Print(9, "UID\tSTATUS\tUSERNAME\t\t\tIP ADDRESS\n");

	for (int i = 0; i < m_UserSessions.Size(); i++)
	{
		CUserSession &session = m_UserSessions[i];
		if (session.State() == USERSESSION_ACTIVE)
		{
			CNetAddress addr;
			addr.SetIP(session.IP());
			addr.SetPort(session.Port());
			g_pConsole->Print(9, "%d\t%d\t%s\t\t\t%s\n", session.UID(), session.Status(), session.UserName(), addr.ToStaticString());
		}
	}
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -