2151 lines
59 KiB
C++
2151 lines
59 KiB
C++
|
||
#include "StdAfx.h"
|
||
#include "DataProcess.h"
|
||
#include "SockProcess.h"
|
||
HANDLE g_hStdOut;
|
||
|
||
unsigned int CRunDataProcesser::s_nSndThreadSleepTime = 20;
|
||
extern bool g_ServerIsRunning;
|
||
|
||
//接收数据的线程
|
||
#ifdef _MSC_VER
|
||
VOID STDCALL CRunDataProcesser::RecvDataProcdaessRoutine(void *arg)
|
||
#else
|
||
VOID* CRunDataProcesser::RecvDataProcessRoutine(void *arg)
|
||
#endif
|
||
{
|
||
CRunDataProcesser * pRunData = (CRunDataProcesser *)arg;
|
||
|
||
//LPCRITICAL_SECTION pQueueLock;
|
||
CBaseList<LPVOID> *pRecvList;
|
||
PCLIENTRECVBUF *ppRecvBufs, pRecvBuf;
|
||
PRUNGATEUSERSESSION pSession;
|
||
INT_PTR nBufferCount;
|
||
TICKCOUNT dwProcStartTick, dwLockDataTick, dwLockCheckTick, dwSendCheckTick, dwPerfDumpTick, dwSendGateUserInfo;
|
||
|
||
//pQueueLock = &pRunData->m_RecvQueueLock;
|
||
pRecvList = pRunData->m_pRecvProcList;
|
||
pRunData->m_llSendKeepAliveTime = 0;
|
||
dwLockDataTick = dwLockCheckTick = dwPerfDumpTick = dwSendGateUserInfo = _getTickCount();
|
||
dwSendCheckTick = dwSendGateUserInfo + 2000;
|
||
while ( !pRunData->m_boStoping )
|
||
{
|
||
dwProcStartTick = _getTickCount();
|
||
|
||
//发送网关自检
|
||
if ( dwProcStartTick - dwSendCheckTick >= 2000 )
|
||
{
|
||
pRunData->SendCheck( GM_CHECKSERVER );
|
||
dwSendCheckTick = dwProcStartTick;
|
||
pRunData->m_llSendKeepAliveTime = dwSendCheckTick;
|
||
}
|
||
|
||
// 发送网关用户数目,一分钟发一次
|
||
if (dwProcStartTick - dwSendGateUserInfo >= 60000 )
|
||
{
|
||
pRunData->SendGateUserInfo();
|
||
dwSendGateUserInfo = dwProcStartTick;
|
||
}
|
||
|
||
//检查会话关闭
|
||
if ( dwProcStartTick - dwLockCheckTick >= 5000 )
|
||
{
|
||
if ( pRunData->CheckCloseSessions( dwProcStartTick - dwLockCheckTick >= 10000 ) )
|
||
{
|
||
dwProcStartTick = dwLockCheckTick = _getTickCount();
|
||
}
|
||
}
|
||
// dump statistic
|
||
if (dwProcStartTick - dwPerfDumpTick >= 120000)
|
||
{
|
||
CTimeProfMgr::getSingleton().dump();
|
||
dwPerfDumpTick = dwProcStartTick;
|
||
}
|
||
|
||
//如果未能获得数据队列锁则让出本次CPU时间
|
||
if ( !TryEnterCriticalSection( &pRunData->m_RecvQueueLock ) )
|
||
{
|
||
if ( dwProcStartTick - dwLockDataTick < 60 )
|
||
{
|
||
Sleep( 1 );
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
EnterCriticalSection( &pRunData->m_RecvQueueLock );
|
||
dwProcStartTick = dwLockDataTick = _getTickCount();
|
||
}
|
||
}
|
||
else dwLockDataTick = dwProcStartTick;
|
||
|
||
//交换数据处理队列
|
||
pRecvList = pRunData->m_pRecvAppendList;
|
||
pRunData->m_pRecvAppendList = pRunData->m_pRecvProcList;
|
||
pRunData->m_pRecvProcList = pRecvList;
|
||
LeaveCriticalSection( &pRunData->m_RecvQueueLock );
|
||
|
||
//如果没有待处理的数据则让出本次CPU时间
|
||
nBufferCount = pRecvList->count();
|
||
if ( !nBufferCount )
|
||
{
|
||
Sleep( 1 );
|
||
continue;
|
||
}
|
||
|
||
ppRecvBufs = (PCLIENTRECVBUF*)(void**)(*pRecvList);
|
||
while ( nBufferCount > 0 )
|
||
{
|
||
pRecvBuf = *ppRecvBufs;
|
||
nBufferCount--;
|
||
ppRecvBufs++;
|
||
pSession = pRecvBuf->pSession;
|
||
if ( pRecvBuf->nBufferSize > 0 )
|
||
{
|
||
//如果会话被关闭或效验过期则不予处理
|
||
if ( pSession->nSocket != INVALID_SOCKET && pSession->nVerifyIdx == pRecvBuf->nVerify && !pSession->boMarkToClose && !pSession->boRemoteClosed )
|
||
{
|
||
pSession->dwClientMsgTick = dwProcStartTick;
|
||
//OutputMsg( rmTip, "dwProcStartTick=%I64d",dwProcStartTick);
|
||
pRunData->ProcessUserRecvPacket( pSession, (char*)(pRecvBuf + 1), pRecvBuf->nBufferSize );
|
||
pSession->nRecvPacketCount++;
|
||
}
|
||
}
|
||
free( pRecvBuf );
|
||
}
|
||
pRecvList->clear();
|
||
pRunData->m_dwLastProcUsrMsgTime = _getTickCount() - dwProcStartTick;
|
||
//循环小于指定时间则休眠一次
|
||
//if ( pRunData->m_dwLastProcUsrMsgTime < 16 )
|
||
if(TRUE)
|
||
{
|
||
Sleep ( 1 );
|
||
}
|
||
}
|
||
ExitThread( 0 );
|
||
}
|
||
|
||
//发送数据的线程
|
||
#ifdef _MSC_VER
|
||
VOID STDCALL CRunDataProcesser::SendDataProcessRoutine(void* arg)
|
||
#else
|
||
VOID* CRunDataProcesser::SendDataProcessRoutine(void* arg)
|
||
#endif
|
||
{
|
||
PRUNDATASENDTHREAD pRunThread = (PRUNDATASENDTHREAD)arg;
|
||
|
||
TICKCOUNT dwProcStartTick;
|
||
CRunDataProcesser *pRunData;
|
||
int nLockSendBufQLockFail = 0;
|
||
pRunData = pRunThread->pRunData;
|
||
|
||
while ( !pRunData->m_boStoping )
|
||
{
|
||
dwProcStartTick = _getTickCount();
|
||
if ( pRunData->CopyWaitSendBuffers( pRunThread, TRUE) )
|
||
nLockSendBufQLockFail = 0;
|
||
else nLockSendBufQLockFail ++;
|
||
|
||
pRunData->CheckSendSessionBuffers( pRunThread );
|
||
|
||
//循环小于指定时间则休眠一次
|
||
pRunThread->dwProcTick = _getTickCount() - dwProcStartTick;
|
||
//if ( pRunThread->dwProcTick < 20 )
|
||
|
||
{
|
||
dwProcStartTick = _getTickCount();
|
||
Sleep(s_nSndThreadSleepTime);
|
||
TICKCOUNT curTick = _getTickCount();
|
||
pRunThread->dwSleepTick = curTick - dwProcStartTick;
|
||
}
|
||
|
||
/*else
|
||
pRunThread->dwSleepTick = 0;*/
|
||
}
|
||
ExitThread( 0 );
|
||
}
|
||
|
||
//收到了服务器的数据,进行处理
|
||
//VOID CRunDataProcesser::ProcessRecvBuffers(const GateMsg* msg)
|
||
VOID CRunDataProcesser::ProcessRecvBuffers(const GATEMSGHDR* pHeader, LPCSTR pData, size_t nLen)
|
||
{
|
||
Assert(pHeader->dwGateCode == RUNGATECODE);
|
||
/*if (msg->header.wIdent == GM_DATA)
|
||
Assert(msg->header.wTemp == RUNTEMPCODE);*/
|
||
if (s_nIgnoreDataPacket)
|
||
return;
|
||
//如果是关闭服务器的话
|
||
if(pHeader->wIdent ==GM_CLOSE_SERVER)
|
||
{
|
||
OutputMsg(rmTip,"Back server close from back");
|
||
g_ServerIsRunning = false;
|
||
return;
|
||
}
|
||
else if (pHeader->wIdent == GM_APPBIGPACK)
|
||
{
|
||
char* pBuffEnd = (char *)pData + nLen;
|
||
GATEMSGHDR* pCurHeader = (GATEMSGHDR *)pData;
|
||
while ((char*)pCurHeader < pBuffEnd)
|
||
{
|
||
if (pCurHeader->dwGateCode != RUNGATECODE)
|
||
{
|
||
OutputMsg(rmError, _T("%s recv packet invalid..."), __FUNCTION__);
|
||
break;
|
||
}
|
||
DispathRecvMessage(pCurHeader, (const char*)(pCurHeader+1), pCurHeader->nDataSize);
|
||
pCurHeader = (GATEMSGHDR *)((char *)pCurHeader + (sizeof(GATEMSGHDR) + pCurHeader->nDataSize));
|
||
}
|
||
}
|
||
else
|
||
DispathRecvMessage((GATEMSGHDR * const)pHeader, pData, nLen);
|
||
}
|
||
|
||
|
||
|
||
VOID CRunDataProcesser::DispathRecvMessage(const PGATEMSGHDR pMsgHdr, const char *pBuffer, SIZE_T nBufSize)
|
||
{
|
||
PRUNGATEUSERSESSION pSession;
|
||
/*
|
||
if(GM_DATA ==pMsgHdr->wIdent)
|
||
{
|
||
OutputMsg(rmTip, _T("收到后台数据,cmd=%d,wSessionIdx=%d,wServerIdx=%d,socket=%d\n"),
|
||
pMsgHdr->wIdent, pMsgHdr->wSessionIdx,pMsgHdr->wServerIdx,pMsgHdr->nSocket);
|
||
}
|
||
*/
|
||
switch ( pMsgHdr->wIdent )
|
||
{
|
||
case GM_CLOSE:
|
||
if ( pMsgHdr->wSessionIdx < m_nMaxSessionCount )
|
||
{
|
||
pSession = &m_Sessions[pMsgHdr->wSessionIdx];
|
||
|
||
if ( pSession->nSocket == pMsgHdr->nSocket && !pSession->boMarkToClose && !pSession->boRemoteClosed )
|
||
{
|
||
SendCloseSession( pSession, FALSE, enReasonGM );
|
||
}
|
||
else
|
||
{
|
||
OutputMsg( rmWaning, _T("GM_CLOSE socket不匹配 wSessionIdx=%d,本地Socket=%d,后台的为%d"),
|
||
pMsgHdr->wSessionIdx, pSession->nSocket, pMsgHdr->nSocket );
|
||
}
|
||
|
||
}
|
||
break;
|
||
case GM_CHECKCLIENT:
|
||
{
|
||
// 保存服务器的时间
|
||
if (m_llSendKeepAliveTime > 0)
|
||
{
|
||
if (m_nCheckTimeCount < 10)
|
||
{
|
||
TICKCOUNT nTimeDiff = pMsgHdr->tickCount - _getTickCount();
|
||
m_llOccuTimeDiff += nTimeDiff;
|
||
m_nCheckTimeCount++;
|
||
m_llSvrTimeDiff = (long long)(m_llOccuTimeDiff / (float)m_nCheckTimeCount);
|
||
OutputMsg(rmNormal, _T("timediff=%lld,result dif=%lld,checkTimecount=%d"),
|
||
nTimeDiff,
|
||
m_llSvrTimeDiff,
|
||
m_nCheckTimeCount);
|
||
}
|
||
}
|
||
/*OutputMsg(rmNormal, _T("------logicSvrTime=%I64d gateTime=%I64d, timeDif=%I64d"), pMsgHdr->tickCount, nCurrTick, m_llSvrTimeDiff);*/
|
||
}
|
||
break;
|
||
case GM_APPKEEPALIVE:
|
||
{
|
||
// 给服务器会应答消息
|
||
pSession = &m_Sessions[pMsgHdr->wSessionIdx];
|
||
if ( pSession->nSocket == pMsgHdr->nSocket && !pSession->boMarkToClose && !pSession->boRemoteClosed )
|
||
{
|
||
SendKeepAliveAck( pSession, pBuffer, nBufSize);
|
||
}
|
||
break;
|
||
}
|
||
case GM_SERVERUSERINDEX:
|
||
if ( pMsgHdr->wSessionIdx < m_nMaxSessionCount )
|
||
{
|
||
pSession = &m_Sessions[pMsgHdr->wSessionIdx];
|
||
if ( pSession->nSocket == pMsgHdr->nSocket && !pSession->boMarkToClose && !pSession->boRemoteClosed )
|
||
{
|
||
pSession->nServerIdx = pMsgHdr->wServerIdx;
|
||
OutputMsg(rmNormal, _T("recv GM_ServerIndex msg. socket=%d, sessionId=%d, set serverIdx=%d"),
|
||
(int)pSession->nSocket, (int)pSession->nIndex, pSession->nServerIdx);
|
||
}
|
||
else
|
||
{
|
||
OutputMsg(rmError, _T("GM_ServerIndex Error, session closed or socket unmatch(session socket=%d, sessionId=%d, msghdr socket=%d"),
|
||
(int)pSession->nSocket, (int)pSession->nIndex, (int)pMsgHdr->nSocket);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case GM_DATA:
|
||
if ( pMsgHdr->wSessionIdx < m_nMaxSessionCount )
|
||
{
|
||
pSession = &m_Sessions[pMsgHdr->wSessionIdx];
|
||
if ( !pSession->boMarkToClose && !pSession->boRemoteClosed )
|
||
{
|
||
if ( pSession->nSocket == pMsgHdr->nSocket )
|
||
{
|
||
PostUserServerData( pSession, pBuffer, (INT)nBufSize, TRUE, TRUE, (TICKCOUNT)pMsgHdr->tickCount);
|
||
}
|
||
else
|
||
{
|
||
OutputMsg( rmWaning, "GM_DATA 会话(%d:%s)套接字不匹配,data Socket=%d,local socket=%d", pMsgHdr->wSessionIdx, pSession->sLoginCharName, pMsgHdr->nSocket,pSession->nSocket );
|
||
//SendCloseSession((SOCKET)pMsgHdr->nSocket); //如果套接字不匹配
|
||
//SendCloseSession( pSession, TRUE, enReasonAllSessionClose );
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
OutputMsg( rmWaning, "GM_DATA 会话(%d:%s,%d,%d)已关闭", pMsgHdr->wSessionIdx, pSession->sLoginCharName,
|
||
(int)(pSession->boMarkToClose),(int)(pSession->boRemoteClosed));
|
||
//这种情况下再次向逻辑发送关闭连接
|
||
//SendCloseSession((SOCKET)pMsgHdr->nSocket);
|
||
}
|
||
}
|
||
else OutputMsg( rmWaning, "GM_DATA 会话ID无效(%d)", pMsgHdr->wSessionIdx );
|
||
break;
|
||
|
||
default:
|
||
{
|
||
GotError( __FUNCTION__, _T("无效的消息序列"), pMsgHdr->wIdent );
|
||
}
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
VOID CRunDataProcesser::OnConnected()
|
||
{
|
||
Inherited::OnConnected();
|
||
m_llSendKeepAliveTime = 0;
|
||
m_nCheckTimeCount = 0;
|
||
m_llOccuTimeDiff = 0;
|
||
OutputMsg(rmTip, _T("BackServer Connected"));
|
||
}
|
||
|
||
VOID CRunDataProcesser::OnClosed()
|
||
{
|
||
Inherited::OnClosed();
|
||
CloseAllSessions(true);
|
||
}
|
||
|
||
VOID CRunDataProcesser::OnError(int errorCode)
|
||
{
|
||
OutputError(errorCode, _T("BackServer Socket Error "));
|
||
}
|
||
|
||
VOID CRunDataProcesser::OnDisconnected()
|
||
{
|
||
m_llSvrTimeDiff = 0;
|
||
m_nCheckTimeCount = 0;
|
||
m_llOccuTimeDiff = 0;
|
||
OutputMsg(rmWaning, _T("BackServer Connection Closed"));
|
||
}
|
||
|
||
CRunDataProcesser::CRunDataProcesser(const int nMaxSessionCount)
|
||
:Inherited()
|
||
{
|
||
m_nActiveUser = 0;
|
||
m_boStoping = FALSE;
|
||
m_boStarted = FALSE;
|
||
|
||
m_DataProcessType = dp_Default;
|
||
|
||
/*
|
||
m_hPipe = INVALID_HANDLE_VALUE;
|
||
strcpy( m_sPipeName, "\\\\.\\pipe\\default" );
|
||
|
||
sprintf( m_sGateName, "游戏网关%d", _getTickCount() % 100 );
|
||
*/
|
||
|
||
m_hProcRecvThread = NULL;
|
||
ZeroMemory( m_SendThreads, sizeof(m_SendThreads) );
|
||
|
||
m_nSendThreadCount = 2;
|
||
m_nMaxSessionCount = nMaxSessionCount; // 默认值: 16384
|
||
m_Sessions = NULL;
|
||
m_pSockProcesser = NULL;
|
||
|
||
InitializeCriticalSection( &m_SessionLock );
|
||
if ( m_Sessions ) ZeroMemory( m_Sessions, sizeof(m_Sessions) );
|
||
|
||
|
||
InitializeCriticalSection( &m_RecvQueueLock );
|
||
m_pRecvAppendList = &m_RecvQueue[0];
|
||
m_pRecvProcList = &m_RecvQueue[1];
|
||
|
||
m_ServerBuf.lpBuffer= NULL;
|
||
m_ServerBuf.nSize = 0;
|
||
m_ServerBuf.nOffset = 0;
|
||
|
||
m_nUserVerify = 1;
|
||
m_dwProcessRecvSize = 0;
|
||
|
||
m_boPrintC2SMsg = FALSE;
|
||
m_boPrintS2CMsg = FALSE;
|
||
|
||
m_llSvrTimeDiff = 0;
|
||
m_nCheckTimeCount = 0;
|
||
m_llOccuTimeDiff = 0;
|
||
InitSendThreadData();
|
||
//m_DataPacker.SetNeedEncrypt(true); //需要加密
|
||
}
|
||
|
||
CRunDataProcesser::~CRunDataProcesser()
|
||
{
|
||
Stop();
|
||
UninitSendThreadData();
|
||
DeleteCriticalSection( &m_RecvQueueLock );
|
||
DeleteCriticalSection( &m_SessionLock );
|
||
}
|
||
|
||
VOID CRunDataProcesser::InitSessions()
|
||
{
|
||
int i;
|
||
PRUNGATEUSERSESSION pSession;
|
||
|
||
EnterCriticalSection( &m_SessionLock );
|
||
if ( !m_Sessions )
|
||
{
|
||
m_Sessions = (PRUNGATEUSERSESSION)malloc(sizeof(m_Sessions[0]) * m_nMaxSessionCount);
|
||
ZeroMemory( m_Sessions, sizeof(m_Sessions[0]) * m_nMaxSessionCount );
|
||
}
|
||
pSession = m_Sessions;
|
||
for ( i=0; i<m_nMaxSessionCount; ++i )
|
||
{
|
||
pSession->nIndex = i;
|
||
pSession->nSocket = INVALID_SOCKET;
|
||
#ifdef WIN32
|
||
pSession->Overlapped.pUser = pSession;
|
||
#endif
|
||
pSession->nServerIdx = 0;
|
||
pSession->btPacketIdx = 0;
|
||
pSession->wPacketError = 0;
|
||
pSession->nRecvPacketCount = 0;
|
||
pSession->nSendPacketCount = 0;
|
||
pSession->boMarkToClose = false;
|
||
pSession->boRemoteClosed = false;
|
||
pSession->boSendAvaliable = true;
|
||
INIT_SESSION_SEND( pSession );
|
||
pSession++;
|
||
}
|
||
LeaveCriticalSection( &m_SessionLock );
|
||
}
|
||
|
||
VOID CRunDataProcesser::UninitSessions()
|
||
{
|
||
int i;
|
||
PRUNGATEUSERSESSION pSession;
|
||
|
||
if ( !m_Sessions ) return;
|
||
EnterCriticalSection( &m_SessionLock );
|
||
pSession = m_Sessions;
|
||
for ( i=0; i<m_nMaxSessionCount; ++i )
|
||
{
|
||
if ( pSession->RecvBuf.lpBuffer )
|
||
{
|
||
free( pSession->RecvBuf.lpBuffer );
|
||
pSession->RecvBuf.lpBuffer = NULL;
|
||
pSession->RecvBuf.nSize = pSession->RecvBuf.nOffset = 0;
|
||
}
|
||
if ( pSession->SendBuf.lpBuffer )
|
||
{
|
||
free( pSession->SendBuf.lpBuffer );
|
||
pSession->SendBuf.lpBuffer = NULL;
|
||
pSession->SendBuf.nSize = pSession->SendBuf.nOffset = 0;
|
||
}
|
||
UNINIT_SESSION_SEND( pSession );
|
||
pSession++;
|
||
}
|
||
free( m_Sessions );
|
||
m_Sessions = NULL;
|
||
LeaveCriticalSection( &m_SessionLock );
|
||
}
|
||
|
||
VOID CRunDataProcesser::FreeRecvBuffers()
|
||
{
|
||
INT_PTR i;
|
||
void **pBuffers;
|
||
EnterCriticalSection( &m_RecvQueueLock );
|
||
|
||
pBuffers = *m_pRecvAppendList;
|
||
for ( i=m_pRecvAppendList->count()-1; i>-1; --i )
|
||
{
|
||
free( pBuffers[i] );
|
||
}
|
||
m_pRecvAppendList->clear();
|
||
|
||
|
||
pBuffers = *m_pRecvProcList;
|
||
for ( i=m_pRecvProcList->count()-1; i>-1; --i )
|
||
{
|
||
free( pBuffers[i] );
|
||
}
|
||
m_pRecvProcList->clear();
|
||
|
||
LeaveCriticalSection( &m_RecvQueueLock );
|
||
}
|
||
|
||
VOID CRunDataProcesser::FreeSendBuffers(PRUNDATASENDTHREAD pSendThread)
|
||
{
|
||
INT_PTR i;
|
||
void **pBuffers;
|
||
EnterCriticalSection( &pSendThread->SendQueueLock );
|
||
|
||
pBuffers = *pSendThread->pSendAppendList;
|
||
for ( i=pSendThread->pSendAppendList->count()-1; i>-1; --i )
|
||
{
|
||
free( pBuffers[i] );
|
||
}
|
||
pSendThread->pSendAppendList->clear();
|
||
|
||
|
||
pBuffers = *pSendThread->pSendProcList;
|
||
for ( i=pSendThread->pSendProcList->count()-1; i>-1; --i )
|
||
{
|
||
free( pBuffers[i] );
|
||
}
|
||
pSendThread->pSendProcList->clear();
|
||
|
||
LeaveCriticalSection( &pSendThread->SendQueueLock );
|
||
}
|
||
/*
|
||
BOOL CRunDataProcesser::OpenServerPipe()
|
||
{
|
||
int nErr;
|
||
|
||
while ( TRUE )
|
||
{
|
||
m_hPipe = CreateFile( m_sPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
|
||
if ( m_hPipe != INVALID_HANDLE_VALUE )
|
||
return TRUE;
|
||
|
||
nErr = GetLastError();
|
||
if ( nErr != ERROR_PIPE_BUSY )
|
||
{
|
||
GotError( __FUNCTION__, "CreateFile", nErr );
|
||
break;
|
||
}
|
||
|
||
if ( !WaitNamedPipe( m_sPipeName, 10000 ) )
|
||
{
|
||
nErr = GetLastError();
|
||
GotError( __FUNCTION__, "WaitNamedPipe", nErr );
|
||
break;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
|
||
VOID CRunDataProcesser::CloseServerPipe()
|
||
{
|
||
if ( m_hPipe != INVALID_HANDLE_VALUE )
|
||
{
|
||
CloseHandle( m_hPipe );
|
||
m_hPipe = INVALID_HANDLE_VALUE;
|
||
}
|
||
}
|
||
|
||
VOID CRunDataProcesser::ServerPipeError()
|
||
{
|
||
if ( m_hPipe != INVALID_HANDLE_VALUE )
|
||
{
|
||
CancelRemainSendSessionBuffers();
|
||
CloseHandle( m_hPipe );
|
||
m_hPipe = INVALID_HANDLE_VALUE;
|
||
//CloseAllSessions 必须在CloseHandle之后调用,否则CloseAllSessions->SendServerMessage->ServerPipeError 造成栈溢出
|
||
CloseAllSessions( TRUE );
|
||
}
|
||
}
|
||
*/
|
||
|
||
BOOL CRunDataProcesser::CopyWaitSendBuffers(PRUNDATASENDTHREAD pSendThread, BOOL boForceCopy)
|
||
{
|
||
PSENDCLIENTBUF pSendBuf, *ppBufers;
|
||
CBaseList<LPVOID> *pBufferList;
|
||
PRUNGATEUSERSESSION pSession;
|
||
INT_PTR nCount, nSize, nTotalSize, nAppendSize;
|
||
TICKCOUNT dwMsgTick;
|
||
|
||
if ( !boForceCopy )
|
||
boForceCopy = TryEnterCriticalSection( &pSendThread->SendQueueLock );
|
||
else EnterCriticalSection( &pSendThread->SendQueueLock );
|
||
|
||
if ( boForceCopy )
|
||
{
|
||
pBufferList = pSendThread->pSendAppendList;
|
||
pSendThread->pSendAppendList = pSendThread->pSendProcList;
|
||
pSendThread->pSendProcList = pBufferList;
|
||
LeaveCriticalSection( &pSendThread->SendQueueLock );
|
||
|
||
nCount = pBufferList->count();
|
||
if ( nCount > 0 )
|
||
{
|
||
dwMsgTick = _getTickCount();
|
||
ppBufers = (PSENDCLIENTBUF*)(void**)(*pBufferList);
|
||
nTotalSize = 0;
|
||
nAppendSize = 0;
|
||
do
|
||
{
|
||
pSendBuf = *ppBufers;
|
||
ppBufers++;
|
||
nCount--;
|
||
|
||
pSession = pSendBuf->pSession;
|
||
if ( pSession->nSocket != INVALID_SOCKET && !pSession->boMarkToClose && !pSession->boRemoteClosed )
|
||
{
|
||
nSize = pSession->SendBuf.nOffset + pSendBuf->nBufferSize + 1;
|
||
if ( pSession->SendBuf.nSize < nSize )
|
||
{
|
||
nSize = (nSize / SESSION_DATAGROW_SIZE + 1) * SESSION_DATAGROW_SIZE;
|
||
pSession->SendBuf.nSize = (INT)nSize;
|
||
pSession->SendBuf.lpBuffer = (char*)realloc( pSession->SendBuf.lpBuffer, nSize );
|
||
}
|
||
memcpy( &pSession->SendBuf.lpBuffer[pSession->SendBuf.nOffset], pSendBuf + 1, pSendBuf->nBufferSize );
|
||
pSession->SendBuf.nOffset += pSendBuf->nBufferSize;
|
||
pSession->SendBuf.lpBuffer[pSession->SendBuf.nOffset] = 0;
|
||
pSession->dwServerMsgTick = dwMsgTick;
|
||
nAppendSize += pSendBuf->nBufferSize;
|
||
}
|
||
nTotalSize += pSendBuf->nBufferSize;
|
||
free( pSendBuf );
|
||
}
|
||
while ( nCount > 0 );
|
||
pBufferList->clear();
|
||
|
||
// 原子操作
|
||
InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, (LONG)nAppendSize );
|
||
InterlockedExchangeAdd( (LONG*)&m_dwWaitSendQueueSize, -(INT)nTotalSize );
|
||
}
|
||
}
|
||
|
||
return boForceCopy;
|
||
}
|
||
|
||
VOID CRunDataProcesser::GetSessionLoginInfo(PRUNGATEUSERSESSION pSession, char *sBuffer, int nBufferSize)
|
||
{
|
||
}
|
||
|
||
|
||
VOID CRunDataProcesser::GotError(LPCSTR sErrFn, LPCSTR sErrApi, int nErr)
|
||
{
|
||
OutputMsg( rmError, _T("CRunDataProcesser::%s Got Error %d on api \"%s\""), sErrFn, nErr, sErrApi );
|
||
}
|
||
|
||
VOID CRunDataProcesser::InitSendThreadData()
|
||
{
|
||
int i;
|
||
|
||
for ( i=0; i<m_nSendThreadCount; ++i )
|
||
{
|
||
InitializeCriticalSection( &m_SendThreads[i].SendQueueLock );
|
||
m_SendThreads[i].pRunData = this;
|
||
m_SendThreads[i].nThreadIdx = i;
|
||
m_SendThreads[i].boSendEWouldBlock = false;
|
||
m_SendThreads[i].boSendFewBuffer = false;
|
||
m_SendThreads[i].pSendAppendList = new CBaseList<LPVOID>();
|
||
m_SendThreads[i].pSendProcList = new CBaseList<LPVOID>();
|
||
}
|
||
}
|
||
|
||
VOID CRunDataProcesser::UninitSendThreadData()
|
||
{
|
||
int i;
|
||
|
||
for ( i=0; i<m_nSendThreadCount; ++i )
|
||
{
|
||
SafeDelete( m_SendThreads[i].pSendAppendList );
|
||
SafeDelete( m_SendThreads[i].pSendProcList );
|
||
DeleteCriticalSection( &m_SendThreads[i].SendQueueLock );
|
||
}
|
||
}
|
||
|
||
VOID CRunDataProcesser::SendCheck(int nIdent)
|
||
{
|
||
SendServerMessage( nIdent, 0, 0, 0, m_sGateName, (int)strlen(m_sGateName) + 1 );
|
||
}
|
||
|
||
VOID CRunDataProcesser::SendGateUserInfo()
|
||
{
|
||
GATEUSERINFO gi;
|
||
gi.nUserCount = GetActiveUserCount();
|
||
gi.nGatePort = GetRunSockProcesser()->GetBindPort();
|
||
SendServerMessage(GM_GATEUSERINFO, 0, 0, 0, (char *)&gi, sizeof(GATEUSERINFO));
|
||
}
|
||
|
||
VOID CRunDataProcesser::SendOpenSession(PRUNGATEUSERSESSION pSession)
|
||
{
|
||
char sRemoteAddr[32];
|
||
strcpy( sRemoteAddr, inet_ntoa( pSession->SockAddr.sin_addr ) );
|
||
SendServerMessage( GM_OPEN, pSession->nIndex, pSession->nSocket, 0, sRemoteAddr, (int)strlen(sRemoteAddr) + 1 );
|
||
OutputMsg(rmTip, _T("SendOpenSession: socket=%d sessionId=%d, remoteAddr=%s"), (int)pSession->nSocket, (int)pSession->nIndex, sRemoteAddr);
|
||
}
|
||
|
||
VOID CRunDataProcesser::SendCloseSession(PRUNGATEUSERSESSION pSession, BOOL boCloseOnServer, INT nReason)
|
||
{
|
||
PCLIENTRECVBUF pRecvBuf;
|
||
int nSocket;
|
||
|
||
if ( !pSession->boMarkToClose && pSession->nSocket != INVALID_SOCKET )
|
||
{
|
||
OutputMsg( rmWaning, "关闭会话 socket=%d, sessionId=%d, serverId=%d,reasonId=%d,nVerifyIdx=%ld", (int)pSession->nSocket,
|
||
(int)pSession->nIndex, (int)pSession->nServerIdx, nReason, pSession->nVerifyIdx );
|
||
|
||
pSession->boMarkToClose = true;
|
||
|
||
nSocket = (int)pSession->nSocket;
|
||
pSession->nSocket = INVALID_SOCKET;
|
||
pSession->dwCloseTick = _getTickCount();
|
||
pSession->nVerifyIdx = 0;
|
||
bool isInCommu =( pSession->nSessionSatus == enCommunication); //当前是否在通信状态
|
||
pSession->nSessionSatus = enSessionStatusIdle; //初始化状态
|
||
|
||
if (nSocket!=INVALID_SOCKET) closesocket( nSocket );
|
||
|
||
//如果需要向服务器发送关闭用户的消息则将消息添加到队列
|
||
//并且需要通信状态了,否则不需要发包,说明还没有通过验证
|
||
if ( boCloseOnServer && isInCommu )
|
||
{
|
||
SendServerMessage( GM_CLOSE, 0, nSocket, 0, NULL, 0 );
|
||
}
|
||
m_nActiveUser--;
|
||
}
|
||
}
|
||
|
||
VOID CRunDataProcesser::SendKeepAliveAck(PRUNGATEUSERSESSION pSession, const char *pBuffer, SIZE_T nBufSize)
|
||
{
|
||
SendServerMessage(GM_APPKEEPALIVEACK, pSession->nIndex, pSession->nSocket, pSession->nServerIdx, (char *)pBuffer, (int)nBufSize);
|
||
}
|
||
|
||
|
||
VOID CRunDataProcesser::CloseAllSessions(BOOL boForceClose)
|
||
{
|
||
int i;
|
||
TICKCOUNT dwCurTick;
|
||
PRUNGATEUSERSESSION pSession;
|
||
|
||
if ( !m_Sessions ) return;
|
||
pSession = m_Sessions;
|
||
EnterCriticalSection( &m_SessionLock );
|
||
EnterCriticalSection( &m_RecvQueueLock );
|
||
for ( i=0; i<m_nSendThreadCount; ++i )
|
||
{
|
||
EnterCriticalSection( &m_SendThreads[i].SendQueueLock );
|
||
}
|
||
Sleep( 3000 );//休眠以等待数据接收以及各发送线程被阻塞
|
||
|
||
dwCurTick = _getTickCount();
|
||
for ( i=0; i<m_nMaxSessionCount; ++i )
|
||
{
|
||
if ( pSession->nSocket != INVALID_SOCKET )
|
||
{
|
||
if ( boForceClose )
|
||
{
|
||
OutputMsg(rmTip,_T("CRunDataProcesser::CloseAllSessions close socket=%d"),(int)pSession->nSocket);
|
||
SendCloseSession( pSession, TRUE, enReasonAllSessionClose );
|
||
//closesocket( pSession->nSocket );
|
||
pSession->boMarkToClose = true;
|
||
pSession->boRemoteClosed = true;
|
||
pSession->dwCloseTick = 0;
|
||
pSession->nSocket = INVALID_SOCKET;
|
||
pSession->nVerifyIdx = 0;
|
||
m_nActiveUser--;
|
||
|
||
if ( pSession->RecvBuf.lpBuffer )
|
||
{
|
||
free( pSession->RecvBuf.lpBuffer );
|
||
pSession->RecvBuf.lpBuffer = NULL;
|
||
}
|
||
pSession->RecvBuf.nSize = pSession->RecvBuf.nOffset = 0;
|
||
if ( pSession->SendBuf.lpBuffer )
|
||
{
|
||
free( pSession->SendBuf.lpBuffer );
|
||
pSession->SendBuf.lpBuffer = NULL;
|
||
}
|
||
pSession->SendBuf.nSize = pSession->SendBuf.nOffset = 0;
|
||
}
|
||
else SendCloseSession( pSession, TRUE, enReasonAllSessionClose );
|
||
}
|
||
pSession++;
|
||
}
|
||
|
||
for ( i=0; i<m_nSendThreadCount; ++i )
|
||
{
|
||
LeaveCriticalSection( &m_SendThreads[i].SendQueueLock );
|
||
}
|
||
LeaveCriticalSection( &m_RecvQueueLock );
|
||
LeaveCriticalSection( &m_SessionLock );
|
||
}
|
||
|
||
VOID CRunDataProcesser::CancelRemainSendSessionBuffers()
|
||
{
|
||
PSENDCLIENTBUF pSendBuf, *ppBufers;
|
||
CBaseList<LPVOID> *pBufferList;
|
||
INT_PTR i, nCount, nTotalSize;
|
||
|
||
nTotalSize = 0;
|
||
for ( i=0; i<m_nSendThreadCount; ++i )
|
||
{
|
||
EnterCriticalSection( &m_SendThreads[i].SendQueueLock );
|
||
|
||
pBufferList = m_SendThreads[i].pSendProcList;
|
||
nCount = pBufferList->count();
|
||
if ( nCount )
|
||
{
|
||
ppBufers = (PSENDCLIENTBUF*)(void**)(*pBufferList);
|
||
do
|
||
{
|
||
pSendBuf = *ppBufers;
|
||
ppBufers++;
|
||
nCount--;
|
||
nTotalSize += pSendBuf->nBufferSize;
|
||
free( pSendBuf );
|
||
}
|
||
while ( nCount > 0 );
|
||
pBufferList->clear();
|
||
}
|
||
|
||
pBufferList = m_SendThreads[i].pSendAppendList;
|
||
nCount = pBufferList->count();
|
||
if ( nCount )
|
||
{
|
||
ppBufers = (PSENDCLIENTBUF*)(void**)(*pBufferList);
|
||
do
|
||
{
|
||
pSendBuf = *ppBufers;
|
||
ppBufers++;
|
||
nCount--;
|
||
nTotalSize += pSendBuf->nBufferSize;
|
||
free( pSendBuf );
|
||
}
|
||
while ( nCount > 0 );
|
||
pBufferList->clear();
|
||
}
|
||
|
||
LeaveCriticalSection( &m_SendThreads[i].SendQueueLock );
|
||
}
|
||
|
||
InterlockedExchangeAdd( (LONG*)&m_dwWaitSendQueueSize, -(INT)nTotalSize );
|
||
}
|
||
|
||
BOOL CRunDataProcesser::CheckCloseSessions(BOOL boForceCheck)
|
||
{
|
||
static const DWORD dwCloseIdleSessionLong = 10 * 60 * 1000;
|
||
int i, boResult;
|
||
TICKCOUNT dwCurTick;
|
||
PRUNGATEUSERSESSION pSession;
|
||
|
||
if ( boForceCheck )
|
||
{
|
||
EnterCriticalSection( &m_SessionLock );
|
||
boResult = TRUE;
|
||
}
|
||
else boResult = TryEnterCriticalSection( &m_SessionLock );
|
||
|
||
if ( boResult )
|
||
{
|
||
dwCurTick = _getTickCount();
|
||
pSession = m_Sessions - 1;
|
||
|
||
for ( i=0; i<m_nMaxSessionCount; ++i )
|
||
{
|
||
pSession++;
|
||
|
||
if ( pSession->boMarkToClose || pSession->boRemoteClosed )
|
||
{
|
||
//加上pSession->dwCloseTick非0判断,防止内存错误
|
||
//可能的原因是标记pSession->boMarkToClose或pSession->boRemoteClosed为true的线程尚未来得及
|
||
//给pSession->dwCloseTick赋值,而此线程恰好已经执行到此处对pSession的资源进行释放,从而
|
||
//造成内存错误。
|
||
if ( pSession->dwCloseTick && dwCurTick - pSession->dwCloseTick >= 10 * 1000 )
|
||
{
|
||
if(pSession->nSocket != INVALID_SOCKET)
|
||
{
|
||
OutputMsg( rmWaning, "Socket%d 标记为删除",(int)pSession->nSocket );
|
||
}
|
||
|
||
LOCK_SESSION_SEND( pSession );
|
||
pSession->nSocket = INVALID_SOCKET;
|
||
pSession->nVerifyIdx = 0;
|
||
|
||
if ( pSession->RecvBuf.lpBuffer )
|
||
{
|
||
free( pSession->RecvBuf.lpBuffer );
|
||
pSession->RecvBuf.lpBuffer = NULL;
|
||
}
|
||
|
||
pSession->RecvBuf.nSize = pSession->RecvBuf.nOffset = 0;
|
||
if ( pSession->SendBuf.lpBuffer )
|
||
{
|
||
free( pSession->SendBuf.lpBuffer );
|
||
pSession->SendBuf.lpBuffer = NULL;
|
||
}
|
||
pSession->SendBuf.nSize = 0;//SendBuf.nOffset值由发送线程维护
|
||
|
||
pSession->boMarkToClose = false;
|
||
pSession->boRemoteClosed = false;
|
||
pSession->dwCloseTick = 0;
|
||
UNLOCK_SESSION_SEND( pSession );
|
||
}
|
||
}
|
||
else if ( pSession->nSocket != INVALID_SOCKET )
|
||
{
|
||
if (dwCurTick - pSession->dwClientMsgTick >= dwCloseIdleSessionLong)
|
||
{
|
||
OutputMsg( rmWaning, "客户端Idle,dwCurTick=%ld,dwClientMsgTick=%ld",(long long)dwCurTick, (long)pSession->dwClientMsgTick);
|
||
SendCloseSession( pSession, TRUE, enReasonIdle );
|
||
}
|
||
if(dwCurTick - pSession->dwServerMsgTick >= dwCloseIdleSessionLong)
|
||
{
|
||
//OutputMsg( rmWaning, "服务器较长时间处于非活动状态的会话,关闭会话" );
|
||
//OutputMsg( rmWaning, "服务器端idle,dwCurTick=%I64d,dwClientMsgTick=%I64d",(long long)dwCurTick, (long long)pSession->dwServerMsgTick);
|
||
//SendCloseSession( pSession, TRUE, enReasonIdle );
|
||
}
|
||
}
|
||
}
|
||
LeaveCriticalSection( &m_SessionLock );
|
||
}
|
||
|
||
return boResult;
|
||
}
|
||
|
||
char* getDescBySysId(int id)
|
||
{
|
||
switch (id)
|
||
{
|
||
case 0:
|
||
return "默认系统";
|
||
break;
|
||
case 1:
|
||
return "移动系统";
|
||
break;
|
||
case 2:
|
||
return "属性系统";
|
||
break;
|
||
case 3:
|
||
return "观察系统";
|
||
break;
|
||
case 4:
|
||
return "Buff系统";
|
||
break;
|
||
case 5:
|
||
return "技能系统";
|
||
break;
|
||
case 6:
|
||
return "任务系统";
|
||
break;
|
||
case 7:
|
||
return "装备系统";
|
||
break;
|
||
case 8:
|
||
return "背包系统";
|
||
break;
|
||
case 9:
|
||
return "聊天系统";
|
||
break;
|
||
case 10:
|
||
return "帮会系统";
|
||
break;
|
||
case 11:
|
||
return "技能标记";
|
||
break;
|
||
case 12:
|
||
return "商城系统";
|
||
break;
|
||
case 13:
|
||
return "交易系统";
|
||
break;
|
||
case 14:
|
||
return "玩家变量";
|
||
break;
|
||
case 15:
|
||
return "拾取系统";
|
||
break;
|
||
case 16:
|
||
return "队伍系统";
|
||
break;
|
||
case 17:
|
||
return "操练系统";
|
||
break;
|
||
case 18:
|
||
return "兵魂系统";
|
||
break;
|
||
case 20:
|
||
return "副本系统";
|
||
break;
|
||
case 21:
|
||
return "交互系统";
|
||
break;
|
||
case 22:
|
||
return "消息系统";
|
||
break;
|
||
case 23:
|
||
return "仓库系统";
|
||
break;
|
||
case 24:
|
||
return "PK系统";
|
||
break;
|
||
case 26:
|
||
return "杂七杂八";
|
||
break;
|
||
case 27:
|
||
return "交易行";
|
||
break;
|
||
case 28:
|
||
return "成就系统";
|
||
break;
|
||
case 30:
|
||
return "特效系统";
|
||
break;
|
||
case 34:
|
||
return "宠物系统";
|
||
break;
|
||
case 35:
|
||
return "交通工具";
|
||
break;
|
||
case 36:
|
||
return "盗梦空间";
|
||
break;
|
||
case 39:
|
||
return "摆摊系统";
|
||
break;
|
||
case 41:
|
||
return "好友系统";
|
||
break;
|
||
case 43:
|
||
return "宝石系统";
|
||
break;
|
||
case 44:
|
||
return "英雄系统";
|
||
break;
|
||
case 45:
|
||
return "载具系统";
|
||
break;
|
||
case 49:
|
||
return "BOSS系统";
|
||
break;
|
||
case 50:
|
||
return "邮件系统";
|
||
break;
|
||
case 51:
|
||
return "衣橱系统";
|
||
break;
|
||
case 52:
|
||
return "加速外挂";
|
||
break;
|
||
case 54:
|
||
return "新头衔";
|
||
break;
|
||
case 57:
|
||
return "职业竞技";
|
||
break;
|
||
|
||
case 128:
|
||
return "脚本";
|
||
break;
|
||
case 129:
|
||
return "NPC交易";
|
||
break;
|
||
case 130:
|
||
return "装备修理";
|
||
break;
|
||
case 134:
|
||
return "技能快捷键";
|
||
break;
|
||
case 137:
|
||
return "内劲系统";
|
||
break;
|
||
case 138:
|
||
return "福利系统";
|
||
break;
|
||
case 139:
|
||
return "脚本乱七八糟";
|
||
break;
|
||
case 140:
|
||
return "功勋系统";
|
||
break;
|
||
case 145:
|
||
return "活动系统";
|
||
break;
|
||
case 255:
|
||
return "登陆系统";
|
||
break;
|
||
default:
|
||
return "错误!";
|
||
break;
|
||
}
|
||
}
|
||
|
||
VOID CRunDataProcesser::CheckSendSessionBuffers(PRUNDATASENDTHREAD pSendThread)
|
||
{
|
||
DECLARE_FUN_TIME_PROF();
|
||
static char sSendCheckBuf[RUNGATE_ONCESENDUSE_LIMIT];
|
||
|
||
int nErr, nRemainSize;
|
||
char *pBuffer;
|
||
PRUNGATEUSERSESSION pSession = &m_Sessions[pSendThread->nThreadIdx];
|
||
|
||
pSendThread->boSendEWouldBlock = false;
|
||
pSendThread->boSendFewBuffer = false;
|
||
|
||
for ( ;pSession <= &m_Sessions[m_nMaxSessionCount-1]; pSession += m_nSendThreadCount )
|
||
{
|
||
if ( pSession->nSocket != INVALID_SOCKET && !pSession->boMarkToClose && !pSession->boRemoteClosed )
|
||
{
|
||
if ( !pSession->boSendAvaliable )
|
||
{
|
||
if ( _getTickCount() >= pSession->dwSendTimeOut )
|
||
{
|
||
pSession->boSendAvaliable = true;
|
||
pSession->dwSendTimeOut = 0;
|
||
}
|
||
else continue;
|
||
}
|
||
|
||
if ( TRYLOCK_SESSION_SEND( pSession ) )
|
||
{
|
||
nRemainSize = pSession->SendBuf.nOffset;
|
||
if ( nRemainSize > 4096 * 1024 )
|
||
{
|
||
SendCloseSession( pSession, TRUE, enReasonSenderBuffLarge );
|
||
nRemainSize = 0;
|
||
OutputMsg( rmWaning, "关闭了一个发送数据队列大于4MB的连接。" );
|
||
}
|
||
if ( nRemainSize )
|
||
{
|
||
pBuffer = pSession->SendBuf.lpBuffer;
|
||
if ( nRemainSize >= MAXINT )//不让它执行这段代码
|
||
{
|
||
sSendCheckBuf[0] = '*';
|
||
memcpy( &sSendCheckBuf[1], pBuffer, RUNGATE_ONCESENDUSE_LIMIT -1 );
|
||
nErr = ::send( pSession->nSocket, sSendCheckBuf, RUNGATE_ONCESENDUSE_LIMIT, 0 );
|
||
if ( nErr > 0 )
|
||
{
|
||
if ( nErr != RUNGATE_ONCESENDUSE_LIMIT )
|
||
pSendThread->boSendFewBuffer = true;
|
||
InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, -(nErr - 1) );
|
||
InterlockedExchangeAdd( (LONG*)&m_dwSendUserSize, nErr );
|
||
nRemainSize -= nErr - 1;
|
||
memcpy( pBuffer, &pBuffer[nErr - 1], nRemainSize );
|
||
pSession->SendBuf.nOffset = nRemainSize;
|
||
pBuffer[nRemainSize] = 0;
|
||
pSession->nSendPacketCount++;
|
||
}
|
||
else if ( !nErr || WSAGetLastError() != WSAEWOULDBLOCK )
|
||
{
|
||
InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, -pSession->SendBuf.nOffset );
|
||
pSession->boRemoteClosed = true;
|
||
pSession->SendBuf.nOffset = 0;
|
||
SendCloseSession( pSession, TRUE, enReasonSocketError );
|
||
}
|
||
else
|
||
{
|
||
pSession->boSendAvaliable = false;
|
||
pSession->dwSendTimeOut = _getTickCount() + RUNGATE_SENDCHECK_TIMEOUT;
|
||
pSendThread->boSendEWouldBlock = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
TICKCOUNT nCurTick = _getTickCount();
|
||
if (nCurTick < pSession->nLastSendPacketTime)
|
||
pSession->nLastSendPacketTime = 0;
|
||
if (nCurTick - pSession->nLastSendPacketTime >= 15)
|
||
{
|
||
pSession->nLastSendPacketTime = nCurTick;
|
||
nErr = ::send( pSession->nSocket, pBuffer, nRemainSize, 0 );
|
||
if ( nErr > 0 )
|
||
{
|
||
pSession->nSendPacketCount++;
|
||
InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, -nErr );
|
||
InterlockedExchangeAdd( (LONG*)&m_dwSendUserSize, nErr );
|
||
if ( nErr < nRemainSize )
|
||
{
|
||
pSendThread->boSendFewBuffer = true;
|
||
memcpy( pBuffer, &pBuffer[nErr], nRemainSize - nErr );
|
||
nRemainSize -= nErr;
|
||
pBuffer[nRemainSize] = 0;
|
||
pSession->SendBuf.nOffset = nRemainSize;
|
||
pSession->nTimeStampOffset = nRemainSize;
|
||
}
|
||
else
|
||
{
|
||
pBuffer[0] = 0;
|
||
pSession->SendBuf.nOffset = 0;
|
||
pSession->nTimeStampOffset = 0;
|
||
}
|
||
|
||
#ifdef _DEBUG_GATEMSG
|
||
char * pIp = inet_ntoa(pSession->SockAddr.sin_addr);
|
||
OutputMsg( rmTip, "[%s]Idx=%d: 发到客户端, 已发长度%d, 剩余待发%d;",
|
||
pIp, pSession->nVerifyIdx, nErr, pSession->SendBuf.nOffset);
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
int nErrorId = WSAGetLastError();
|
||
if ( !nErr || nErrorId != WSAEWOULDBLOCK )
|
||
{
|
||
OutputMsg(rmWaning,"Socket =%d,send fail, errorid=%d ",(int)pSession->nSocket,nErrorId);
|
||
|
||
InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, -nRemainSize );
|
||
InterlockedExchangeAdd( (LONG*)&m_dwSendUserSize, nRemainSize );
|
||
pBuffer[0] = 0;
|
||
pSession->SendBuf.nOffset = 0;
|
||
}
|
||
else
|
||
{
|
||
pSession->boSendAvaliable = false;
|
||
pSession->dwSendTimeOut = _getTickCount() + RUNGATE_SENDCHECK_TIMEOUT;
|
||
pSendThread->boSendEWouldBlock = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
UNLOCK_SESSION_SEND( pSession );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//会话关闭后减少待发送数据统计值
|
||
if ( nRemainSize = pSession->SendBuf.nOffset )
|
||
{
|
||
InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, -nRemainSize );
|
||
pSession->SendBuf.nOffset = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
}
|
||
//发送数据到服务器
|
||
VOID CRunDataProcesser::SendServerMessage(int nIdent, int nSessionIdx, SOCKET nSocket, int nServerIdx, char *pBuffer, int nBufSize)
|
||
{
|
||
if ( !connected() )
|
||
return;
|
||
|
||
PutMessage(nIdent, nSessionIdx, nSocket, nServerIdx, m_llSvrTimeDiff, pBuffer, nBufSize);
|
||
/*
|
||
if (GM_CHECKCLIENT != nIdent && GM_CHECKSERVER != nIdent && GM_DATA != nIdent)
|
||
{
|
||
TRACE( _T("向后台发送命令CMD=%d,socketID=%d,nSessionIdx=%d,nServerIdx=%d\n"), nIdent,nSocket,nSessionIdx,nServerIdx);
|
||
}
|
||
|
||
if (nIdent == GM_DATA)
|
||
{
|
||
OutputMsg( rmTip, _T("向后台发送数据size=%d,nSocket=%d,nSessionIdx=%d,nServerIdx=%d"),nBufSize,nSocket,nSessionIdx,nServerIdx);
|
||
}
|
||
*/
|
||
/* --begin 老的发送给服务器数据代码
|
||
//这个是消息头
|
||
RUNGATEMSGHDR Hdr;
|
||
Hdr.dwGateCode = RUNGATECODE;
|
||
Hdr.nSocket = nSocket;
|
||
Hdr.wSessionIdx = nSessionIdx;
|
||
Hdr.wIdent = nIdent;
|
||
Hdr.wServerIdx = nServerIdx;
|
||
Hdr.nDataSize = nBufSize;
|
||
Hdr.tickCount = m_llSvrTimeDiff + _getTickCount();
|
||
|
||
SIZE_T headSize = sizeof(Hdr);
|
||
|
||
CDataPacket &packet = allocSendPacket();
|
||
packet << Hdr;
|
||
packet.writeBuf(pBuffer, nBufSize);
|
||
flushSendPacket(packet);
|
||
---end of 老的发送数据给服务器代码
|
||
*/
|
||
|
||
/*
|
||
char buff [MAX_SEND_BUFF_SIZE];
|
||
|
||
size_t headSize = sizeof(Hdr);
|
||
size_t totalSize = headSize + nBufSize;
|
||
if (totalSize > MAX_SEND_BUFF_SIZE)
|
||
{
|
||
GotError( __FUNCTION__, _T("发送包的长度过大"), nBufSize );
|
||
return;
|
||
}
|
||
memcpy(buff,&Hdr,headSize);
|
||
memcpy((buff+headSize),pBuffer,nBufSize);
|
||
*/
|
||
//AppendSendBuffer(&Hdr,headSize );
|
||
//AppendSendBuffer(pBuffer,nBufSize );
|
||
|
||
/* 这里使用的是pipe,修改为socket发送
|
||
RUNGATEMSGHDR Hdr;
|
||
DWORD dwBytesWriten;
|
||
if ( m_hPipe != INVALID_HANDLE_VALUE )
|
||
{
|
||
Hdr.dwGateCode = RUNGATECODE;
|
||
Hdr.nSocket = nSocket;
|
||
Hdr.wSessionIdx = nSessionIdx;
|
||
Hdr.wIdent = nIdent;
|
||
Hdr.wServerIdx = nServerIdx;
|
||
Hdr.nDataSize = nBufSize;
|
||
|
||
|
||
#pragma __CPMSG__("----------------修改此处WriteFile为Socket的AppendSendData")
|
||
if ( !WriteFile( m_hPipe, &Hdr, sizeof(Hdr), &dwBytesWriten, NULL ) )
|
||
{
|
||
GotError( __FUNCTION__, "WriteFile", GetLastError() );
|
||
ServerPipeError();
|
||
}
|
||
else if ( nBufSize > 0 && !WriteFile( m_hPipe, pBuffer, nBufSize, &dwBytesWriten, NULL ) )
|
||
{
|
||
GotError( __FUNCTION__, "WriteFile", GetLastError() );
|
||
ServerPipeError();
|
||
}
|
||
}
|
||
*/
|
||
}
|
||
|
||
/*
|
||
* 解包WebSocket数据
|
||
* param[in] pSession 用户会话
|
||
* param[] pInBuff 输入的数据包
|
||
* param[] nInSize 输入的数据包的长度
|
||
* param[] pOutBuff 输出的数据包指针
|
||
* param[] nOutSize 输出的数据包的长度
|
||
* param[] nInProcessSize 输入的数据包处理了的长度,如果大于0,那么前面的这个字节的数据包可以丢弃了
|
||
* param[] nOutProcessSize 处理好的数据长度,处理好的数据放在pOutBuff里
|
||
* ret 如果进行了数据处理返回true,否则返回false。数据处理包括发现前面有无效数字,拷贝了一个完整的数据包,丢弃一些字节等
|
||
*/
|
||
static bool WebSocketDataUnpack(PRUNGATEUSERSESSION pSession,
|
||
char* pInBuff, SIZE_T nInSize,
|
||
char* pOutBuff, SIZE_T nOutSize,
|
||
SIZE_T& nInProcessSize, SIZE_T& nOutProcessSize)
|
||
{
|
||
pSession->webSocketHead.reset();
|
||
|
||
nInProcessSize = 0;
|
||
nOutProcessSize = 0;
|
||
if (NULL == pInBuff || NULL == pOutBuff) return false;
|
||
|
||
char* pdata = pInBuff;
|
||
SIZE_T nLeftSize = nInSize;
|
||
#define WEBSOCKET_READ(_TYPE) *((_TYPE*)pdata); nLeftSize -= sizeof(_TYPE); pdata += sizeof(_TYPE)
|
||
|
||
//读取websocket固定包头
|
||
if (!pSession->webSocketHead.rh)
|
||
{
|
||
//长度不满足
|
||
if (nLeftSize < 2) return false;
|
||
|
||
//读取
|
||
uint8_t head = WEBSOCKET_READ(uint8_t);
|
||
pSession->webSocketHead.fin = head >> 7;
|
||
pSession->webSocketHead.opcode = emOpcode(head & 0xF);
|
||
head = WEBSOCKET_READ(uint8_t);
|
||
pSession->webSocketHead.len = head & 0x7F;
|
||
pSession->webSocketHead.mask = head >> 7;
|
||
pSession->webSocketHead.rh = 1;//标记头部读取完成
|
||
|
||
nInProcessSize += 2;//记录处理长度
|
||
}
|
||
|
||
//读取长度
|
||
if (!pSession->webSocketHead.rl)
|
||
{
|
||
uint8_t nsize = pSession->webSocketHead.GetLenNeedByte();
|
||
if (nsize)
|
||
{
|
||
//这个包不够一个长度
|
||
if (nLeftSize < nsize) return false;
|
||
|
||
if (nsize == 2) {
|
||
pSession->webSocketHead.ex_len.v16 = WEBSOCKET_READ(uint16_t);
|
||
pSession->webSocketHead.ex_len.v16 = ntohs(pSession->webSocketHead.ex_len.v16);
|
||
nInProcessSize += 2; //记录处理长度
|
||
} else {
|
||
pSession->webSocketHead.ex_len.v64 = WEBSOCKET_READ(uint64_t);
|
||
pSession->webSocketHead.ex_len.v64 = ntohl((u_long)pSession->webSocketHead.ex_len.v64);
|
||
nInProcessSize += 8; //记录处理长度
|
||
}
|
||
}
|
||
pSession->webSocketHead.rl = 1;
|
||
}
|
||
|
||
//读取MKEY
|
||
if (!pSession->webSocketHead.rk)
|
||
{
|
||
if (pSession->webSocketHead.mask) {
|
||
|
||
//这个包不够一个key长度
|
||
if (nLeftSize < 4) return false;
|
||
|
||
pSession->webSocketHead.mkey[0] = WEBSOCKET_READ(uint8_t);
|
||
pSession->webSocketHead.mkey[1] = WEBSOCKET_READ(uint8_t);
|
||
pSession->webSocketHead.mkey[2] = WEBSOCKET_READ(uint8_t);
|
||
pSession->webSocketHead.mkey[3] = WEBSOCKET_READ(uint8_t);
|
||
nInProcessSize += 4; //记录处理长度
|
||
}
|
||
pSession->webSocketHead.rk = 1;
|
||
}
|
||
|
||
//读取数据段
|
||
uint64_t data_len = pSession->webSocketHead.GetLen();
|
||
if (nLeftSize < data_len) return false;
|
||
|
||
// 掩码处理
|
||
if (pSession->webSocketHead.mask)
|
||
{
|
||
char* dptr = pdata;
|
||
for (size_t i = 0; i < data_len; ++i) {
|
||
dptr[i] = dptr[i] ^ pSession->webSocketHead.mkey[i % 4];
|
||
}
|
||
}
|
||
|
||
memcpy(pOutBuff,(void *)(pInBuff + nInProcessSize), data_len);
|
||
//OutputMsg( rmTip, "Websocket数据(头长:%ld, 数据长:%ld)", nInProcessSize, data_len, *((int*)pInBuff));
|
||
nInProcessSize += data_len;
|
||
nOutProcessSize = data_len;
|
||
return true;
|
||
}
|
||
|
||
//收到用户的数据包
|
||
VOID CRunDataProcesser::ProcessUserRecvPacket(PRUNGATEUSERSESSION pSession, char *pBuffer, int nBufferSize)
|
||
{
|
||
DECLARE_FUN_TIME_PROF();
|
||
//static const char szFlashSocketPolicyRequest[] = "<policy-file-request/>";
|
||
//static const char szFlashSocketPolicyRequestReply[]= "<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>";
|
||
//static int s_policyStrLen = (int)strlen(szFlashSocketPolicyRequest) +1; //请求安全策略文件的长度,后面都是以\0结尾的
|
||
//static int s_policyReplyStrLen = (int)strlen(szFlashSocketPolicyRequestReply) +1;//回复安全策略文件的长度
|
||
|
||
InterlockedExchangeAdd( (LONG*)&m_dwProcessRecvSize, nBufferSize );
|
||
|
||
//session中已缓存的数据(剩下待处理的数据)
|
||
int nLeftDataSize = pSession->RecvBuf.nOffset + nBufferSize + 1;
|
||
if ( pSession->RecvBuf.nSize < nLeftDataSize )
|
||
{
|
||
pSession->RecvBuf.nSize = (nLeftDataSize / SESSION_DATAGROW_SIZE + 1) * SESSION_DATAGROW_SIZE;
|
||
pSession->RecvBuf.lpBuffer = (char*)realloc( pSession->RecvBuf.lpBuffer, pSession->RecvBuf.nSize );
|
||
}
|
||
nLeftDataSize--;
|
||
|
||
//将数据拷贝过来
|
||
char *pDataBuffer;
|
||
pDataBuffer = pSession->RecvBuf.lpBuffer;
|
||
memcpy( &pDataBuffer[pSession->RecvBuf.nOffset], pBuffer, nBufferSize );
|
||
pSession->RecvBuf.nOffset = nLeftDataSize;
|
||
pDataBuffer[nLeftDataSize] = 0;
|
||
|
||
//如果剩余数据超过峰值则丢弃
|
||
if ( pSession->RecvBuf.nOffset >= SESSION_MAX_RECVPROC_SIZE )
|
||
{
|
||
pSession->RecvBuf.nOffset = 0;
|
||
SendCloseSession( pSession, TRUE, enReasonLargePackLeft );
|
||
return;
|
||
}
|
||
|
||
//输出日志
|
||
#ifdef _DEBUG_GATEMSG
|
||
//char * pIp = inet_ntoa(pSession->SockAddr.sin_addr);
|
||
OutputMsg( rmTip, "Idx=%ld: 准备处理socket数据, session状态为%d, 当前接收缓存为%d;",
|
||
pSession->nVerifyIdx, pSession->nSessionSatus, nLeftDataSize);
|
||
#endif
|
||
|
||
//SIZE_T nPolicyStrSize = (int)strlen(szFlashSocketPolicyRequest);
|
||
|
||
//处理Session的buffer
|
||
char pDataProcBuf[MAX_SEND_BUFF_SIZE];
|
||
#ifdef _DEBUG_GATEMSG
|
||
memset(pDataProcBuf, 0, MAX_SEND_BUFF_SIZE);
|
||
#endif
|
||
while ( nLeftDataSize > 0 )
|
||
{
|
||
if ( pSession->wPacketError >= SESSION_PACKETERR_MAX )
|
||
{
|
||
nLeftDataSize = 0;
|
||
SendCloseSession( pSession, TRUE, enReasonRecvLargerPack );
|
||
OutputMsg( rmWaning, "wPacketError=%d,超出了",pSession->wPacketError);
|
||
break;
|
||
}
|
||
if ( pSession->boMarkToClose || pSession->boRemoteClosed )
|
||
{
|
||
OutputMsg( rmTip, "远程关闭,不处理数据");
|
||
break;
|
||
}
|
||
SIZE_T nBuffSize = pSession->RecvBuf.nOffset ;
|
||
|
||
//正常通信状态,这个最多放前面
|
||
if (pSession->nSessionSatus != enSessionStatusIdle)
|
||
{
|
||
SIZE_T nInprocessSize =0 ,nOutProcessSize =0;
|
||
|
||
// Websocket数据解包处理
|
||
if (WebSocketDataUnpack(pSession, pDataBuffer, nLeftDataSize,
|
||
pDataProcBuf, MAX_SEND_BUFF_SIZE, nInprocessSize, nOutProcessSize))
|
||
{
|
||
// 调整已处理过的字节
|
||
if (nInprocessSize > 0)
|
||
{
|
||
nLeftDataSize -= (INT)nInprocessSize;
|
||
if (nLeftDataSize < 0)
|
||
{
|
||
nLeftDataSize = 0;
|
||
}
|
||
else
|
||
{
|
||
pDataBuffer = (char *)(pDataBuffer + nInprocessSize);
|
||
}
|
||
}
|
||
|
||
#ifdef _DEBUG_GATEMSG
|
||
OutputMsg( rmTip, "Idx=%ld: 已处理%d, 协议有效长%d, 当前接收缓存为%d;",
|
||
pSession->nVerifyIdx, nInprocessSize, nOutProcessSize, nLeftDataSize);
|
||
#endif
|
||
|
||
// 将输出的数据要传递到LogicServer
|
||
if (nOutProcessSize > 0)
|
||
{
|
||
//正常通讯
|
||
if (pSession->nSessionSatus == enCommunication)
|
||
{
|
||
//检查退出
|
||
if (pSession->webSocketHead.opcode == emOpcode(0x8))
|
||
{
|
||
OutputMsg( rmTip, "远程关闭,不处理数据");
|
||
SendCloseSession(pSession, TRUE, 1);
|
||
return;
|
||
}
|
||
|
||
//检查服务端key
|
||
if (nOutProcessSize >= 2)
|
||
{
|
||
unsigned short tag = *((unsigned short*)pDataProcBuf);
|
||
if(tag != pSession->nKey)
|
||
{
|
||
SendCloseSession(pSession, TRUE, 2);
|
||
return;
|
||
}
|
||
|
||
//截去key
|
||
char* pOutData = (char*)pDataProcBuf + sizeof(unsigned short);
|
||
nOutProcessSize -= sizeof(unsigned short);
|
||
|
||
//截去验证
|
||
uint32_t check = *((uint32_t*)pOutData);
|
||
pOutData = pOutData + sizeof(uint32_t);
|
||
nOutProcessSize -= sizeof(uint32_t);
|
||
|
||
//测试代码,数据转发给客户端
|
||
//PostUserServerData(pSession, pOutData, (INT)nOutProcessSize, TRUE, TRUE);
|
||
|
||
#ifdef _DEBUG_GATEMSG
|
||
OutputMsg( rmTip, "Idx=%ld: 准备发服务器 [%s] SysID:%d, CmdID:%d;",
|
||
pSession->nVerifyIdx, getDescBySysId(*((unsigned char*)pOutData)), *((unsigned char*)pOutData), *((unsigned char*)pOutData + 1));
|
||
#endif
|
||
|
||
//把数据发到服务器
|
||
SendServerMessage(GM_DATA, pSession->nIndex, pSession->nSocket,
|
||
pSession->nServerIdx, pOutData, (INT)nOutProcessSize);
|
||
//OutputMsg( rmTip, "systemID = %d", *((char*)(pOutData)));
|
||
//OutputMsg( rmTip, "cmdID = %d", *((char*)(pOutData + 1)));
|
||
}
|
||
}
|
||
//刚连上来
|
||
else if(pSession->nSessionSatus == enConn)
|
||
{
|
||
pSession->nKey = (unsigned short)wrand(INT_MAX);
|
||
PostUserServerData(pSession, (char *)&pSession->nKey, 2);
|
||
pSession->nSessionSatus = enCommunication;
|
||
OutputMsg( rmTip, "=================================================Finish");
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
OutputMsg( rmTip, "消息长度不够,等待下一次组包");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
//修正Session的buffer
|
||
if (pSession->RecvBuf.lpBuffer != NULL)
|
||
{
|
||
if ( nLeftDataSize > 0 )
|
||
{
|
||
if ( pDataBuffer != pSession->RecvBuf.lpBuffer )
|
||
{
|
||
memcpy( pSession->RecvBuf.lpBuffer, &pSession->RecvBuf.lpBuffer[pSession->RecvBuf.nOffset - nLeftDataSize], nLeftDataSize );
|
||
pSession->RecvBuf.lpBuffer[nLeftDataSize] = 0;
|
||
pSession->RecvBuf.nOffset = nLeftDataSize;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pSession->RecvBuf.lpBuffer[0] = 0;
|
||
pSession->RecvBuf.nOffset = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
int CRunDataProcesser::s_nIgnoreDataPacket = 0;
|
||
VOID CRunDataProcesser::PostUserServerData(PRUNGATEUSERSESSION pSession, const char *pBuffer, int nBufferSize, BOOL boWriteWsHdr, BOOL boWriteProtoHdr, TICKCOUNT nSendTime)
|
||
{
|
||
/*if (s_nIgnoreDataPacket)
|
||
{
|
||
return;
|
||
} */
|
||
|
||
//OutputMsg( rmTip, "向玩家发送%d个字节数据",nBufferSize);
|
||
DECLARE_FUN_TIME_PROF();
|
||
char *pDataPtr;
|
||
PRUNDATASENDTHREAD pSendThread;
|
||
PSENDCLIENTBUF pSendBuf;
|
||
PDATAHEADER pProtoHdr;
|
||
static char sPrintS2CBuffer[81920];
|
||
|
||
pSendThread = &m_SendThreads[pSession->nIndex % m_nSendThreadCount];
|
||
pSendBuf = (PSENDCLIENTBUF)malloc( nBufferSize + sizeof(*pSendBuf) + 4 + sizeof(*pProtoHdr) + 16);
|
||
pSendBuf->pSession = pSession;
|
||
|
||
|
||
int wsheaderLength = 0;
|
||
pDataPtr = (char*)(pSendBuf + 1);
|
||
CDataPacket pack(pDataPtr, nBufferSize + 4 + sizeof(*pProtoHdr) + 16);
|
||
pack.setPosition(0);
|
||
|
||
// 写入websocket头部
|
||
if( boWriteWsHdr )
|
||
{
|
||
int totallen = boWriteProtoHdr ? nBufferSize + sizeof(uint16_t) : nBufferSize;
|
||
pack << (uint8_t)0x82;//写头部
|
||
//写长度
|
||
if (totallen >= 126) {//7位放不下
|
||
if (totallen <= 0xFFFF) {//16位放
|
||
pack << (uint8_t)126;
|
||
pack << (uint16_t)htons((u_short)totallen);
|
||
} else {//64位放
|
||
pack << (uint8_t)127;
|
||
pack << (uint64_t)OrderSwap64(totallen);
|
||
}
|
||
} else {
|
||
pack << (uint8_t)totallen;
|
||
}
|
||
}
|
||
|
||
// 写入协议头部
|
||
if ( boWriteProtoHdr )
|
||
{
|
||
//DATAHEADER ProtoHd;
|
||
//ProtoHd.tag = DEFAULT_TAG_VALUE;
|
||
//ProtoHd.len = nBufferSize;
|
||
//ProtoHd.u.tp = nSendTime - m_llSvrTimeDiff; // 网关收到来自服务器的数据包,盖上时间戳
|
||
//ProtoHd.u.tp = __max(0, _getTickCount() - (nSendTime - m_llSvrTimeDiff));
|
||
//pack.writeBuf(&ProtoHd, sizeof(DATAHEADER));
|
||
|
||
//写数据
|
||
pack << (uint16_t)pSession->nKey;
|
||
}
|
||
|
||
//写数据
|
||
pack.writeBuf(pBuffer, nBufferSize);
|
||
|
||
// 写入数据总长度
|
||
pack.setPosition(0);
|
||
pSendBuf->nBufferSize = pack.getAvaliableLength();
|
||
|
||
#ifdef _DEBUG_GATEMSG
|
||
OutputMsg( rmTip, "Idx=%d: 准备发客户端 [%s] SysID:%d, CmdID:%d, 数据长:%d, 协议有效长:%d",
|
||
pSession->nVerifyIdx, getDescBySysId(*((unsigned char*)pBuffer)), *((unsigned char*)pBuffer), *((unsigned char*)pBuffer + 1), pSendBuf->nBufferSize, nBufferSize);
|
||
#endif
|
||
|
||
InterlockedExchangeAdd( (LONG*)&m_dwWaitSendQueueSize, nBufferSize );
|
||
EnterCriticalSection( &pSendThread->SendQueueLock );
|
||
pSendThread->pSendAppendList->add( pSendBuf );
|
||
LeaveCriticalSection( &pSendThread->SendQueueLock );
|
||
}
|
||
|
||
/*
|
||
VOID CRunDataProcesser::PostUserServerRawData(PRUNGATEUSERSESSION pSession, const char *pBuffer, DWORD dwBufferSize)
|
||
{
|
||
char *pDataPtr;
|
||
PRUNDATASENDTHREAD pSendThread;
|
||
PSENDCLIENTBUF pSendBuf;
|
||
|
||
pSendThread = &m_SendThreads[pSession->nIndex % m_nSendThreadCount];
|
||
|
||
if (dwBufferSize > 0)
|
||
{
|
||
|
||
pSendBuf = (PSENDCLIENTBUF)malloc( sizeof(*pSendBuf) + dwBufferSize + 1 );
|
||
pSendBuf->pSession = pSession;
|
||
|
||
pDataPtr = (char*)(pSendBuf + 1);
|
||
memcpy( pDataPtr, pBuffer, dwBufferSize );
|
||
pDataPtr[dwBufferSize] = 0;
|
||
|
||
pSendBuf->nBufferSize = dwBufferSize;
|
||
InterlockedExchangeAdd( (LONG*)&m_dwWaitSendQueueSize, dwBufferSize );
|
||
}
|
||
EnterCriticalSection( &pSendThread->SendQueueLock );
|
||
pSendThread->pSendAppendList->add( pSendBuf );
|
||
LeaveCriticalSection( &pSendThread->SendQueueLock );
|
||
}
|
||
*/
|
||
|
||
|
||
INT CRunDataProcesser::GetActiveUserCount()
|
||
{
|
||
return m_nActiveUser;
|
||
}
|
||
|
||
VOID CRunDataProcesser::SetName(LPCSTR sName)
|
||
{
|
||
ZeroMemory( m_sGateName, sizeof(m_sGateName) );
|
||
strncpy( m_sGateName, sName, __min(sizeof(m_sGateName)-1, strlen(sName)) );
|
||
SetClientName(sName);
|
||
}
|
||
/*
|
||
VOID CRunDataProcesser::SetPipeName(LPCSTR sPipeName)
|
||
{
|
||
ZeroMemory( m_sPipeName, sizeof(m_sPipeName) );
|
||
strncpy( m_sPipeName, sPipeName, __min(sizeof(m_sPipeName)-1, strlen(sPipeName)) );
|
||
}
|
||
*/
|
||
|
||
INT CRunDataProcesser::GetSendThreadCount()
|
||
{
|
||
return m_nSendThreadCount;
|
||
}
|
||
|
||
VOID CRunDataProcesser::SetSendThreadCount(INT ThreadCount)
|
||
{
|
||
if ( !m_boStarted && ThreadCount > 0 && ThreadCount <= RUNDATA_MAX_SENDTHREAD )
|
||
{
|
||
m_nSendThreadCount = ThreadCount;
|
||
}
|
||
}
|
||
|
||
DATAPROCESSERTYPE CRunDataProcesser::GetDataProcessType()
|
||
{
|
||
return m_DataProcessType;
|
||
}
|
||
|
||
VOID CRunDataProcesser::SetDataProcessType(DATAPROCESSERTYPE Type)
|
||
{
|
||
m_DataProcessType = Type;
|
||
}
|
||
|
||
VOID CRunDataProcesser::SetRunSockProcesser(CRunSockProcesser* pSockProcesser)
|
||
{
|
||
m_pSockProcesser = pSockProcesser;
|
||
}
|
||
|
||
INT CRunDataProcesser::GetMaxSessionCount()
|
||
{
|
||
return m_nMaxSessionCount;
|
||
}
|
||
|
||
PRUNDATASENDTHREAD CRunDataProcesser::GetSendThreadInfo(INT ThreadIdx)
|
||
{
|
||
if ( ThreadIdx >= 0 && ThreadIdx < RUNDATA_MAX_SENDTHREAD )
|
||
{
|
||
if ( m_SendThreads[ThreadIdx].hThread )
|
||
return &m_SendThreads[ThreadIdx];
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
PRUNGATEUSERSESSION CRunDataProcesser::GetFirstSession()
|
||
{
|
||
return m_Sessions;
|
||
}
|
||
|
||
VOID CRunDataProcesser::SetPrintC2SMessage(const BOOL boPrint)
|
||
{
|
||
m_boPrintC2SMsg = boPrint;
|
||
}
|
||
|
||
VOID CRunDataProcesser::SetPrintS2CMessage(const BOOL boPrint)
|
||
{
|
||
m_boPrintS2CMsg = boPrint;
|
||
}
|
||
|
||
|
||
|
||
BOOL CRunDataProcesser::Startup()
|
||
{
|
||
int i;
|
||
|
||
m_boStoping = FALSE;
|
||
|
||
m_dwWaitSendUserSize = 0;
|
||
m_dwWaitSendQueueSize = 0;
|
||
m_dwLastProcUsrMsgTime = 0;
|
||
m_dwLastProcSrvMsgTime = 0;
|
||
m_dwLastRecvSrvMsgTime = 0;
|
||
m_dwRecvSeverSize = 0;
|
||
m_dwSendUserSize = 0;
|
||
m_dwProcSrvThreadSleep = 0;
|
||
m_dwSendQueueSize = 0;
|
||
|
||
//初始化会话队列
|
||
InitSessions();
|
||
|
||
//创建用户数据处理线程
|
||
#ifdef _MSC_VER
|
||
m_hProcRecvThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)RecvDataProcessRoutine, this, 0, NULL );
|
||
if ( !m_hProcRecvThread )
|
||
{
|
||
GotError( __FUNCTION__, _T("CreateThread"), GetLastError() );
|
||
return FALSE;
|
||
}
|
||
#else
|
||
if (pthread_create(&m_hProcRecvThread, NULL, RecvDataProcessRoutine, this)) {
|
||
return FALSE;
|
||
}
|
||
#endif
|
||
|
||
//创建用户数据发送线程
|
||
for ( i=0; i<m_nSendThreadCount; ++i )
|
||
{
|
||
m_SendThreads[i].pRunData = this;
|
||
m_SendThreads[i].nThreadIdx = i;
|
||
m_SendThreads[i].boSendEWouldBlock = false;
|
||
m_SendThreads[i].boSendFewBuffer = false;
|
||
#ifdef _MSC_VER
|
||
m_SendThreads[i].hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)SendDataProcessRoutine, &m_SendThreads[i], 0, &m_SendThreads[i].dwThreadId );
|
||
if ( !m_SendThreads[i].hThread )
|
||
{
|
||
GotError( __FUNCTION__, _T("CreateThread"), GetLastError() );
|
||
return FALSE;
|
||
}
|
||
#else
|
||
if (pthread_create(&(m_SendThreads[i].hThread), NULL, SendDataProcessRoutine, &m_SendThreads[i])) {
|
||
return FALSE;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
if ( Inherited::Startup() )
|
||
{
|
||
m_boStarted = TRUE;
|
||
return TRUE;
|
||
}
|
||
else return FALSE;
|
||
}
|
||
|
||
|
||
int CRunDataProcesser::ChangeConsoleLine(int nLine, int nPos, LPCSTR sFormat, ...)
|
||
{
|
||
COORD cPos;
|
||
va_list args;
|
||
|
||
cPos.X = nPos;
|
||
cPos.Y = nLine;
|
||
#ifdef _MSC_VER
|
||
SetConsoleCursorPosition( g_hStdOut, cPos );
|
||
#endif
|
||
va_start(args, sFormat);
|
||
cPos.X = vfprintf( stdout, sFormat, args );
|
||
va_end(args);
|
||
|
||
return cPos.X;
|
||
}
|
||
|
||
VOID CRunDataProcesser::ShowGateStatus(CRunDataProcesser *pRunData)
|
||
{
|
||
int i, nLine = 0;
|
||
PRUNDATASENDTHREAD pSendThread;
|
||
|
||
ChangeConsoleLine( nLine, 0, "---------------------网关状态[%s]-----------------\n", pRunData->GetName());
|
||
nLine++;
|
||
|
||
ChangeConsoleLine( nLine, 0, "活动连接数:%d \n", pRunData->GetActiveUserCount() );
|
||
nLine++;
|
||
|
||
ChangeConsoleLine( nLine, 0, "接收用户数据: %dB 发送用户数据: %dKB 待发用户数据: %dKB 待发用户队列: %dKB \n",
|
||
pRunData->m_dwProcessRecvSize, pRunData->m_dwSendUserSize / 1024, pRunData->m_dwWaitSendUserSize / 1024,
|
||
pRunData->m_dwSendQueueSize / 1024 );
|
||
nLine++;
|
||
|
||
ChangeConsoleLine( nLine, 0, "接收引擎数据: %dKB 接收数据时间: %d毫秒 引擎数据处理: %d毫秒 用户数据处理: %d毫秒 \n",
|
||
pRunData->m_dwRecvSeverSize / 1024, pRunData->m_dwLastRecvSrvMsgTime, pRunData->m_dwLastProcSrvMsgTime,
|
||
pRunData->m_dwLastProcUsrMsgTime );
|
||
nLine++;
|
||
|
||
for ( i=0; i<RUNDATA_MAX_SENDTHREAD; ++i )
|
||
{
|
||
pSendThread = pRunData->GetSendThreadInfo( i );
|
||
if ( !pSendThread )
|
||
continue;
|
||
ChangeConsoleLine( nLine, 0, "发送线程%d[数据处理: %d毫秒 休眠时间: %d毫秒 标志:%d/%d] \n",
|
||
i, pSendThread->dwProcTick, pSendThread->dwSleepTick, pSendThread->boSendEWouldBlock, pSendThread->boSendFewBuffer );
|
||
nLine++;
|
||
InterlockedExchange( (LONG*)&pSendThread->dwProcTick, 0 );
|
||
InterlockedExchange( (LONG*)&pSendThread->dwSleepTick, 0 );
|
||
}
|
||
|
||
ChangeConsoleLine( nLine, 0, "服务器数据处理线程休眠: %d毫秒\n",
|
||
pRunData->m_dwProcSrvThreadSleep );
|
||
nLine++;
|
||
|
||
ChangeConsoleLine( nLine, 0, "----------------------------------------------------------------\n" );
|
||
nLine++;
|
||
pRunData->Dump();
|
||
InterlockedExchange( (LONG*)&pRunData->m_dwProcessRecvSize, 0 );
|
||
InterlockedExchange( (LONG*)&pRunData->m_dwSendUserSize, 0 );
|
||
InterlockedExchange( (LONG*)&pRunData->m_dwRecvSeverSize, 0 );
|
||
|
||
}
|
||
|
||
VOID CRunDataProcesser::Stop()
|
||
{
|
||
int i;
|
||
m_boStoping = TRUE;
|
||
|
||
Inherited::Stop();
|
||
|
||
CloseThread( m_hProcRecvThread );
|
||
for ( i=0; i<m_nSendThreadCount; ++i )
|
||
{
|
||
if ( m_SendThreads[i].hThread )
|
||
{
|
||
CloseThread( m_SendThreads[i].hThread );
|
||
FreeSendBuffers( &m_SendThreads[i] );
|
||
}
|
||
}
|
||
|
||
//CloseServerPipe();
|
||
|
||
|
||
if ( m_ServerBuf.lpBuffer )
|
||
{
|
||
free( m_ServerBuf.lpBuffer );
|
||
m_ServerBuf.lpBuffer = NULL;
|
||
}
|
||
m_ServerBuf.nOffset = m_ServerBuf.nSize = 0;
|
||
|
||
FreeRecvBuffers();
|
||
|
||
//FreeSendBuffers();
|
||
|
||
CancelRemainSendSessionBuffers();
|
||
|
||
CloseAllSessions( TRUE );
|
||
|
||
UninitSessions();
|
||
|
||
m_boStarted = FALSE;
|
||
}
|
||
|
||
//创建一个Session
|
||
PRUNGATEUSERSESSION CRunDataProcesser::NewSession(SOCKET nSocket, SOCKADDRIN RemoteAddr)
|
||
{
|
||
if (!connected())
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
int i;
|
||
PRUNGATEUSERSESSION pSession, pNewSession = NULL;
|
||
/*
|
||
if ( m_hPipe == INVALID_HANDLE_VALUE )
|
||
return NULL;
|
||
*/
|
||
OutputMsg( rmTip, "=================================================Begin");
|
||
OutputMsg( rmTip, "开始接入新的socket=%d", (int)nSocket);
|
||
EnterCriticalSection( &m_SessionLock );
|
||
pSession = m_Sessions;
|
||
for ( i=0; i<m_nMaxSessionCount; ++i )
|
||
{
|
||
//这里安潮发现一个问题,在多线程的情况下一个线程要了一个session,然后睡眠了,另外一个线程可能依然获得这个session
|
||
if ( pSession->nSocket == INVALID_SOCKET &&
|
||
!pSession->boMarkToClose &&
|
||
!pSession->boRemoteClosed &&
|
||
!pSession->dwCloseTick &&
|
||
pSession->nSessionSatus ==enSessionStatusIdle)
|
||
{
|
||
pNewSession = pSession;
|
||
pNewSession->SendBuf.nOffset = 0;
|
||
pNewSession->dwCloseTick = 0;
|
||
pNewSession->boMarkToClose = false;
|
||
pNewSession->boRemoteClosed = false;
|
||
pNewSession->nSessionSatus = enConn;
|
||
break;
|
||
}
|
||
pSession++;
|
||
}
|
||
LeaveCriticalSection( &m_SessionLock );
|
||
|
||
if ( pNewSession )
|
||
{
|
||
pNewSession->SockAddr = RemoteAddr;
|
||
pNewSession->nServerIdx = 0;
|
||
pNewSession->btPacketIdx = 0;
|
||
pNewSession->wPacketError = 0;
|
||
pNewSession->nRecvPacketCount=0;
|
||
pNewSession->nSendPacketCount=0;
|
||
pNewSession->boMarkToClose = false;
|
||
pNewSession->boRemoteClosed = false;
|
||
pNewSession->boSendAvaliable= true;
|
||
pNewSession->dwSendTimeOut = 0;
|
||
pNewSession->dwCloseTick = 0;
|
||
pNewSession->dwConnectTick = _getTickCount();
|
||
pNewSession->dwClientMsgTick= pNewSession->dwConnectTick;
|
||
pNewSession->dwServerMsgTick= pNewSession->dwConnectTick;
|
||
pNewSession->nVerifyIdx = InterlockedIncrement( (unsigned long long*)&m_nUserVerify );
|
||
pNewSession->webSocketHead.reset();
|
||
pNewSession->webSocketShakeHand = false;
|
||
pNewSession->sLoginAccount[0] = 0;
|
||
pNewSession->sLoginCharName[0]= 0;
|
||
//pNewSession->nSessionId = 0;
|
||
if ( !pNewSession->RecvBuf.lpBuffer )
|
||
{
|
||
pNewSession->RecvBuf.nSize = SESSION_RECV_BUFSIZE ;
|
||
pNewSession->RecvBuf.lpBuffer = (char*)malloc( pNewSession->RecvBuf.nSize );
|
||
}
|
||
pNewSession->RecvBuf.nOffset = 0;
|
||
#ifdef WIN32
|
||
pNewSession->Overlapped.WSABuf.buf = pNewSession->sRecvBuf;
|
||
pNewSession->Overlapped.WSABuf.len = sizeof(pNewSession->sRecvBuf) - 1;
|
||
#endif
|
||
pNewSession->sRecvBuf[sizeof(pNewSession->sRecvBuf)] = 0;
|
||
|
||
if ( !pNewSession->SendBuf.lpBuffer )
|
||
{
|
||
pNewSession->SendBuf.nSize = SESSION_SEND_BUFSIZE ;
|
||
pNewSession->SendBuf.lpBuffer = (char*)malloc( pNewSession->SendBuf.nSize );
|
||
}
|
||
pNewSession->SendBuf.nOffset = 0;
|
||
//最后设置会话的nSocket成员数据,
|
||
//以防止其他线程通过nSocket != INVALID_SOCKET判断后对一个尚为初始化完毕的会话进行操作!
|
||
pNewSession->nSocket = nSocket;
|
||
pNewSession->nSessionSatus = enConn; //开始处于连接状态
|
||
char * pIp = inet_ntoa(RemoteAddr.sin_addr);
|
||
|
||
OutputMsg( rmTip, "[%s]接入新的socket=%d 完毕,nVerifyIdx=%ld",pIp, (int)nSocket,pNewSession->nVerifyIdx);
|
||
|
||
m_nActiveUser++; //增加活动用户计数
|
||
|
||
struct timeval tv_timeout;
|
||
tv_timeout.tv_sec = 10;
|
||
tv_timeout.tv_usec = 0;
|
||
setsockopt(nSocket,SOL_SOCKET,SO_RCVTIMEO,&tv_timeout, sizeof(tv_timeout));
|
||
setsockopt(nSocket,SOL_SOCKET,SO_SNDLOWAT,&tv_timeout, sizeof(tv_timeout));
|
||
|
||
int nErr = ::recv(pNewSession->nSocket, pNewSession->sRecvBuf, sizeof(pNewSession->sRecvBuf)-1, 0);
|
||
if ( nErr > 0 )
|
||
{
|
||
pNewSession->sRecvBuf[nErr] = 0;
|
||
AddRecvBuf( pNewSession, pNewSession->nVerifyIdx, pNewSession->sRecvBuf, nErr );
|
||
}
|
||
else if (nErr == SOCKET_ERROR)
|
||
{
|
||
pNewSession->boRemoteClosed = true;
|
||
SendCloseSession( pNewSession, TRUE, 2002 );
|
||
}
|
||
}
|
||
return pNewSession;
|
||
}
|
||
|
||
static bool gFindHttpParam(const char * param, const char * buf) {
|
||
while (*param == *buf) {
|
||
if (*(param + 1) == '\0') return true;
|
||
++param; ++buf;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
#define WEB_SOCKET_HANDS_RE "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\n\r\n"
|
||
#define MAGIC_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||
VOID CRunDataProcesser::ShakeHandsHandle(PRUNGATEUSERSESSION pSession, char* pBuffer, int BufferSize) {
|
||
char key[512]; memset(key, 0, 512);
|
||
for (int i = 0; i < BufferSize; ++i)
|
||
{
|
||
if (gFindHttpParam("Sec-WebSocket-Key", pBuffer+i)) {
|
||
short k = i + 17, ki = 0;
|
||
while(*(pBuffer + k) != '\r' && *(pBuffer + k) != '\n') {
|
||
if (*(pBuffer + k) == ':' || *(pBuffer + k) == ' '){
|
||
++k; continue;
|
||
} else {
|
||
key[ki++] = *(pBuffer + k);
|
||
}
|
||
++k;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
//MSG_LOG("key:%s...", key);
|
||
memcpy(key + strlen(key), MAGIC_KEY, sizeof(MAGIC_KEY));
|
||
//MSG_LOG("megerkey:%s...", key);
|
||
|
||
//求哈希1
|
||
SHA1 sha;
|
||
unsigned int message_digest[5];
|
||
sha.Reset();
|
||
sha << key;
|
||
sha.Result(message_digest);
|
||
for (int i = 0; i < 5; i++) {
|
||
message_digest[i] = htonl(message_digest[i]);
|
||
}
|
||
|
||
memset(key, 0, 512);
|
||
base64_encode(key, reinterpret_cast<const char*>(message_digest), 20);
|
||
char http_res[512] = "";
|
||
sprintf(http_res, WEB_SOCKET_HANDS_RE, key);
|
||
PostUserServerData(pSession, http_res, strlen(http_res), false, false);
|
||
//MSG_LOG("res:%s...",http_res);//fkYTdNEVkParesYkrM4S
|
||
pSession->webSocketShakeHand = true;
|
||
|
||
char * pIp = inet_ntoa(pSession->SockAddr.sin_addr);
|
||
OutputMsg( rmTip, "[%s]握手完毕,nVerifyIdx=%ld",pIp, pSession->nVerifyIdx);
|
||
|
||
}
|
||
|
||
VOID CRunDataProcesser::AddRecvBuf(PRUNGATEUSERSESSION pSession,unsigned long long nVerify, char *pBuffer, int BufferSize)
|
||
{
|
||
PCLIENTRECVBUF pRecvBuf;
|
||
char *pData;
|
||
|
||
if ( pSession->nSocket == INVALID_SOCKET || pSession->boMarkToClose || pSession->boRemoteClosed || !nVerify || pSession->nVerifyIdx != nVerify )
|
||
return;
|
||
|
||
//--pSession->boSendAvaliable = true;
|
||
char * pIp = inet_ntoa(pSession->SockAddr.sin_addr);
|
||
|
||
// 未进行websocket握手,则先握手
|
||
if (pSession->webSocketShakeHand)
|
||
{
|
||
#ifdef _DEBUG_GATEMSG
|
||
OutputMsg( rmNormal, "");
|
||
OutputMsg( rmTip, "[%s]Idx=%ld: 接收socket数据, 长度为%d, session状态为%d",
|
||
pIp, pSession->nVerifyIdx, BufferSize, pSession->nSessionSatus);
|
||
#endif
|
||
pRecvBuf = (PCLIENTRECVBUF)malloc( sizeof(*pRecvBuf) + BufferSize + 1 );
|
||
pRecvBuf->pSession = pSession;
|
||
pRecvBuf->nVerify = nVerify;
|
||
pRecvBuf->nBufferSize = BufferSize;
|
||
pData = (char*)(pRecvBuf + 1);
|
||
|
||
memcpy( pData, pBuffer, BufferSize );
|
||
pData[BufferSize] = 0;
|
||
|
||
EnterCriticalSection( &m_RecvQueueLock );
|
||
m_pRecvAppendList->add( pRecvBuf );
|
||
LeaveCriticalSection( &m_RecvQueueLock );
|
||
} else {
|
||
OutputMsg( rmTip, "[%s]进行握手, 长度为%d, session状态为%d, nVerifyIdx=%ld",
|
||
pIp, BufferSize, pSession->nSessionSatus, pSession->nVerifyIdx);
|
||
//OutputMsg( rmTip, "握手数据:\n%s", pBuffer);
|
||
ShakeHandsHandle(pSession, pBuffer, BufferSize);
|
||
SendOpenSession(pSession);//发送到LogicServer新增连接
|
||
}
|
||
|
||
|
||
}
|