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

📄 usersession.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	if (buildNum < MINIMUM_BUILD_NUMBER)
	{
		// send login failed message
		m_iStatus = 0;

		ISendMessage *reply = net()->CreateReply(TSVC_LOGINFAIL, pMsg);
		reply->WriteInt("reason", -4);
		SendMessage(reply, NET_RELIABLE);
		m_iUserSessionState = USERSESSION_CONNECTFAILED;
		sessionmanager()->FreeUserSession(this);
		return;
	}

	m_iUserSessionState = USERSESSION_ACTIVE;

	m_iBuildNum = buildNum;

	if (status < 1)
	{
		status = 1;
	}

	// record heartbeat rate
	m_flTimeoutDelay = (heartBeatRateMillis / 1000.0f) + USER_TIMEOUT_SLOP;

	// try and login
	m_pDB->User_Login(this, m_iUserID, m_szPassword, m_NetAddress.IP(), m_NetAddress.Port(), sessionID, status, buildNum);

	// now wait on reply, handled in SQLDBResponse()
}

//-----------------------------------------------------------------------------
// Purpose: Heartbeat message received from user
//			Performs keepalive actions for the user
//-----------------------------------------------------------------------------
void CUserSession::ReceivedMsg_Heartbeat(IReceiveMessage *pMsg)
{
	int status;
	pMsg->ReadInt("status", status);

	g_pConsole->Print(1, "Heartbeat userid: %d  status: %d\n", m_iUserID, status);

	// check to see if we have any game info
	bool updateGameInfo = false;
	bool updateStatusInfo = false;

	if (status != m_iStatus)
	{
		m_iStatus = status;
		updateStatusInfo = true;
	}

	if (status == STATUS_INGAME)
	{
		unsigned int ip, port;
		pMsg->ReadUInt("GameIP", ip);
		pMsg->ReadUInt("GamePort", port);

		if (ip != m_iGameIP && port != m_iGamePort)
		{
			updateGameInfo = true;
			pMsg->ReadString("Game", m_szGameType, sizeof(m_szGameType));
			m_iGameIP = ip;
			m_iGamePort = port;
		}
	}
	else
	{
		// clear the game info if they're not in a game
		m_iGameIP = 0;
		m_iGamePort = 0;
		m_szGameType[0] = 0;
	}

	// check for heartbeat rate update
	int heartBeatRateMillis;
	if (pMsg->ReadInt("hrate", heartBeatRateMillis))
	{
		m_flTimeoutDelay = (heartBeatRateMillis / 1000.0f) + USER_TIMEOUT_SLOP;
	}

	if (updateGameInfo || updateStatusInfo)
	{
		// 0 status is a log off message
		if (m_iStatus < 1)
		{
			// log the user off the server
			Logoff(false, false, false);
			return;
		}
		else
		{
			// update the status in the DB
			m_pDB->User_Update(m_iUserID, m_iStatus, m_iGameIP, m_iGamePort, m_szGameType);

			// tell the new status to friends
			UpdateStatusToFriends();
		}
	}

	// see if we need to update their status
	if (m_bUpdateFirewallWindowToClient)
	{
		// send them a heartbeat with their new firewall window
		ISendMessage *msg = CreateUserMessage(TSVC_HEARTBEAT);
		msg->WriteInt("FirewallWindow", (int)m_flFirewallWindow);
	}

	// check for messages
	CheckForMessages();
}

//-----------------------------------------------------------------------------
// Purpose: Generic message routing to a friend
//-----------------------------------------------------------------------------
void CUserSession::ReceivedMsg_RouteToFriend(IReceiveMessage *dataBlock)
{
	// parse out details
	int msgID;
	unsigned int userID, sessionID, serverID = 0;
	dataBlock->ReadInt("rID", msgID);
	dataBlock->ReadUInt("rUserID", userID);
	dataBlock->ReadUInt("rSessionID", sessionID);
	dataBlock->ReadUInt("rServerID", serverID);

	// parse out the message to be routed
	char buf[1300];
	int bytesRead = dataBlock->ReadBlob("rData", buf, sizeof(buf));

	// route the message through a different server
	topology()->SendNetworkMessageToUser(userID, sessionID, serverID, msgID, buf, bytesRead);
}

//-----------------------------------------------------------------------------
// Purpose: REDUNDANT: Message from user to be redirected to a friend
//			this function has been replaced by RouteToFriend and should be deleted
//-----------------------------------------------------------------------------
void CUserSession::ReceivedMsg_Message(IReceiveMessage *pMsg)
{
	// parse out redirection info
	unsigned int fsessionID, fip, fport;
	pMsg->ReadUInt("FSID", fsessionID);
	pMsg->ReadUInt("FIP", fip);
	pMsg->ReadUInt("FPort", fport);

	// parse out message
	unsigned int userID, targetID;
	int status, chatID;
	char text[512], userName[32];
	pMsg->ReadUInt("uid", userID);

	// check userID match
	if (userID != m_iUserID)
		return;

	pMsg->ReadUInt("targetID", targetID);
	pMsg->ReadString("UserName", userName, sizeof(userName));
	pMsg->ReadInt("status", status);
	pMsg->ReadString("Text", text, sizeof(text));
	pMsg->ReadInt("chatID", chatID);

	// write out redirected message
	ISendMessage *msg = net()->CreateMessage(TSVC_MESSAGE);
	CNetAddress addr;
	addr.SetIP(fip);
	addr.SetPort(fport);
	msg->SetNetAddress(addr);
	msg->SetEncrypted(true);
	msg->SetSessionID(fsessionID);
	
	msg->WriteUInt("uid", m_iUserID);
	msg->WriteUInt("targetID", targetID);
	msg->WriteString("UserName", userName);
	msg->WriteInt("status", status);
	msg->WriteString("Text", text);
	if (chatID)
	{
		msg->WriteInt("chatID", chatID);
	}
 
	SendMessage(msg, NET_RELIABLE);
}

//-----------------------------------------------------------------------------
// Purpose: Disconnects the user from the server
//-----------------------------------------------------------------------------
void CUserSession::Logoff(bool forced, bool fastReconnect, bool permanentDisconnect)
{
	if (!m_iUserID || !m_pDB)
		return;

	m_iStatus = 0;

	if (!forced)
	{
		g_pConsole->Print(4, "Logging off: %d (user requested)\n", m_iUserID);
	}
	else
	{
		if (permanentDisconnect)
		{
			g_pConsole->Print(4, "Logging off: %d (overriding login)\n", m_iUserID);
		}
		else if (fastReconnect)
		{
			g_pConsole->Print(4, "Logging off: %d (timed out)\n", m_iUserID);
		}
		else
		{
			g_pConsole->Print(4, "Logging off: %d (range lock or flush)\n", m_iUserID);
		}
	}

	// then log them off
	m_pDB->User_Logoff(this, m_iUserID, false);

	if (forced)
	{
		// send disconnect message to user
		ISendMessage *msg = CreateUserMessage(TSVC_DISCONNECT);

		// tell user to reconnect at a random time within the range (in seconds)
		if (permanentDisconnect)
		{
			msg->WriteInt("minTime", 0);
			msg->WriteInt("maxTime", 0);
			msg->WriteInt("logoffMsg", 1);
		}
		else if (fastReconnect)
		{
			msg->WriteInt("minTime", 1);
			msg->WriteInt("maxTime", 5);
		}
		else
		{
			msg->WriteInt("minTime", 5);
			msg->WriteInt("maxTime", 15);
		}

		// just send the message (don't go through the normal send path)
		net()->SendMessage(msg, NET_RELIABLE);
	}

	// empty the message queue
	FlushMessageQueue();

	// wait for result to return
}

//-----------------------------------------------------------------------------
// Purpose: Sends the users' current status to all their watchers
//-----------------------------------------------------------------------------
void CUserSession::UpdateStatusToFriends()
{
	m_pDB->User_GetWatchers(this, m_iUserID);
}

//-----------------------------------------------------------------------------
// Purpose: Checks for and sends the user and messages they having waiting for them
//-----------------------------------------------------------------------------
void CUserSession::CheckForMessages()
{
	// look to see if we have any messages
	m_pDB->User_GetMessage(this, m_iUserID);
}

//-----------------------------------------------------------------------------
// Purpose: Searches the database for the set of users that match the criteria
//-----------------------------------------------------------------------------
void CUserSession::ReceivedMsg_FindUser(IReceiveMessage *msg)
{
	// the message contains search criteria to find a friend
	unsigned int iUID;
	char szEmail[128];
	char szUserName[32];
	char szFirstName[32];
	char szLastName[32];

	msg->ReadUInt("uid", iUID);
	msg->ReadString("Email", szEmail, 128);
	msg->ReadString("UserName", szUserName, 32);
	msg->ReadString("FirstName", szFirstName, 32);
	msg->ReadString("LastName", szLastName, 32);

	// search for the users
	if (iUID)
	{
		// only one user
		g_pDataManager->TrackerUser(iUID)->Find_Users(this, iUID, szEmail, szUserName, szFirstName, szLastName);
	}
	else
	{
		// look in each database
		for (int i = 0; i < g_pDataManager->TrackerUserCount(); i++)
		{
			g_pDataManager->TrackerUserByIndex(i).db->Find_Users(this, iUID, szEmail, szUserName, szFirstName, szLastName);
		}
	}

	// await replies from db
}

//-----------------------------------------------------------------------------
// Purpose: Authorizes a user
//-----------------------------------------------------------------------------
void CUserSession::ReceivedMsg_AuthUser(IReceiveMessage *msg)
{
	unsigned int iUID;
	int auth;

	msg->ReadUInt("targetID", iUID);
	msg->ReadInt("auth", auth);

	if (auth)
	{
		// Run the auth user DB command
		AuthorizeUser(iUID);
	}
	else
	{
		// it's a deny message, break the link between users
		UnauthUser(iUID);
	}
}

//-----------------------------------------------------------------------------
// Purpose: requesting authorization from a user
//-----------------------------------------------------------------------------
void CUserSession::ReceivedMsg_ReqAuth(IReceiveMessage *msg)
{
	unsigned int friendID;
	char szRequestReason[128];

	msg->ReadUInt("uid", friendID);
	msg->ReadString("ReqReason", szRequestReason, 128);

	// remove any block we have on that user
	m_pDB->User_SetBlock(m_iUserID, friendID, false);

	// get our current authorization state
	m_pDB->User_IsAuthed(this, STATE_REQUESTINGAUTH, m_iUserID, friendID, szRequestReason);
}

//-----------------------------------------------------------------------------
// Purpose: User is requesting an updated friends list
//-----------------------------------------------------------------------------
void CUserSession::ReceivedMsg_ReqFriends(IReceiveMessage *reqAuthMsg)
{
	// this is not supported, since the user should have always received the correct set of stati
}

//-----------------------------------------------------------------------------
// Purpose: Returns information about a single user to a user, but only
//			if they're authorized to see
//-----------------------------------------------------------------------------
void CUserSession::ReceivedMsg_FriendInfo(IReceiveMessage *reqFriendInfoMsg)
{
	unsigned int iUID;
	reqFriendInfoMsg->ReadUInt("uid", iUID);

	// check to see if we're authorized to get that info
	// always authorized to see our own info
	m_pDB->User_IsAuthed(this, STATE_GETFRIENDINFO, m_iUserID, iUID, NULL);
}

//-----------------------------------------------------------------------------
// Purpose: Updates the information regarding a user
//-----------------------------------------------------------------------------
void CUserSession::ReceivedMsg_SetInfo(IReceiveMessage *msg)
{
	unsigned int iUID;
	char szUser[32];
	char szFirst[32];
	char szLast[32];

	msg->ReadUInt("uid", iUID);
	msg->ReadString("UserName", szUser, 32);
	msg->ReadString("FirstName", szFirst, 32);
	msg->ReadString("LastName", szLast, 32);

	if (iUID != m_iUserID)
		return;

	// update information in database
	m_pDB->User_SetInfo(m_iUserID, szUser, szFirst, szLast);
}

//-----------------------------------------------------------------------------
// Purpose: Authorizes one use to be able to get the others IP address
//-----------------------------------------------------------------------------
void CUserSession::AuthorizeUser(unsigned int targetID)
{
	// remove any message blocks
	m_pDB->User_SetBlock(m_iUserID, targetID, false);

	// set up the two way link
	m_pDB->User_SetAuth(targetID, m_iUserID, AUTHLEVEL_FULLAUTH);
	m_pDB->User_SetAuth(m_iUserID, targetID, AUTHLEVEL_FULLAUTH);
	
	// add the link on both servers
	ITrackerUserDatabase *targetDB = g_pDataManager->TrackerUser(targetID);
	if (!targetDB)
		return;

	if (targetDB != m_pDB)
	{
		targetDB->User_SetAuth(targetID, m_iUserID, AUTHLEVEL_FULLAUTH);
		targetDB->User_SetAuth(m_iUserID, targetID, AUTHLEVEL_FULLAUTH);
	}

	// set the user up to watch us
	targetDB->User_GetSessionInfo(this, STATE_ADDWATCH, targetID);
	// put our watch on them
	targetDB->User_AddSingleWatch(m_iUserID, m_iSessionID, topology()->GetServerID(), targetID);

	// post a message to the user and have them check their messages right away
	PostMessageToUser(m_iUserID, targetID, "Authed", MESSAGEFLAG_AUTHED);
	targetDB->User_GetSessionInfo(this, STATE_CHECKMESSAGES, targetID);

	// send status both ways
	targetDB->User_GetSessionInfo(this, STATE_EXCHANGESTATUS, targetID);
}

//-----------------------------------------------------------------------------
// Purpose: Breaks the authorization links between two users, and blocks the users from rerequesting status
//-----------------------------------------------------------------------------
void CUserSession::UnauthUser(unsigned int targetID)
{
	// remove auth link
	// watchmaps are automatically modified
	m_pDB->User_RemoveAuth(targetID, m_iUserID);
	// remove the link on both servers if different
	if (g_pDataManager->TrackerUser(targetID) != m_pDB)
	{
		g_pDataManager->TrackerUser(targetID)->User_RemoveAuth(targetID, m_iUserID);
	}

	m_pDB->User_SetBlock(m_iUserID, targetID, true);

	// tell the user that we've gone offline
	g_pDataManager->TrackerUser(targetID)->User_GetSessionInfo(this, STATE_SENDINGOFFLINESTATUS, targetID);
}


//-----------------------------------------------------------------------------
// Purpose: Stores a message in the database for later collection by a user
//-----------------------------------------------------------------------------
void CUserSession::PostMessageToUser(unsigned int fromID, unsigned int targetID, const char *text, int flags)
{
	// store the message in the database and flag the user to collect it next time they log on / heartbeat
	const char *name = "";
	if (fromID == m_iUserID)
	{
		name = m_szUserName;
	}

	g_pDataManager->TrackerUser(targetID)->User_PostMessage(fromID, targetID, "Normal", text, name, flags);

	// tell the friend that they have a message waiting for them, so the auth request is instant
	g_pDataManager->TrackerUser(targetID)->User_GetSessionInfo(this, STATE_CHECKMESSAGES, targetID);
}

//-----------------------------------------------------------------------------
// Purpose: Wraps the TrackerNET send message
//-----------------------------------------------------------------------------
void CUserSession::SendMessage(ISendMessage *SendMessage, Reliability_e state)
{
	float currentTime = sessionmanager()->GetCurrentTime();
	// check to see if firewall window is open
	if (m_flLastAccess + m_flFirewallWindow > currentTime)
	{
		// just send the message
		net()->SendMessage(SendMessage, state);
	}

⌨️ 快捷键说明

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