Files
mir_server/server/LogicServer/gate/LogicGate.cpp
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

1136 lines
35 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "LogicGate.h"
int CLogicGate::s_nMaxPacketSizes = 0;
CLogicGate::CLogicGate()
:Inherited()
{
m_pLogicServer = NULL;
m_vFreeList.setLock(&m_vFreeListLock);
AddAllGateUsersToFreeList();
m_pSendToGatePacket = NULL;
m_ullSendPacketSize = 0;
m_bUseBigPacket = true;
}
CLogicGate::~CLogicGate()
{
//释放datapacket
m_vFreeList.flush();
for(int i = 0; i < m_vFreeList.count(); i++)
{
CDataPacket* dp = m_vFreeList[i];
if ( dp )
{
dp->setPosition(0);
flushSendPacket(*dp);
}
}
m_vFreeList.clear();
for(int i = 0; i < m_vMsgList.count(); i++)
{
CDataPacket* dp = m_vMsgList[i];
if ( dp )
{
dp->setPosition(0);
flushSendPacket(*dp);
}
}
m_vMsgList.clear();
//最后的包发向网关:),实际为了释放这个包的内存
SendToGate();
}
VOID CLogicGate::AddAllGateUsersToFreeList()
{
int i;
m_FreeUserList.clear();
for ( i=ArrayCount(m_GateUsers)-1; i>-1; --i )
{
CLogicGateUser* pGateUser = &m_GateUsers[i];
if ( pGateUser )
{
m_FreeUserList.add( pGateUser );
}
}
}
CCustomServerGateUser* CLogicGate::CreateGateUser()
{
INT_PTR nCount = m_FreeUserList.count();
if ( nCount > 0 )
{
nCount--;
CCustomServerGateUser* pUser = m_FreeUserList[nCount];
m_FreeUserList.trunc(nCount);
return pUser;
}
return NULL;
}
VOID CLogicGate::DestroyGateUser(CCustomServerGateUser* pUser)
{
if ( pUser )
{
m_FreeUserList.add((CLogicGateUser*)pUser);
}
}
VOID CLogicGate::OnOpenUser(CCustomServerGateUser *pGateUser)
{
if ( !pGateUser )
{
return;
}
CLogicGateUser* pLogicGateUser = (CLogicGateUser*)pGateUser;
//NOTIFY the logicServer
//GetGlobalLogicEngine()->PostInternalMessage(SSM_GATE_CREATE_ACTOR,)
//create the user
//使用当前的tickcount以及一个随机数生成一个key用作玩家的本次的校验的
UINT64 key=0;
UINT64 nTick= (UINT64)pGateUser->nSocket; //当前的tickcount
UINT64 nRandValue = wrandvalue(); //一个随机数
//如果是0.那么就设置一个数避免出现key=0
if(nRandValue ==0)
{
nRandValue =0xffee1133;
}
key = (nRandValue << 32 | nTick) ;
pLogicGateUser->lLogicKey = key; //玩家的key
pLogicGateUser->nGlobalSessionId = 0;
pLogicGateUser->sAccount[0] = 0;
pLogicGateUser->nCharId = 0;
pLogicGateUser->sCharName[0] = 0;
pLogicGateUser->nHandleIndex =0;
pLogicGateUser->boHasSecPsw = false;
pLogicGateUser->boCheckSecPswSucess = false;
pLogicGateUser->boWhiteIpLogin = false;
OutputMsg(rmTip,_T("[Login] (3) 添加一个玩家Gate logickey(%lld)socket(%lld)GateIdx(%d)LogicIdx(%d)CurrentThreadId(%d)。"),
pLogicGateUser->lLogicKey,pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex,GetCurrentThreadId());
}
//通过key返回指针
CLogicGateUser * CLogicGate::GetGateUserByKey(UINT64 lKey)
{
CLogicGateUser *pUser ;
for(INT_PTR i=0; i< m_UserList.count(); i++)
{
pUser = (CLogicGateUser *)m_UserList[i];
if(pUser && pUser->lLogicKey == lKey)
{
return pUser;
}
}
return NULL;
}
//nServerSessionIndex, nHandleIndex,nAccountId
VOID CLogicGate::DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4)
{
Inherited::DispatchInternalMessage(uMsg,uParam1,uParam2,uParam3,uParam4); //先执行父类的消息处理
if(uMsg == SSM_RECV_LOGIN_DATA)
{
//会话服务器发来的
if(uParam1 == jxInterSrvComm::SessionServerProto::sCheckPasswdResult) //数据服发来玩家的登陆失败的信息
{
CDataPacket* pDataPacket = (CDataPacket*)uParam2; //数据包的指针
if(pDataPacket)
{
pDataPacket->setPosition(0);
CCustomGlobalSession session;
memset(&session,0,sizeof(session));
*pDataPacket >> session;
GetLogicServer()->GetSessionClient()->FreeBackUserDataPacket(pDataPacket);
CLogicGateUser *pGateUser = GetGateUserByKey(session.lKey);
if(pGateUser )
{
pGateUser->boWhiteIpLogin = (session.nState ==0) ?true:false;
//ResponseLoginErrorAndCloseUser(pGateUser,0,session.nSessionId);
//这里要向数据服发消息,取玩家的角色列表
pGateUser->nGlobalSessionId = session.nSessionId;
strncpy(pGateUser->sAccount,session.sAccount,sizeof(pGateUser->sAccount));
SendDbGetActorList(pGateUser); //向数据服发消息,获取角色的列表
}
else
{
//OutputMsg(rmError,"收到会话发来的校验密码结果,但是找不到会话的key=%lld",session.lKey);
OutputMsg(rmTip,_T("[Login] (8) logickey找不到对应的玩家gate logickey(%lld)CurrentThreadId(%d)。"),
session.lKey,GetCurrentThreadId());
}
}
}
//数据服务器发来的
else if( jxInterSrvComm::DbServerProto::dcGetActorList ==uParam1
|| jxInterSrvComm::DbServerProto::dcCreateActor ==uParam1
|| jxInterSrvComm::DbServerProto::dcDeleteActor ==uParam1
|| jxInterSrvComm::DbServerProto::dcGetRandName ==uParam1
|| jxInterSrvComm::DbServerProto::dcCheckSecondPsw == uParam1
|| jxInterSrvComm::DbServerProto::dcCreateSecondPsw == uParam1
)
{
CDataPacket* pDataPacket = (CDataPacket*)uParam2; //数据包的指针
if(pDataPacket)
{
pDataPacket->setPosition(0);
Uint64 lKey =0;
*pDataPacket >>lKey; //读取key
CLogicGateUser *pUser = GetGateUserByKey(lKey);
if(pUser )
{
BYTE cmd =0;
switch(uParam1)
{
case jxInterSrvComm::DbServerProto::dcGetActorList:
cmd=sGetUserList;
break;
case jxInterSrvComm::DbServerProto::dcCreateActor:
cmd=sCreateActor;
break;
case jxInterSrvComm::DbServerProto::dcDeleteActor:
cmd=sDeleteActor;
break;
case jxInterSrvComm::DbServerProto::dcGetRandName:
cmd=sRandNameActor;
break;
case jxInterSrvComm::DbServerProto::dcCheckSecondPsw:
cmd=sCheckSecondPswResult;
break;
case jxInterSrvComm::DbServerProto::dcCreateSecondPsw:
cmd=sCreateSecondPswRessult;
break;
}
CDataPacket &dataPack = AllocGateSendPacket(pUser->nSocket,pUser->nGateSessionIndex,pUser->nServerSessionIndex);
dataPack <<(BYTE)enLoginSystemId << (BYTE) cmd ;
//名字的随机需要特殊处理,把玩家的账户弄过来
if(cmd == sRandNameActor)
{
BYTE bErrorCode =0,bSex=0;
*pDataPacket >> pUser->nLastRandNameIndex >>bErrorCode >> bSex ;
dataPack << bErrorCode << bSex;
if(bErrorCode ==0 && pUser->nLastRandNameIndex >=0 )
{
pDataPacket->readString(pUser->sLastRandName,sizeof(pUser->sLastRandName));
dataPack.writeString(pUser->sLastRandName);
}
}
else if( cmd == sGetUserList)
{
INT_PTR nLength = pDataPacket->getLength();
INT_PTR nOffer = pDataPacket->getPosition();
pDataPacket->setPosition(nLength - 1);
BYTE btCode = 0;
*pDataPacket >> btCode;
if ( btCode == 3 )
{
pUser->boHasSecPsw = true;
}
else
{
pUser->boHasSecPsw = false;
}
pDataPacket->setPosition(nOffer);
dataPack << (int)(GetLogicServer()->GetDaysSinceOpenServer());
BYTE canCreate = 1;
int nNosetopenday = GetLogicServer()->GetDataProvider()->GetEditionProvider().GetEditionInfo().nNoSetOpenDay;
if( nNosetopenday > 0 && (GetLogicServer()->GetDaysSinceOpenServer() > nNosetopenday))
{
canCreate = 0;
}
dataPack <<(BYTE)canCreate;
dataPack.writeBuf(pDataPacket->getOffsetPtr(),pDataPacket->getLength() - pDataPacket->getPosition());
OutputMsg(rmTip,_T("[Login] (9) 发送角色列表: logickey(%lld)socket(%lld)GateIdx(%d)LogicIdx(%d)SessId(%d), CurrentThreadId(%d)。"),
pUser->lLogicKey,pUser->nSocket,pUser->nGateSessionIndex,pUser->nServerSessionIndex,pUser->nGlobalSessionId,GetCurrentThreadId());
if ( !GetGlobalLogicEngine()->GetLoginSecondPswFlag() )
{
OutputMsg(rmWaning,_T("secondPsw account%u-thread%u "),pUser->nGlobalSessionId,GetCurrentThreadId());
}
}
else if (cmd == sCheckSecondPswResult)
{
BYTE btError = 1;
*pDataPacket >> btError;
if ( btError == 0 || GetGlobalLogicEngine()->GetSecondPswFlag() || pUser->boWhiteIpLogin)
{
pUser->boCheckSecPswSucess = true;
btError = 0;
}
dataPack << (BYTE)btError;
}
else
{
dataPack.writeBuf(pDataPacket->getOffsetPtr(),pDataPacket->getLength() - pDataPacket->getPosition());
}
FlushGateSendPacket(dataPack);
}
else
{
OutputMsg(rmError,"收到数据服发来的校验密码结果,但是找不到会话的key=%lld,cmd=%d",lKey,(int)uParam1 );
}
GetLogicServer()->GetDbClient()->FreeBackUserDataPacket(pDataPacket);
}
}
else if( jxInterSrvComm::SessionServerProto::sSimulateCheckPasswdResult ==uParam1 )
{
{
Uint64 lKey =(Uint64)uParam2;
CLogicGateUser *pUser = GetGateUserByKey(lKey);
if(pUser )
{
CDataPacket &dataPack = AllocGateSendPacket(pUser->nSocket,pUser->nGateSessionIndex,pUser->nServerSessionIndex);
dataPack <<(BYTE)enLoginSystemId << (BYTE) sCrossServerInit ;
dataPack << (unsigned int)uParam4;
FlushGateSendPacket(dataPack);
}
else
{
OutputMsg(rmError,"跨服模拟发来的校验密码结果,但是找不到会话的key=%lld,cmd=%d",lKey,(int)uParam1 );
}
}
}
}
else if(uMsg == SSM_RECV_LOGIN_CMD) //收到了数据
{
if( uParam1 == jxInterSrvComm::SessionServerProto::sCheckPasswdResult) //登陆的结果
{
Uint64 lKey =uParam2;
BYTE bErrorCode =(BYTE)uParam3;
CLogicGateUser *pGateUser = GetGateUserByKey(lKey);
if(pGateUser )
{
if(bErrorCode !=0)
{
ResponseLoginErrorAndCloseUser(pGateUser,bErrorCode);
//OutputMsg(rmWaning,"用户session检测失败,code=%dkey=%lld",(int)bErrorCode,lKey);
//CloseUser(pGateUser->nSocket,pGateUser->nServerSessionIndex); //数据服没有连上来
OutputMsg(rmTip,_T("[Login] (7) 账户验证失败: logickey(%lld)socket(%lld)GateIdx(%d)LogicIdx(%d)SessId(%d), CurrentThreadId(%d)Errer%d"),
pGateUser->lLogicKey,pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex,pGateUser->nGlobalSessionId,GetCurrentThreadId(),bErrorCode);
}
else
{
OutputMsg(rmWaning,"actor check passwd from session,errorcode=%dkey=%lld",(int)bErrorCode,lKey);
}
}
else
{
//OutputMsg(rmError,"收到会话发来的校验密码结果,code=%d但是找不到会话的key=%lld",(int)bErrorCode,lKey);
OutputMsg(rmTip,_T("[Login] (7) 账户验证失败且logickey找不到对应的玩家gate logickey(%lld)CurrentThreadId(%d)Errer%d"),
lKey,GetCurrentThreadId(),bErrorCode);
}
}
}
else if(uMsg == SSM_GATE_CREATE_ACTOR)
{
//nServerSessionIndex
//nHandleIndex
//nAccountId
bool isValid = true;
if(uParam1 <0 || uParam1 >= (UINT_PTR)m_UserList.count() )
{
OutputMsg(rmWaning,_T("SSM_GATE_CREATE_ACTOR nServerSessionIndex=%u,to large"),uParam1);
isValid =false;
}
if(isValid)
{
CLogicGateUser * pUser =(CLogicGateUser *) m_UserList[uParam1];
if(pUser ==NULL)
{
OutputMsg(rmWaning,_T("CREATE ACTOR FAIL FOR THE nGateServerIndex=%d, not existing"),uParam1);
isValid =false;
}
else
{
if(pUser->nGlobalSessionId != uParam3)
{
OutputMsg(rmWaning,_T("CREATE ACTOR FAIL,accouid =%d ,local accountid=%d"),pUser->nGlobalSessionId,uParam3);
isValid =false;
}
if(isValid && pUser->nHandleIndex !=0)
{
OutputMsg(rmWaning,_T("CREATE ACTOR FAIL,nHandleIndex!=0 ,nServerSessionIndex=%d"),uParam1);
isValid =false;
//return; //已经设置过了handle了
}
//OutputMsg(rmTip,_T("CREATE ACTOR nHandleIndex=%d"),uParam3);
if(uParam2 ==0) //create entity fail
{
OutputMsg(rmWaning,_T("CREATE ACTOR FAIL FOR THE nServerSessionIndex=%d"),uParam2);
isValid =false;
CloseUser(pUser->nSocket,pUser->nServerSessionIndex); //CLOSE the session
}
else
{
pUser->nHandleIndex = (unsigned int)uParam2;
}
}
}
if(isValid ==false)
{
GetGlobalLogicEngine()->GetNetWorkHandle()->PostInternalMessage(SSM_GATE_USER_LOGOUT,uParam3);
}
}
else if(uMsg == SSM_KICK_USER)
{
CLogicGateUser * pUser=GetGateUserByKey(uParam2);
if(pUser ==NULL) return;
PostCloseUser(pUser->nSocket);
}
else if(SSM_CLOSE_SERVER == uMsg) //关闭服务器
{
PostCloseGateServer();
}
}
VOID CLogicGate::KickUserByGlobalSessionId(const int nGlobalSessionId)
{
INT_PTR nIndex;
CCustomServerGateUser *pUserList = UserExistsOfGlobalSessionId(nGlobalSessionId, &nIndex);
if ( pUserList )
{
CLogicGateUser* pLogicGateUser = (CLogicGateUser*)pUserList;
GetGlobalLogicEngine()->GetNetWorkHandle()->PostInternalMessage(SSM_SESSION_KICK_USER,pLogicGateUser->nGlobalSessionId);
}
}
VOID CLogicGate::OnCloseUser(CCustomServerGateUser *pGateUser)
{
if ( !pGateUser )
{
return;
}
CLogicGateUser* pLogicGateUser = (CLogicGateUser*)pGateUser;
int nSessionId = pLogicGateUser->nGlobalSessionId;
OutputMsg(rmTip,_T("CLogicGate::OnCloseUser. socket=%d, sessionId=%d, serverId=%d, accountId=%u, thread=%u"), (int)pGateUser->nSocket,
(int)pGateUser->nGateSessionIndex, (int)pGateUser->nServerSessionIndex, nSessionId,GetCurrentThreadId());
if ( nSessionId != 0 && m_pLogicServer )
{
GetGlobalLogicEngine()->GetNetWorkHandle()->PostInternalMessage(SSM_GATE_USER_LOGOUT,nSessionId,pLogicGateUser->lLogicKey);
}
pLogicGateUser->nGlobalSessionId = 0;
pLogicGateUser->sAccount[0] = 0;
pLogicGateUser->nCharId = 0;
pLogicGateUser->sCharName[0] = 0;
pLogicGateUser->nHandleIndex =0;
pLogicGateUser->lLogicKey =0;
pLogicGateUser->boCheckSecPswSucess = false;
pLogicGateUser->boHasSecPsw = false;
pLogicGateUser->boWhiteIpLogin = false;
//这个玩家关闭连接了,需要通知会话
}
VOID CLogicGate::OnGateClosed()
{
}
//收到了登陆包,先判断一下是否已经登陆了,如果能够登陆就通知逻辑服务器
VOID CLogicGate::OnUserLogin(CLogicGateUser *pGateUser,unsigned nAccountID, unsigned nActorID,int nLoginIndex)
{
//jxSrvDef::GLOBALSESSIONOPENDATA sessionData;
if ( !pGateUser )
{
return;
}
pGateUser->nGlobalSessionId = nAccountID; //帐户id也就是全局的sessionID
pGateUser->nCharId = nActorID;
//OutputMsg(rmNormal, _T("CLogicGate::OnUserLogin: socket=%d, sessionId=%d, serverId=%d, accountId=%u, actorid=%u"), (int)pGateUser->nSocket,
// (int)pGateUser->nGateSessionIndex, (int)pGateUser->nServerSessionIndex, nAccountID, nActorID);
OutputMsg(rmTip,_T("[Login] (10) 收到玩家登陆角色请求: logickey(%lld)socket(%lld)GateIdx(%d)LogicIdx(%d)SessId(%d), AccountId(%u)ActorId(%d)CurrentThreadId(%d)。"),
pGateUser->lLogicKey,pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex,pGateUser->nGlobalSessionId, nAccountID, nActorID,GetCurrentThreadId());
//获取是否有这个用户在
bool isValid =true;
INT_PTR nErrorID =0;
int nServerIndex = 0; // TODO.这里客户端登录的时候传递ServerIndex数据
//通知逻辑有人登陆了
GetGlobalLogicEngine()->GetNetWorkHandle()->PostInternalMessage(SSM_GATE_CREATE_ACTOR,
(UINT_PTR)pGateUser->nSocket,
nActorID,
m_nGateIndex,
pGateUser->nGateSessionIndex,
pGateUser->nServerSessionIndex,
pGateUser->nGlobalSessionId,
pGateUser->lLogicKey,
nLoginIndex
);
}
//告诉玩家的结果
void CLogicGate::ResponseLoginErrorAndCloseUser(CLogicGateUser *pUser,int nErrorCode)
{
if ( !pUser )
{
return;
}
//向用户发消息,登陆失败
CDataPacket &dataPack = AllocGateSendPacket(pUser->nSocket,pUser->nGateSessionIndex,pUser->nServerSessionIndex);
dataPack <<(BYTE)enLoginSystemId << (BYTE) sLoginErrorCode << (BYTE)nErrorCode ;
FlushGateSendPacket(dataPack);
OutputMsg(rmWaning,"login close user,errocode=%d",nErrorCode);
//这里先不踢下线,让客户端主动断开连接
if(pUser->nSocket != INVALID_SOCKET)
{
//CloseUser(pUser->nSocket,pUser->nServerSessionIndex); //CLOSE the session
//PostCloseUser();
//PostCloseUser(pUser->nSocket,pUser->nServerSessionIndex);
}
}
//转发到会话服务器的
void CLogicGate::Client2SesionCheckUserPasswd(CDataPacketReader &pack,CLogicGateUser* pLogicGateUser)
{
//首先检测会话服和数据服是否是ok的如果没有ok告诉玩家不能登陆
if( m_pLogicServer->GetSessionClient()->connected())
{
if( m_pLogicServer->GetDbClient()->connected() )
{
CLogicSSClient* pSSClient = GetLogicServer()->GetSessionClient();
if(pSSClient)
{
CDataPacket &data = pSSClient->allocProtoPacket(jxInterSrvComm::SessionServerProto::cLogicCheckPasswd); //发给会话校验密码
TCHAR name[ACCOUNT_NAME_BUFF_LENGTH];
TCHAR passwd[MAX_PASSWD_LENGTH];
char identity[64]; //身份证号码
name[0]=0;
passwd[0]=0;
identity[0] =0;
int nLoginServerId =0; // 要登陆的服务器的编号
int nRawServerId =0; // 要登陆的服务器的编号
pack.readString(name,sizeof(name));
pack.readString(passwd,sizeof(passwd));
pack >> nLoginServerId;
pack >> nRawServerId;
pLogicGateUser->nRawServerIndex = nRawServerId;
data << (Uint64)pLogicGateUser->lLogicKey; //发key过去
data.writeString(name);
data.writeString(passwd);
data << (int)nLoginServerId; //要登陆的服务器id
data << (int)nRawServerId; //要连接的服务器的id
data << (int)m_nGateIndex; //将网关的编号发过去
unsigned long long sip = (inet_addr(pLogicGateUser->sIPAddr));
data << sip; //将登陆的ip发过去
char md5[64];
char currenttime[32];
md5[0]=0;
currenttime[0] =0;
data << BYTE(1); //增加1个字节过去表示需要校验md5值
if(pack.getAvaliableLength() >0)
{
pack.readString(md5,sizeof(md5));
data.writeString(md5);
}
if(pack.getAvaliableLength() >0)
{
pack.readString(currenttime,sizeof(currenttime));
data.writeString(currenttime);
}
//读取身份证号码
if(pack.getAvaliableLength() >0)
{
pack.readString(identity,sizeof(identity));
data.writeString(identity);
}
pSSClient->flushProtoPacket(data);
OutputMsg(rmTip,_T("[Login] (6) 发送到SessionServer验证账号 AccountName(%s), logickey(%lld)socket(%lld)GateIdx(%d)LogicIdx(%d)CurrentThreadId(%d)。"),
name,pLogicGateUser->lLogicKey,pLogicGateUser->nSocket,pLogicGateUser->nGateSessionIndex,pLogicGateUser->nServerSessionIndex,GetCurrentThreadId());
}
}
else
{
ResponseLoginErrorAndCloseUser(pLogicGateUser,enDbServerClose);
OutputMsg(rmError,_T("[Login] (6) CDataClient获取失效(数据服没连接) logickey(%lld)socket(%lld)GateIdx(%d)LogicIdx(%d)CurrentThreadId(%d)。"),
pLogicGateUser->lLogicKey,pLogicGateUser->nSocket,pLogicGateUser->nGateSessionIndex,pLogicGateUser->nServerSessionIndex,GetCurrentThreadId());//数据服没有连上来
return ;
}
}
else
{
ResponseLoginErrorAndCloseUser(pLogicGateUser,enSessionServerClose);
OutputMsg(rmError,_T("[Login] (6) CLogicSSClient获取失效(会话服没连接) logickey(%lld)socket(%lld)GateIdx(%d)LogicIdx(%d)CurrentThreadId(%d)。"),GetCurrentThreadId());//玩家登陆的时候,会话或者数据服是关闭的
return ;
}
}
//向会话服务器创建账户
void CLogicGate::Client2SesionCreateAccount(CDataPacketReader &pack,CLogicGateUser* pGateUser)
{
//首先检测会话服和数据服是否是ok的如果没有ok告诉玩家不能登陆
if( m_pLogicServer->GetSessionClient()->connected())
{
if( m_pLogicServer->GetDbClient()->connected() )
{
CLogicSSClient* pSSClient = GetLogicServer()->GetSessionClient();
if(pSSClient)
{
CDataPacket &data = pSSClient->allocProtoPacket(jxInterSrvComm::SessionServerProto::cLogicCreateAccount); //发给会话校验密码
TCHAR name[ACCOUNT_NAME_BUFF_LENGTH];
TCHAR passwd[MAX_PASSWD_LENGTH];
TCHAR identity[128];
name[0]=0;
passwd[0]=0;
identity[0] =0;
pack.readString(name,sizeof(name));
pack.readString(passwd,sizeof(passwd));
pack.readString(identity,sizeof(identity));
data.writeString(name);
data.writeString(passwd);
data.writeString(identity);
unsigned long long sip = (inet_addr(pGateUser->sIPAddr));
data << sip; //将登陆的ip发过去
pSSClient->flushProtoPacket(data);
}
}
else
{
ResponseLoginErrorAndCloseUser(pGateUser,enDbServerClose);
//CloseUser(pLogicGateUser->nSocket,pLogicGateUser->nServerSessionIndex); //数据服没有连上来
return ;
}
}
else
{
//OutputMsg(rmWaning,"actor login,but session or db is disconnect, login fail"); //玩家登陆的时候,会话或者数据服是关闭的
ResponseLoginErrorAndCloseUser(pGateUser,enSessionServerClose);
return ;
}
}
//获取玩家角色列表
void CLogicGate::SendDbGetActorList(CLogicGateUser* pGateUser)
{
if ( !pGateUser )
{
return;
}
CDataClient * pDbClient= m_pLogicServer->GetDbClient();
if(pDbClient ==NULL || !pDbClient->connected())
{
ResponseLoginErrorAndCloseUser(pGateUser,enDbServerClose);
OutputMsg(rmTip,_T("[Login] (8) 数据库连接失败,没法获取角色列表: logickey(%lld)socket(%lld)GateIdx(%d)LogicIdx(%d)SessId(%d), CurrentThreadId(%d)。"),
pGateUser->lLogicKey,pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex,pGateUser->nGlobalSessionId,GetCurrentThreadId());
}
else
{
//向数据服发消息,获取当前的玩家列表
CDataPacket &packet = pDbClient->allocProtoPacket(jxInterSrvComm::DbServerProto::dcGetActorList);
int nServerId = GetLogicServer()->GetServerIndex(); //当前的服务器的编号
int nRawServerId= pGateUser->nRawServerIndex ;
//协议约定key放在最前面
packet << nRawServerId << nServerId << (BYTE)m_nGateIndex <<pGateUser->lLogicKey << pGateUser->nGlobalSessionId ;
pDbClient->flushProtoPacket(packet);
OutputMsg(rmTip,_T("[Login] (8) 获取角色列表: logickey(%lld)socket(%lld)GateIdx(%d)LogicIdx(%d)SessId(%d), CurrentThreadId(%d)。"),
pGateUser->lLogicKey,pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex,pGateUser->nGlobalSessionId,GetCurrentThreadId());
}
}
void CLogicGate::Client2DbCreateActor(CDataPacketReader &reader,CLogicGateUser* pGateUser)
{
if ( !pGateUser )
{
return;
}
CDataClient * pDbClient= m_pLogicServer->GetDbClient();
if(pDbClient ==NULL || !pDbClient->connected())
{
ResponseLoginErrorAndCloseUser(pGateUser,enDbServerClose);
return;
}
char actorName[ACTOR_NAME_BUFF_LENGTH];
actorName[0]=0;
reader.readString(actorName,ArrayCount(actorName));
char Sex=0; //性别
char Job=0; //职业的编码
char Icon=0; //头像
BYTE Zy=0;
reader >>Sex >> Job >> Icon >> Zy ;
char strToken[MAX_TOKEN_LENGTH];
strToken[0] = 0;
reader.readString(strToken,ArrayCount(strToken));
int nAdid = 0;
reader >> nAdid;
BYTE nEnterId = 0;
//reader >> nEnterId;
CDataPacket &packet = pDbClient->allocProtoPacket(jxInterSrvComm::DbServerProto::dcCreateActor);
int nServerId = GetLogicServer()->GetServerIndex(); //当前的服务器的编号
int nRawServerId= pGateUser->nRawServerIndex ;
//IP地址
unsigned long long sip = (inet_addr(pGateUser->sIPAddr));
//协议约定key放在最前面
packet <<nRawServerId <<nServerId << (BYTE)m_nGateIndex << pGateUser->lLogicKey << pGateUser->nGlobalSessionId ;
packet << sip;
packet.writeString(actorName);
packet.writeString(pGateUser->sAccount); //账户名字
packet<< Sex <<Job << Icon << Zy;
bool bUseRandName =false;
if(pGateUser->nLastRandNameIndex >=0 )
{
if(strncmp(actorName,pGateUser->sLastRandName,sizeof(actorName)) ==0)
{
bUseRandName =true;
}
}
//如果是随机名字生效那么发上次的index上去
if(bUseRandName)
{
packet << pGateUser->nLastRandNameIndex;
}
else
{
packet <<(int) -1;
}
if(strToken[0] == 0)
{
packet.writeString(" ");
}
else
{
packet.writeString(strToken);
}
packet << nAdid;
packet << nEnterId;
BYTE canCreate = 1;
int nNosetopenday = GetLogicServer()->GetDataProvider()->GetEditionProvider().GetEditionInfo().nNoSetOpenDay;
if( nNosetopenday > 0 && (GetLogicServer()->GetDaysSinceOpenServer() > nNosetopenday))
{
canCreate = 0;
}
packet <<(BYTE)canCreate;
//这些数据已经没有用了,清掉
if(pGateUser->nLastRandNameIndex >=0)
{
pGateUser->nLastRandNameIndex =-1;
pGateUser->sLastRandName[0] =0;
}
OutputMsg(rmTip,_T("CreateActor[1] accounName:%s,actorName:%s, "),pGateUser->sAccount,actorName);
pDbClient->flushProtoPacket(packet);
}
void CLogicGate::Client2DbDeleteActor(CDataPacketReader &reader,CLogicGateUser* pGateUser)
{
if ( !pGateUser )
{
return;
}
CDataClient * pDbClient= m_pLogicServer->GetDbClient();
if(pDbClient ==NULL || !pDbClient->connected())
{
ResponseLoginErrorAndCloseUser(pGateUser,enDbServerClose);
return;
}
unsigned int nActorId=0;
reader >> nActorId; //删除这个玩家
CDataPacket &packet = pDbClient->allocProtoPacket(jxInterSrvComm::DbServerProto::dcDeleteActor);
int nServerId = GetLogicServer()->GetServerIndex(); //当前的服务器的编号
int nRawServerId= pGateUser->nRawServerIndex ;
//协议约定key放在最前面
packet <<nRawServerId << nServerId << (BYTE)m_nGateIndex << pGateUser->lLogicKey << pGateUser->nGlobalSessionId ;
packet <<nActorId ;
packet.writeString(pGateUser->sAccount); //将玩家的账户名字发过去
pDbClient->flushProtoPacket(packet);
}
void CLogicGate::OnDispatchUserMsg(CCustomServerGateUser *pGateUser, char* lpData, SIZE_T nSize)
{
if ( !pGateUser )
{
return;
}
pGateUser->dwLastMsgTick = _getTickCount();
CLogicGateUser* pLogicGateUser = (CLogicGateUser*)pGateUser;
CDataPacketReader pack(lpData,nSize);
BYTE nStstemID=0, nCmd =0;
pack >> nStstemID >> nCmd ;
if( nStstemID == enLoginSystemId)
{
// if(! m_pLogicServer->GetSessionClient()->connected())
// {
// ResponseLoginErrorAndCloseUser(pLogicGateUser,enSessionServerClose);
// return;
// }
// if(! m_pLogicServer->GetDbClient()->connected() )
// {
// ResponseLoginErrorAndCloseUser(pLogicGateUser,enDbServerClose);
// return;
// }
switch (nCmd)
{
case cCheckUserPasswd: //检测密码
{
if (GetLogicServer()->IsCommonServer())
{
INT_PTR nTotalCount = 0;
INT_PTR nCount = GetGlobalLogicEngine()->GetEntityMgr()->GetOnlineActorCount(nTotalCount);
// if ( nTotalCount >= GetLogicServer()->GetDataProvider()->GetGlobalConfig().nWuyiCrossMaxCount )
// {
// ResponseLoginErrorAndCloseUser(pLogicGateUser,enServerOnLineCountMAx);
// return;
// }
}
Client2SesionCheckUserPasswd(pack,pLogicGateUser);
break;
}
case cCreateAccount: //创建账户
{
//必须屏蔽
Client2SesionCreateAccount(pack,pLogicGateUser);
break;
}
case cGetUserList: //获取玩家的列表
{
SendDbGetActorList(pLogicGateUser);
break;
}
case cCreateActor: //创建角色
{
Client2DbCreateActor(pack,pLogicGateUser);
break;
}
case cDeleteActor: //删除角色
{
if ( (pLogicGateUser->boHasSecPsw && !pLogicGateUser->boCheckSecPswSucess) &&
!GetGlobalLogicEngine()->GetSecondPswFlag() && !pLogicGateUser->boWhiteIpLogin)
{
return;
}
Client2DbDeleteActor(pack,pLogicGateUser);
break;
}
case cRandName: //随机名字
{
Client2DbRandName(pack,pLogicGateUser);
break;
}
case cCheckSecondPsw:
{
Client2DbCheckSecondPsw(pack,pLogicGateUser);
break;
}
case cCreateSecondPsw:
{
Client2DbCreateSecondPsw(pack,pLogicGateUser);
OutputMsg(rmTip,_T("%s(%u) create second password."),pLogicGateUser->sAccount,pLogicGateUser->nGlobalSessionId);
break;
}
case cCrossServerInit:
{
SimulateClient2SesionCheckUserPasswd(pack,pLogicGateUser);
break;
}
}
return ;
}
/*if(pGateUser->nGlobalSessionId && (CActor::s_nTraceAccountId <0 || CActor::s_nTraceAccountId == pGateUser->nGlobalSessionId ))
{
OutputMsg(rmTip,_T("1CLogicGate account=%d, system=%d,cmd=%d,size=%d"),pGateUser->nGlobalSessionId,(int)nStstemID,(int)nCmd,(int)nSize);
}*/
if(pLogicGateUser->nHandleIndex ==0) //如果收到确认
{
unsigned nAccountID =0; //帐户ID
unsigned nActorID =0; //角色的ID
int nLogSceneId = 0;
if(nStstemID == enDefaultEntitySystemID &&nCmd == cLogin)
{
pack >> nAccountID >> nActorID;
pack >> nLogSceneId;
if ( !GetGlobalLogicEngine()->GetLoginSecondPswFlag() )
{
if ((pLogicGateUser->boHasSecPsw && !pLogicGateUser->boCheckSecPswSucess) &&
!GetGlobalLogicEngine()->GetSecondPswFlag() && !pLogicGateUser->boWhiteIpLogin)
{
OutputMsg(rmWaning,_T("cannot login by second password account%u-actor%u-thread%u "),nAccountID,nActorID,GetCurrentThreadId());
return;
}
}
OnUserLogin(pLogicGateUser,nAccountID,nActorID,nLogSceneId); //通知逻辑服务器有人要登陆了
//OutputMsg(rmNormal,_T("收到登陆包 nAccountID=%d,nActorID=%d"),nAccountID,nActorID );
}
else
{
OutputMsg(rmWaning,_T("%s在实体没有创建好的时候收到了未知的数据包,nStstemID=%d,nCmd=%d"),__FUNCTION__,nStstemID,nCmd );
}
return;
}
LOGICUSERDATA UserData;
UserData.nHandleIndex = pLogicGateUser->nHandleIndex;
if (m_vFreeList.count() <= 0)
{
AllocGateSendPacketList(m_vFreeList,512);
}
if (m_vFreeList.count() <= 0)
{
OutputMsg(rmError, _T("%s这个位置创建新包失败丢包中,子系统=%did=%d"), __FUNCTION__, nStstemID, nCmd);
return;
}
CDataPacket* m_TempData = m_vFreeList.pop();//得到一个空闲的Datapacket
if (!m_TempData)
{
return;
}
m_TempData->setPosition(0);
//TRACE("free m_TempData:%d\n",(int)(m_TempData));
//复制到内存块中
(*m_TempData) << (unsigned int)UserData.nHandleIndex << (long long) pGateUser->dwGateTickCount; //将网关的时间拷贝过去
(*m_TempData) << (long long)_getTickCount(); // 记录逻辑服务器收到此消息的时间
m_TempData->writeBuf(lpData,nSize);
m_vMsgList.add(m_TempData);
}
void CLogicGate::Client2DbRandName(CDataPacketReader &reader,CLogicGateUser* pGateUser)
{
if ( !pGateUser )
{
return;
}
CDataClient * pDbClient= m_pLogicServer->GetDbClient();
if(pDbClient ==NULL || !pDbClient->connected())
{
ResponseLoginErrorAndCloseUser(pGateUser,enDbServerClose);
return;
}
//随机名字
BYTE bSex=0;
reader >> bSex; //删除这个玩家
CDataPacket &packet = pDbClient->allocProtoPacket(jxInterSrvComm::DbServerProto::dcGetRandName);
int nServerId = GetLogicServer()->GetServerIndex(); //当前的服务器的编号
int nRawServerId= pGateUser->nRawServerIndex ;
//协议约定key放在最前面
packet <<nRawServerId << nServerId << (BYTE)m_nGateIndex << pGateUser->lLogicKey ;
packet <<bSex ;
pDbClient->flushProtoPacket(packet);
}
VOID CLogicGate::OnRun()
{
Inherited::OnRun();
if ( m_vFreeList.appendCount() > 0 )
{
m_vFreeList.flush();
}
//传递网络包给逻辑线程
if ( m_vMsgList.count() > 0 )
{
GetGlobalLogicEngine()->GetNetWorkHandle()->PostUserDataList(m_nGateIndex, m_vMsgList);
}
ProcessUsers();
}
VOID CLogicGate::ProcessUsers()
{
INT_PTR i;
CLogicGateUser *pGateUser;
Uint64 dwCurTick = _getTickCount();
if (m_ProcessUserInterval.CheckAndSet(dwCurTick, true))
{
//必须降序循环
for (i=m_UserList.count()-1; i>-1; --i)
{
pGateUser = (CLogicGateUser*)m_UserList[i];
if ( !pGateUser )
continue;
//检查延时关闭
if ( pGateUser->dwDelayCloseTick && dwCurTick >= (Uint64)(pGateUser->dwDelayCloseTick) )//dwDelayCloseTick貌似没设置
pGateUser->boMarkToClose = TRUE;
//如果长时间无通信数据则关闭用户
if ( pGateUser->boMarkToClose )
{
OutputMsg(rmWaning,_T("延迟将玩家踢下线"));
CloseUser( pGateUser->nSocket, pGateUser->nServerSessionIndex );
continue;
}
else if( pGateUser->dwLastMsgTick && dwCurTick - pGateUser->dwLastMsgTick >= 900000 && !IsDebuggerPresent() )
{
OutputMsg(rmWaning,_T("15分钟没有收到玩家数据出现严重超时踢下线,socket=%d,accoutid=%d"),(int)pGateUser->nSocket,pGateUser->nGlobalSessionId);
if(pGateUser->nSocket == INVALID_SOCKET)
{
CloseUser( pGateUser->nSocket, pGateUser->nServerSessionIndex ,false);
}
else
{
CloseUser( pGateUser->nSocket, pGateUser->nServerSessionIndex ,true);
}
continue;
}
}
}
}
void CLogicGate::Client2DbCheckSecondPsw(CDataPacketReader &reader,CLogicGateUser* pGateUser)
{
if (!pGateUser)
{
return;
}
CDataClient * pDbClient= m_pLogicServer->GetDbClient();
if(pDbClient ==NULL || !pDbClient->connected())
{
ResponseLoginErrorAndCloseUser(pGateUser,enDbServerClose);
}
else
{
ACTORNAME sPsw = {0};
reader.readString(sPsw,ArrayCount(sPsw));
CDataPacket &packet = pDbClient->allocProtoPacket(jxInterSrvComm::DbServerProto::dcCheckSecondPsw);
int nServerId = GetLogicServer()->GetServerIndex();
int nRawServerId= pGateUser->nRawServerIndex ;
packet << nRawServerId << nServerId << (BYTE)m_nGateIndex <<pGateUser->lLogicKey << pGateUser->nGlobalSessionId;
MD5_CTX md5_context;
MD5Init(&md5_context);
MD5Update(&md5_context, (unsigned char*)sPsw, ArrayCount(sPsw));
ACTORNAME smd5 = {0};
MD5Final((unsigned char*)smd5,&md5_context);
packet.writeString(smd5);
//packet.writeString(sPsw);
pDbClient->flushProtoPacket(packet);
}
}
void CLogicGate::Client2DbCreateSecondPsw(CDataPacketReader &reader,CLogicGateUser* pGateUser)
{
if ( !pGateUser )
{
return;
}
CDataClient * pDbClient= m_pLogicServer->GetDbClient();
if(pDbClient ==NULL || !pDbClient->connected())
{
ResponseLoginErrorAndCloseUser(pGateUser,enDbServerClose);
}
else
{
ACTORNAME sPsw = {0};
reader.readString(sPsw,ArrayCount(sPsw));
CDataPacket &packet = pDbClient->allocProtoPacket(jxInterSrvComm::DbServerProto::dcCreateSecondPsw);
int nServerId = GetLogicServer()->GetServerIndex();
int nRawServerId= pGateUser->nRawServerIndex ;
packet << nRawServerId << nServerId << (BYTE)m_nGateIndex <<pGateUser->lLogicKey << pGateUser->nGlobalSessionId;
MD5_CTX md5_context;
MD5Init(&md5_context);
MD5Update(&md5_context, (unsigned char*)sPsw, ArrayCount(sPsw));
ACTORNAME smd5 = {0};
MD5Final((unsigned char*)smd5,&md5_context);
packet.writeString(smd5);
//packet.writeString(sPsw);
pDbClient->flushProtoPacket(packet);
}
}
//跨服相关逻辑
//模拟账号验证
void CLogicGate::SimulateClient2SesionCheckUserPasswd(CDataPacketReader &pack,CLogicGateUser* pLogicGateUser)
{
//模拟
TCHAR name[ACCOUNT_NAME_BUFF_LENGTH];
TCHAR passwd[MAX_PASSWD_LENGTH];
char identity[64]; //身份证号码
name[0]=0;
passwd[0]=0;
identity[0] =0;
unsigned int nCrossActorId =0; //
int nRawServerId =0; // 要登陆的服务器的编号
pack >> nCrossActorId;
pack >> nRawServerId;
pLogicGateUser->nRawServerIndex = nRawServerId;
GetGlobalLogicEngine()->GetNetWorkHandle()->PostInternalMessage(SSM_CROSS_CEHCK_ACTORDATA,
nCrossActorId, nRawServerId, m_nGateIndex,pLogicGateUser->lLogicKey);
GetGlobalLogicEngine()->GetCrossMgr().AddLoginActors(nCrossActorId, nRawServerId);
OutputMsg(rmTip,_T("[CrossLogin 10] 发送到CrossMgr nCrossActorId(%d),nRawServerId(%d), logickey(%lld)socket(%lld)GateIdx(%d)LogicIdx(%d)CurrentThreadId(%d)。"),
nCrossActorId,nRawServerId,pLogicGateUser->lLogicKey,pLogicGateUser->nSocket,pLogicGateUser->nGateSessionIndex,pLogicGateUser->nServerSessionIndex,GetCurrentThreadId());
}