📄 usersession.cpp
字号:
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 + -