改为V5.9.6

This commit is contained in:
NH
2025-04-18 13:39:34 +08:00
parent 40504ab11f
commit abf2a90c56
60 changed files with 4248 additions and 2084 deletions

View File

@@ -692,9 +692,8 @@ public:
{
if(pSession->Reset())
{
#ifndef USE_EXTERNAL_GC
ReleaseGCSession();
#endif
if(!m_lsFreeSession.TryPut(pSession))
m_lsGCSession.PushBack(pSession);
}
@@ -717,12 +716,13 @@ public:
ENSURE(m_lsGCSession.IsEmpty());
}
private:
void ReleaseGCSession(BOOL bForce = FALSE)
{
::ReleaseGCObj(m_lsGCSession, m_dwSessionLockTime, bForce);
}
virtual BOOL OnReadyRead(const TDispContext* pContext, PVOID pv, UINT events) override
virtual BOOL OnReadyRead(PVOID pv, UINT events) override
{
if(events & _EPOLL_ALL_ERROR_EVENTS)

View File

@@ -1319,11 +1319,6 @@ HPSOCKET_API BOOL __HP_CALL HP_TcpAgent_SendSmallFile(HP_Agent pAgent, HP_CONNID
/**********************************************************************************/
/***************************** TCP Agent 属性访问方法 *****************************/
HPSOCKET_API void __HP_CALL HP_TcpAgent_SetSyncConnectTimeout(HP_TcpAgent pAgent, DWORD dwSyncConnectTimeout)
{
C_HP_Object::ToSecond<ITcpAgent>(pAgent)->SetSyncConnectTimeout(dwSyncConnectTimeout);
}
HPSOCKET_API void __HP_CALL HP_TcpAgent_SetSocketBufferSize(HP_TcpAgent pAgent, DWORD dwSocketBufferSize)
{
C_HP_Object::ToSecond<ITcpAgent>(pAgent)->SetSocketBufferSize(dwSocketBufferSize);
@@ -1344,11 +1339,6 @@ HPSOCKET_API void __HP_CALL HP_TcpAgent_SetNoDelay(HP_TcpAgent pAgent, BOOL bNoD
C_HP_Object::ToSecond<ITcpAgent>(pAgent)->SetNoDelay(bNoDelay);
}
HPSOCKET_API DWORD __HP_CALL HP_TcpAgent_GetSyncConnectTimeout(HP_TcpAgent pAgent)
{
return C_HP_Object::ToSecond<ITcpAgent>(pAgent)->GetSyncConnectTimeout();
}
HPSOCKET_API DWORD __HP_CALL HP_TcpAgent_GetSocketBufferSize(HP_TcpAgent pAgent)
{
return C_HP_Object::ToSecond<ITcpAgent>(pAgent)->GetSocketBufferSize();
@@ -1526,11 +1516,6 @@ HPSOCKET_API BOOL __HP_CALL HP_TcpClient_SendSmallFile(HP_Client pClient, LPCTST
/**********************************************************************************/
/***************************** TCP Client 属性访问方法 *****************************/
HPSOCKET_API void __HP_CALL HP_TcpClient_SetSyncConnectTimeout(HP_TcpClient pClient, DWORD dwSyncConnectTimeout)
{
C_HP_Object::ToSecond<ITcpClient>(pClient)->SetSyncConnectTimeout(dwSyncConnectTimeout);
}
HPSOCKET_API void __HP_CALL HP_TcpClient_SetSocketBufferSize(HP_TcpClient pClient, DWORD dwSocketBufferSize)
{
C_HP_Object::ToSecond<ITcpClient>(pClient)->SetSocketBufferSize(dwSocketBufferSize);
@@ -1551,11 +1536,6 @@ HPSOCKET_API void __HP_CALL HP_TcpClient_SetNoDelay(HP_TcpClient pClient, BOOL b
C_HP_Object::ToSecond<ITcpClient>(pClient)->SetNoDelay(bNoDelay);
}
HPSOCKET_API DWORD __HP_CALL HP_TcpClient_GetSyncConnectTimeout(HP_TcpClient pClient)
{
return C_HP_Object::ToSecond<ITcpClient>(pClient)->GetSyncConnectTimeout();
}
HPSOCKET_API DWORD __HP_CALL HP_TcpClient_GetSocketBufferSize(HP_TcpClient pClient)
{
return C_HP_Object::ToSecond<ITcpClient>(pClient)->GetSocketBufferSize();

View File

@@ -66,7 +66,7 @@ void DestroySocketTaskObj(LPTSocketTask pTask)
}
}
volatile UINT CHPThreadPool::sm_uiNum = MAXUINT;
volatile UINT CHPThreadPool::sm_uiNum = 0;
LPCTSTR CHPThreadPool::POOLED_THREAD_PREFIX = _T("hp-pool-");
BOOL CHPThreadPool::Start(DWORD dwThreadCount, DWORD dwMaxQueueSize, EnRejectedPolicy enRejectedPolicy, DWORD dwStackSize)
@@ -476,7 +476,7 @@ BOOL CHPThreadPool::CheckStoping()
void CHPThreadPool::Reset(BOOL bSetWaitEvent)
{
m_uiSeq = MAXUINT;
m_uiSeq = 0;
m_dwStackSize = 0;
m_dwTaskCount = 0;
m_dwThreadCount = 0;

View File

@@ -197,15 +197,6 @@ template<class T, USHORT default_port> EnHandleResult CHttpAgentT<T, default_por
return result;
}
template<class T, USHORT default_port> void CHttpAgentT<T, default_port>::ReleaseGCSocketObj(BOOL bForce)
{
__super::ReleaseGCSocketObj(bForce);
#ifdef USE_EXTERNAL_GC
m_objPool.ReleaseGCHttpObj(bForce);
#endif
}
template<class T, USHORT default_port> BOOL CHttpAgentT<T, default_port>::IsUpgrade(CONNID dwConnID)
{
THttpObj* pHttpObj = FindHttpObj(dwConnID);

View File

@@ -134,8 +134,6 @@ private:
virtual EnHandleResult DoFireClose(TAgentSocketObj* pSocketObj, EnSocketOperation enOperation, int iErrorCode);
virtual EnHandleResult DoFireShutdown();
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE);
EnHandleResult DoFireSuperReceive(TAgentSocketObj* pSocketObj, const BYTE* pData, int iLength)
{return __super::DoFireReceive(pSocketObj, pData, iLength);}

View File

@@ -87,7 +87,7 @@ typedef llhttp_settings_t http_parser_settings;
#define MIN_HTTP_RELEASE_CHECK_INTERVAL ((DWORD)1000)
#define MIN_HTTP_RELEASE_DELAY 100
#define MAX_HTTP_RELEASE_DELAY (60 * 1000)
#define DEFAULT_HTTP_RELEASE_DELAY (5 * 1000)
#define DEFAULT_HTTP_RELEASE_DELAY (3 * 1000)
#define DEFAULT_HTTP_VERSION HV_1_1
#define DEFAULT_HTTP_SYNC_CONNECT_TIMEOUT 5000
@@ -1302,9 +1302,8 @@ public:
{
pHttpObj->SetFree();
#ifndef USE_EXTERNAL_GC
ReleaseGCHttpObj();
#endif
if(!m_lsFreeHttpObj.TryPut(pHttpObj))
m_lsGCHttpObj.PushBack(pHttpObj);
}
@@ -1322,6 +1321,7 @@ public:
VERIFY(m_lsGCHttpObj.IsEmpty());
}
private:
void ReleaseGCHttpObj(BOOL bForce = FALSE)
{
::ReleaseGCObj(m_lsGCHttpObj, m_dwHttpObjLockTime, bForce);

View File

@@ -293,15 +293,6 @@ template<class T, USHORT default_port> EnHandleResult CHttpServerT<T, default_po
return result;
}
template<class T, USHORT default_port> void CHttpServerT<T, default_port>::ReleaseGCSocketObj(BOOL bForce)
{
__super::ReleaseGCSocketObj(bForce);
#ifdef USE_EXTERNAL_GC
m_objPool.ReleaseGCHttpObj(bForce);
#endif
}
template<class T, USHORT default_port> void CHttpServerT<T, default_port>::WaitForCleanerThreadEnd()
{
if(m_thCleaner.IsRunning())

View File

@@ -128,8 +128,6 @@ private:
virtual EnHandleResult DoFireClose(TSocketObj* pSocketObj, EnSocketOperation enOperation, int iErrorCode);
virtual EnHandleResult DoFireShutdown();
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE);
EnHandleResult DoFireSuperReceive(TSocketObj* pSocketObj, const BYTE* pData, int iLength)
{return __super::DoFireReceive(pSocketObj, pData, iLength);}

View File

@@ -62,8 +62,6 @@
#define DEFAULT_CLIENT_FREE_BUFFER_POOL_SIZE 60
/* Client 默认内存块缓存池回收阀值 */
#define DEFAULT_CLIENT_FREE_BUFFER_POOL_HOLD 60
/* Client/Agent 默认同步连接超时时间 */
#define DEFAULT_SYNC_CONNECT_TIMEOUT 10000
/* IPv4 默认绑定地址 */
#define DEFAULT_IPV4_BIND_ADDRESS _T("0.0.0.0")
/* IPv6 默认绑定地址 */
@@ -107,9 +105,6 @@
/* 默认压缩/解压数据缓冲器长度 */
#define DEFAULT_COMPRESS_BUFFER_SIZE (16 * 1024)
/* 垃圾回收检查间隔(毫秒) */
#define GC_CHECK_INTERVAL (15 * 1000)
#define HOST_SEPARATOR_CHAR '^'
#define PORT_SEPARATOR_CHAR ':'
#define IPV6_ADDR_BEGIN_CHAR '['

View File

@@ -66,15 +66,6 @@ void CSSLAgent::OnWorkerThreadEnd(THR_ID dwThreadID)
__super::OnWorkerThreadEnd(dwThreadID);
}
void CSSLAgent::ReleaseGCSocketObj(BOOL bForce)
{
__super::ReleaseGCSocketObj(bForce);
#ifdef USE_EXTERNAL_GC
m_sslPool.ReleaseGCSession(bForce);
#endif
}
BOOL CSSLAgent::SendPackets(CONNID dwConnID, const WSABUF pBuffers[], int iCount)
{
ASSERT(pBuffers && iCount > 0);

View File

@@ -70,8 +70,6 @@ protected:
virtual void OnWorkerThreadEnd(THR_ID dwThreadID);
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE);
protected:
virtual BOOL StartSSLHandShake(TAgentSocketObj* pSocketObj);

View File

@@ -1168,9 +1168,8 @@ void CSSLSessionPool::PutFreeSession(CSSLSession* pSession)
{
if(pSession->Reset())
{
#ifndef USE_EXTERNAL_GC
ReleaseGCSession();
#endif
if(!m_lsFreeSession.TryPut(pSession))
m_lsGCSession.PushBack(pSession);
}

View File

@@ -336,6 +336,7 @@ public:
void Prepare ();
void Clear ();
private:
void ReleaseGCSession (BOOL bForce = FALSE);
public:

View File

@@ -66,15 +66,6 @@ void CSSLServer::OnWorkerThreadEnd(THR_ID dwThreadID)
__super::OnWorkerThreadEnd(dwThreadID);
}
void CSSLServer::ReleaseGCSocketObj(BOOL bForce)
{
__super::ReleaseGCSocketObj(bForce);
#ifdef USE_EXTERNAL_GC
m_sslPool.ReleaseGCSession(bForce);
#endif
}
BOOL CSSLServer::SendPackets(CONNID dwConnID, const WSABUF pBuffers[], int iCount)
{
ASSERT(pBuffers && iCount > 0);

View File

@@ -78,8 +78,6 @@ protected:
virtual void OnWorkerThreadEnd(THR_ID dwThreadID);
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE);
protected:
virtual BOOL StartSSLHandShake(TSocketObj* pSocketObj);

View File

@@ -53,7 +53,7 @@ BOOL SetCurrentWorkerThreadName()
BOOL SetWorkerThreadDefaultName(THR_ID tid)
{
static volatile UINT _s_uiSeq = MAXUINT;
static volatile UINT _s_uiSeq = 0;
return ::SetSequenceThreadName(tid, DEFAULT_WORKER_THREAD_PREFIX, _s_uiSeq);
}
@@ -77,7 +77,6 @@ LPCTSTR GetSocketErrorDesc(EnSocketError enCode)
case SE_NETWORK: return _T("Network Error");
case SE_DATA_PROC: return _T("Process Data Error");
case SE_DATA_SEND: return _T("Send Data Fail");
case SE_GC_START: return _T("Start GC Fail");
case SE_SSL_ENV_NOT_READY: return _T("SSL environment not ready");
@@ -354,10 +353,10 @@ BOOL FreeHostIPAddresses(LPTIPAddr* lppIPAddr)
BOOL sockaddr_IN_2_A(const HP_SOCKADDR& addr, ADDRESS_FAMILY& usFamily, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort)
{
BOOL isOK = FALSE;
BOOL isOK = FALSE;
usFamily = addr.family;
usPort = addr.Port();
usFamily = addr.family;
usPort = addr.Port();
if(::InetNtop(addr.family, addr.SinAddr(), lpszAddress, iAddressLen))
{
@@ -447,36 +446,6 @@ BOOL SetMultiCastSocketOptions(SOCKET sock, const HP_SOCKADDR& bindAddr, const H
return TRUE;
}
int WaitForSocketWrite(SOCKET sock, DWORD dwTimeout)
{
timeval tv = {(__time_t)(dwTimeout / 1000), (__suseconds_t)((dwTimeout % 1000) * 1000)};
fd_set wfds, efds;
FD_ZERO(&wfds);
FD_ZERO(&efds);
FD_SET(sock, &wfds);
FD_SET(sock, &efds);
int rs = NO_EINTR_INT(select(sock + 1, nullptr, &wfds, &efds, &tv));
if(rs <= 0) return ((rs == 0) ? ERROR_TIMEOUT : ENSURE_ERROR(ERROR_CANT_WAIT));
if(FD_ISSET(sock, &efds))
{
rs = SSO_GetError(sock);
return ((rs != NO_ERROR && rs != SOCKET_ERROR) ? rs : ENSURE_ERROR(ERROR_CANT_WAIT));
}
VERIFY(FD_ISSET(sock, &wfds));
rs = SSO_GetError(sock);
if(!IS_NO_ERROR(rs))
return ((rs != SOCKET_ERROR) ? rs : ENSURE_ERROR(ERROR_CANT_WAIT));
return NO_ERROR;
}
ULONGLONG NToH64(ULONGLONG value)
{
return (((ULONGLONG)ntohl((UINT)((value << 32) >> 32))) << 32) | ntohl((UINT)(value >> 32));
@@ -642,7 +611,7 @@ int SSO_ReuseAddress(SOCKET sock, EnReuseAddressPolicy opt)
BOOL bReusePortSupported =
#if defined(__linux) || defined(__linux__)
::IsKernelVersionAbove(2, 6, 32);
::IsKernelVersionAbove(3, 9, 0);
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__) || defined(__MACH__)
TRUE;
#else

View File

@@ -303,14 +303,11 @@ public:
DECLARE_NO_COPY_CLASS(TNodeBufferObj)
};
typedef CCASQueue<TNodeBufferObj> CNodeRecvQueue;
typedef TItemPtrT<TNodeBufferObj> TNodeBufferObjPtr;
typedef CNodePoolT<TNodeBufferObj> CNodeBufferObjPool;
typedef CCASQueue<TNodeBufferObj> CNodeRecvQueue;
typedef TItemListExT<TNodeBufferObj, volatile int> TNodeBufferObjList;
typedef unique_ptr<CCriSec[]> CNodeCriSecs;
typedef unique_ptr<TNodeBufferObjList[]> TNodeBufferObjLists;
/* Server 组件和 Agent 组件内部使用的事件处理结果常量 */
// 连接已关闭
@@ -323,7 +320,7 @@ enum EnDispCmdType
DISP_CMD_RECEIVE = 0x02, // 接收数据
DISP_CMD_UNPAUSE = 0x03, // 恢复接收数据
DISP_CMD_DISCONNECT = 0x04, // 断开连接
DISP_CMD_TIMEOUT = 0x05, // 保活超时
DISP_CMD_TIMEOUT = 0x05 // 保活超时
};
/* 关闭连接标识 */
@@ -334,20 +331,14 @@ enum EnSocketCloseFlag
SCF_ERROR = 2 // 触发 异常关闭 OnClose 事件
};
/* 监听 Socket 数组智能指针 */
typedef unique_ptr<SOCKET[]> ListenSocketsPtr;
/* 数据缓冲节点 */
typedef TItem TBufferObj;
typedef TItem TBufferObj;
/* 数据缓冲节点智能指针 */
typedef TItemPtr TBufferObjPtr;
typedef TItemPtr TBufferObjPtr;
/* 数据缓冲区对象池 */
typedef CItemPool CBufferObjPool;
typedef CItemPool CBufferObjPool;
/* 数据缓冲区链表模板 */
typedef TItemListExV TBufferObjList;
/* 接收缓冲区数组智能指针 */
typedef unique_ptr<CBufferPtr[]> CReceiveBuffersPtr;
typedef TItemListExV TBufferObjList;
/* 线程 ID - 接收缓冲区哈希表 */
typedef unordered_map<THR_ID, CBufferPtr*> TReceiveBufferMap;
@@ -359,10 +350,7 @@ typedef TReceiveBufferMap::const_iterator TReceiveBufferMapCI;
/* Socket 缓冲区基础结构 */
struct TSocketObjBase : public CSafeCounter
{
CPrivateHeap& heap;
CReentrantCriSec csSend;
TBufferObjList sndBuff;
CPrivateHeap& heap;
CONNID connID;
HP_SOCKADDR remoteAddr;
@@ -381,7 +369,7 @@ struct TSocketObjBase : public CSafeCounter
volatile BOOL connected;
volatile BOOL paused;
TSocketObjBase(CPrivateHeap& hp, CBufferObjPool& bfPool) : heap(hp), sndBuff(bfPool) {}
TSocketObjBase(CPrivateHeap& hp) : heap(hp) {}
static BOOL IsExist(TSocketObjBase* pSocketObj)
{return pSocketObj != nullptr;}
@@ -393,41 +381,13 @@ struct TSocketObjBase : public CSafeCounter
{ASSERT(IsExist(pSocketObj)); pSocketObj->valid = FALSE;}
static void Release(TSocketObjBase* pSocketObj)
{
ASSERT(IsExist(pSocketObj));
pSocketObj->freeTime = ::TimeGetTime();
pSocketObj->sndBuff.Release();
}
static BOOL InvalidSocketObj(TSocketObjBase* pSocketObj)
{
BOOL bDone = FALSE;
if(TSocketObjBase::IsValid(pSocketObj))
{
pSocketObj->SetConnected(FALSE);
CReentrantCriSecLock locallock(pSocketObj->csSend);
if(TSocketObjBase::IsValid(pSocketObj))
{
TSocketObjBase::Invalid(pSocketObj);
bDone = TRUE;
}
}
return bDone;
}
{ASSERT(IsExist(pSocketObj)); pSocketObj->freeTime = ::TimeGetTime();}
DWORD GetConnTime () const {return connTime;}
DWORD GetFreeTime () const {return freeTime;}
DWORD GetActiveTime () const {return activeTime;}
BOOL IsPaused () const {return paused;}
int Pending () const {return sndBuff.Length();}
BOOL IsPending () const {return Pending() > 0;}
BOOL HasConnected() {return connected == TRUE;}
BOOL IsConnecting() {return connected == CST_CONNECTING;}
void SetConnected(BOOL bConnected = TRUE) {connected = bConnected;}
@@ -451,7 +411,11 @@ struct TSocketObj : public TSocketObjBase
{
using __super = TSocketObjBase;
SOCKET socket;
CReentrantCriSec csIo;
CReentrantCriSec csSend;
SOCKET socket;
TBufferObjList sndBuff;
static TSocketObj* Construct(CPrivateHeap& hp, CBufferObjPool& bfPool)
{
@@ -471,11 +435,41 @@ struct TSocketObj : public TSocketObjBase
}
TSocketObj(CPrivateHeap& hp, CBufferObjPool& bfPool)
: __super(hp, bfPool)
: __super(hp), sndBuff(bfPool)
{
}
static void Release(TSocketObj* pSocketObj)
{
__super::Release(pSocketObj);
pSocketObj->sndBuff.Release();
}
int Pending() {return sndBuff.Length();}
BOOL IsPending() {return Pending() > 0;}
static BOOL InvalidSocketObj(TSocketObj* pSocketObj)
{
BOOL bDone = FALSE;
if(TSocketObjBase::IsValid(pSocketObj))
{
pSocketObj->SetConnected(FALSE);
CReentrantCriSecLock locallock(pSocketObj->csIo);
CReentrantCriSecLock locallock2(pSocketObj->csSend);
if(TSocketObjBase::IsValid(pSocketObj))
{
TSocketObjBase::Invalid(pSocketObj);
bDone = TRUE;
}
}
return bDone;
}
void Reset(CONNID dwConnID, SOCKET soClient)
{
__super::Reset(dwConnID);
@@ -535,13 +529,22 @@ struct TAgentSocketObj : public TSocketObj
/* UDP 数据缓冲区结构 */
struct TUdpSocketObj : public TSocketObjBase
{
using __super = TSocketObjBase;
using __super = TSocketObjBase;
using CRecvQueue = CCASQueue<TItem>;
int index;
PVOID pHolder;
FD fdTimer;
PVOID pHolder;
FD fdTimer;
volatile DWORD detectFails;
CBufferObjPool& itPool;
CRWLock lcIo;
CRWLock lcSend;
CCriSec csSend;
TBufferObjList sndBuff;
CRecvQueue recvQueue;
volatile DWORD detectFails;
static TUdpSocketObj* Construct(CPrivateHeap& hp, CBufferObjPool& bfPool)
{
@@ -561,19 +564,67 @@ struct TUdpSocketObj : public TSocketObjBase
}
TUdpSocketObj(CPrivateHeap& hp, CBufferObjPool& bfPool)
: __super(hp, bfPool)
: __super(hp), sndBuff(bfPool), itPool(bfPool)
{
}
~TUdpSocketObj()
{
ClearRecvQueue();
}
static void Release(TUdpSocketObj* pSocketObj)
{
__super::Release(pSocketObj);
pSocketObj->ClearRecvQueue();
pSocketObj->sndBuff.Release();
}
int Pending() {return sndBuff.Length();}
BOOL IsPending() {return Pending() > 0;}
BOOL HasRecvData() {return !recvQueue.IsEmpty();}
static BOOL InvalidSocketObj(TUdpSocketObj* pSocketObj)
{
BOOL bDone = FALSE;
if(TSocketObjBase::IsValid(pSocketObj))
{
pSocketObj->SetConnected(FALSE);
CReentrantWriteLock locallock(pSocketObj->lcIo);
CReentrantWriteLock locallock2(pSocketObj->lcSend);
CCriSecLock locallock3(pSocketObj->csSend);
if(TSocketObjBase::IsValid(pSocketObj))
{
TSocketObjBase::Invalid(pSocketObj);
bDone = TRUE;
}
}
return bDone;
}
void Reset(CONNID dwConnID)
{
__super::Reset(dwConnID);
index = -1;
detectFails = 0;
fdTimer = INVALID_FD;
pHolder = nullptr;
fdTimer = INVALID_FD;
detectFails = 0;
}
void ClearRecvQueue()
{
TItem* pItem = nullptr;
while(recvQueue.PopFront(&pItem))
itPool.PutFreeItem(pItem);
VERIFY(recvQueue.IsEmpty());
}
};
@@ -696,8 +747,6 @@ BOOL GetSocketLocalAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen,
BOOL GetSocketRemoteAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort);
/* 设置组播选项 */
BOOL SetMultiCastSocketOptions(SOCKET sock, const HP_SOCKADDR& bindAddr, const HP_SOCKADDR& castAddr, int iMCTtl, BOOL bMCLoop);
/* 等待连接 */
int WaitForSocketWrite(SOCKET sock, DWORD dwTimeout);
/* 64 位网络字节序转主机字节序 */
ULONGLONG NToH64(ULONGLONG value);

View File

@@ -56,7 +56,6 @@ BOOL CTcpAgent::CheckParams()
{
if ((m_enSendPolicy >= SP_PACK && m_enSendPolicy <= SP_DIRECT) &&
(m_enOnSendSyncPolicy >= OSSP_NONE && m_enOnSendSyncPolicy <= OSSP_RECEIVE) &&
((int)m_dwSyncConnectTimeout > 0) &&
((int)m_dwMaxConnectionCount > 0 && m_dwMaxConnectionCount <= MAX_CONNECTION_COUNT) &&
((int)m_dwWorkerThreadCount > 0 && m_dwWorkerThreadCount <= MAX_WORKER_THREAD_COUNT) &&
((int)m_dwSocketBufferSize >= MIN_SOCKET_BUFFER_SIZE) &&
@@ -83,9 +82,6 @@ void CTcpAgent::PrepareStart()
m_bfObjPool.SetPoolHold(m_dwFreeBufferObjHold);
m_bfObjPool.Prepare();
m_rcBuffers = make_unique<CBufferPtr[]>(m_dwWorkerThreadCount);
for_each(m_rcBuffers.get(), m_rcBuffers.get() + m_dwWorkerThreadCount, [this](CBufferPtr& buff) {buff.Malloc(m_dwSocketBufferSize);});
}
BOOL CTcpAgent::CheckStarting()
@@ -155,27 +151,13 @@ BOOL CTcpAgent::ParseBindAddress(LPCTSTR lpszBindAddress)
BOOL CTcpAgent::CreateWorkerThreads()
{
DWORD dwWorkerThreadCount = m_dwWorkerThreadCount
#ifdef USE_EXTERNAL_GC
+ 1
#endif
;
if(!m_ioDispatcher.Start(this, DEFAULT_WORKER_MAX_EVENT_COUNT, dwWorkerThreadCount))
{
SetLastError(SE_WORKER_THREAD_CREATE, __FUNCTION__, ::WSAGetLastError());
if(!m_ioDispatcher.Start(this, DEFAULT_WORKER_MAX_EVENT_COUNT, m_dwWorkerThreadCount))
return FALSE;
}
#ifdef USE_EXTERNAL_GC
m_fdGCTimer = m_ioDispatcher.AddTimer(m_dwWorkerThreadCount, GC_CHECK_INTERVAL, this);
const CIODispatcher::CWorkerThread* pWorkerThread = m_ioDispatcher.GetWorkerThreads();
if(IS_INVALID_FD(m_fdGCTimer))
{
SetLastError(SE_GC_START, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
#endif
for(DWORD i = 0; i < m_dwWorkerThreadCount; i++)
m_rcBufferMap[pWorkerThread[i].GetThreadID()] = new CBufferPtr(m_dwSocketBufferSize);
return TRUE;
}
@@ -235,14 +217,6 @@ void CTcpAgent::ReleaseFreeSocket()
{
m_lsFreeSocket.Clear();
#ifdef USE_EXTERNAL_GC
if(IS_VALID_FD(m_fdGCTimer))
{
close(m_fdGCTimer);
m_fdGCTimer = INVALID_FD;
}
#endif
ReleaseGCSocketObj(TRUE);
VERIFY(m_lsGCSocket.IsEmpty());
}
@@ -253,7 +227,7 @@ void CTcpAgent::Reset()
m_phSocket.Reset();
m_soAddr.Reset();
m_rcBuffers = nullptr;
::ClearPtrMap(m_rcBufferMap);
m_enState = SS_STOPPED;
@@ -264,29 +238,34 @@ BOOL CTcpAgent::Connect(LPCTSTR lpszRemoteAddress, USHORT usPort, CONNID* pdwCon
{
ASSERT(lpszRemoteAddress && usPort != 0);
if(!HasStarted())
{
::SetLastError(ERROR_INVALID_STATE);
return FALSE;
}
DWORD result = NO_ERROR;
SOCKET soClient = INVALID_SOCKET;
if(!pdwConnID)
pdwConnID = CreateLocalObject(CONNID);
pdwConnID = CreateLocalObject(CONNID);
*pdwConnID = 0;
HP_SOCKADDR addr;
HP_SCOPE_HOST host(lpszRemoteAddress);
SOCKET soClient = INVALID_SOCKET;
DWORD result = CreateClientSocket(host.addr, usPort, lpszLocalAddress, usLocalPort, soClient, addr);
if(result == NO_ERROR)
if(!HasStarted())
result = ERROR_INVALID_STATE;
else
{
result = PrepareConnect(*pdwConnID, soClient);
HP_SCOPE_HOST host(lpszRemoteAddress);
result = CreateClientSocket(host.addr, usPort, lpszLocalAddress, usLocalPort, soClient, addr);
if(result == NO_ERROR)
result = ConnectToServer(*pdwConnID, host.name, soClient, addr, pExtra);
{
result = PrepareConnect(*pdwConnID, soClient);
if(result == NO_ERROR)
{
result = ConnectToServer(*pdwConnID, host.name, soClient, addr, pExtra);
soClient = INVALID_SOCKET;
}
}
}
if(result != NO_ERROR)
@@ -365,42 +344,44 @@ int CTcpAgent::PrepareConnect(CONNID& dwConnID, SOCKET soClient)
return NO_ERROR;
}
int CTcpAgent::ConnectToServer(CONNID dwConnID, LPCTSTR lpszRemoteHostName, SOCKET& soClient, const HP_SOCKADDR& addr, PVOID pExtra)
int CTcpAgent::ConnectToServer(CONNID dwConnID, LPCTSTR lpszRemoteHostName, SOCKET soClient, const HP_SOCKADDR& addr, PVOID pExtra)
{
TAgentSocketObj* pSocketObj = GetFreeSocketObj(dwConnID, soClient);
CReentrantCriSecLock locallock(pSocketObj->csIo);
AddClientSocketObj(dwConnID, pSocketObj, addr, lpszRemoteHostName, pExtra);
int result = HAS_ERROR;
VERIFY(::fcntl_SETFL(pSocketObj->socket, O_NOATIME | O_NONBLOCK | O_CLOEXEC));
int rc = ::connect(pSocketObj->socket, addr.Addr(), addr.AddrSize());
if(IS_NO_ERROR(rc) || IS_IO_PENDING_ERROR())
if(m_bAsyncConnect)
{
if(m_bAsyncConnect)
::fcntl_SETFL(pSocketObj->socket, O_NOATIME | O_NONBLOCK | O_CLOEXEC);
int rc = ::connect(pSocketObj->socket, addr.Addr(), addr.AddrSize());
if(IS_NO_ERROR(rc) || IS_IO_PENDING_ERROR())
{
if(m_ioDispatcher.AddFD(pSocketObj->socket, EPOLLOUT, pSocketObj))
if(m_ioDispatcher.AddFD(pSocketObj->socket, EPOLLOUT | EPOLLONESHOT, pSocketObj))
result = NO_ERROR;
}
else
}
else
{
if(::connect(pSocketObj->socket, addr.Addr(), addr.AddrSize()) != SOCKET_ERROR)
{
if(IS_HAS_ERROR(result))
result = ::WaitForSocketWrite(pSocketObj->socket, m_dwSyncConnectTimeout);
::fcntl_SETFL(pSocketObj->socket, O_NOATIME | O_NONBLOCK | O_CLOEXEC);
if(IS_NO_ERROR(result))
pSocketObj->SetConnected();
if(TRIGGER(FireConnect(pSocketObj)) == HR_ERROR)
result = ENSURE_ERROR_CANCELLED;
else
{
pSocketObj->SetConnected();
UINT evts = (pSocketObj->IsPending() ? EPOLLOUT : 0) | (pSocketObj->IsPaused() ? 0 : EPOLLIN);
if(TRIGGER(FireConnect(pSocketObj)) == HR_ERROR)
result = ENSURE_ERROR_CANCELLED;
else
{
UINT evts = (pSocketObj->IsPending() ? EPOLLOUT : 0) | (pSocketObj->IsPaused() ? 0 : EPOLLIN);
if(!m_ioDispatcher.AddFD(pSocketObj->socket, evts | EPOLLRDHUP, pSocketObj))
result = HAS_ERROR;
}
if(m_ioDispatcher.AddFD(pSocketObj->socket, evts | EPOLLRDHUP | EPOLLONESHOT, pSocketObj))
result = NO_ERROR;
}
}
}
@@ -408,10 +389,7 @@ int CTcpAgent::ConnectToServer(CONNID dwConnID, LPCTSTR lpszRemoteHostName, SOCK
if(result == HAS_ERROR)
result = ::WSAGetLastError();
if(result != NO_ERROR)
{
AddFreeSocketObj(pSocketObj, SCF_NONE);
soClient = INVALID_SOCKET;
}
return result;
}
@@ -458,9 +436,7 @@ void CTcpAgent::AddFreeSocketObj(TAgentSocketObj* pSocketObj, EnSocketCloseFlag
m_bfActiveSockets.Remove(pSocketObj->connID);
TAgentSocketObj::Release(pSocketObj);
#ifndef USE_EXTERNAL_GC
ReleaseGCSocketObj();
#endif
if(!m_lsFreeSocket.TryPut(pSocketObj))
m_lsGCSocket.PushBack(pSocketObj);
@@ -810,7 +786,7 @@ BOOL CTcpAgent::Disconnect(CONNID dwConnID, BOOL bForce)
return FALSE;
}
return m_ioDispatcher.SendCommandByFD(pSocketObj->socket, DISP_CMD_DISCONNECT, dwConnID, bForce);
return m_ioDispatcher.SendCommand(DISP_CMD_DISCONNECT, dwConnID, bForce);
}
BOOL CTcpAgent::DisconnectLongConnections(DWORD dwPeriod, BOOL bForce)
@@ -885,21 +861,13 @@ BOOL CTcpAgent::PauseReceive(CONNID dwConnID, BOOL bPause)
pSocketObj->paused = bPause;
if(!bPause)
return m_ioDispatcher.SendCommandByFD(pSocketObj->socket, DISP_CMD_UNPAUSE, pSocketObj->connID);
return m_ioDispatcher.SendCommand(DISP_CMD_UNPAUSE, pSocketObj->connID);
return TRUE;
}
BOOL CTcpAgent::OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CTcpAgent::OnBeforeProcessIo(PVOID pv, UINT events)
{
if(pv == this)
{
ReleaseGCSocketObj(FALSE);
::ReadTimer(m_fdGCTimer);
return FALSE;
}
TAgentSocketObj* pSocketObj = (TAgentSocketObj*)(pv);
if(!TAgentSocketObj::IsValid(pSocketObj))
@@ -909,25 +877,30 @@ BOOL CTcpAgent::OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT e
pSocketObj->SetConnected(FALSE);
pSocketObj->Increment();
pSocketObj->csIo.lock();
if(!TAgentSocketObj::IsValid(pSocketObj))
{
pSocketObj->csIo.unlock();
pSocketObj->Decrement();
return FALSE;
}
if(pSocketObj->IsConnecting())
{
HandleConnect(pContext, pSocketObj, events);
HandleConnect(pSocketObj, events);
pSocketObj->csIo.unlock();
pSocketObj->Decrement();
return FALSE;
}
return TRUE;
}
VOID CTcpAgent::OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT events, BOOL rs)
VOID CTcpAgent::OnAfterProcessIo(PVOID pv, UINT events, BOOL rs)
{
TAgentSocketObj* pSocketObj = (TAgentSocketObj*)(pv);
@@ -936,37 +909,38 @@ VOID CTcpAgent::OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT ev
ASSERT(rs && !(events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)));
UINT evts = (pSocketObj->IsPending() ? EPOLLOUT : 0) | (pSocketObj->IsPaused() ? 0 : EPOLLIN);
m_ioDispatcher.ModFD(pSocketObj->socket, evts | EPOLLRDHUP, pSocketObj);
m_ioDispatcher.ModFD(pSocketObj->socket, evts | EPOLLRDHUP | EPOLLONESHOT, pSocketObj);
}
pSocketObj->csIo.unlock();
pSocketObj->Decrement();
}
VOID CTcpAgent::OnCommand(const TDispContext* pContext, TDispCommand* pCmd)
VOID CTcpAgent::OnCommand(TDispCommand* pCmd)
{
switch(pCmd->type)
{
case DISP_CMD_SEND:
HandleCmdSend(pContext, (CONNID)(pCmd->wParam));
HandleCmdSend((CONNID)(pCmd->wParam));
break;
case DISP_CMD_UNPAUSE:
HandleCmdUnpause(pContext, (CONNID)(pCmd->wParam));
HandleCmdUnpause((CONNID)(pCmd->wParam));
break;
case DISP_CMD_DISCONNECT:
HandleCmdDisconnect(pContext, (CONNID)(pCmd->wParam), (BOOL)pCmd->lParam);
HandleCmdDisconnect((CONNID)(pCmd->wParam), (BOOL)pCmd->lParam);
break;
}
}
VOID CTcpAgent::HandleCmdSend(const TDispContext* pContext, CONNID dwConnID)
VOID CTcpAgent::HandleCmdSend(CONNID dwConnID)
{
TAgentSocketObj* pSocketObj = FindSocketObj(dwConnID);
if(TAgentSocketObj::IsValid(pSocketObj) && pSocketObj->IsPending())
m_ioDispatcher.ProcessIo(pContext, pSocketObj, EPOLLOUT);
m_ioDispatcher.ProcessIo(pSocketObj, EPOLLOUT);
}
VOID CTcpAgent::HandleCmdUnpause(const TDispContext* pContext, CONNID dwConnID)
VOID CTcpAgent::HandleCmdUnpause(CONNID dwConnID)
{
TAgentSocketObj* pSocketObj = FindSocketObj(dwConnID);
@@ -974,37 +948,37 @@ VOID CTcpAgent::HandleCmdUnpause(const TDispContext* pContext, CONNID dwConnID)
return;
if(BeforeUnpause(pSocketObj))
m_ioDispatcher.ProcessIo(pContext, pSocketObj, EPOLLIN);
m_ioDispatcher.ProcessIo(pSocketObj, EPOLLIN);
else
AddFreeSocketObj(pSocketObj, SCF_ERROR, SO_RECEIVE, ENSURE_ERROR_CANCELLED);
}
VOID CTcpAgent::HandleCmdDisconnect(const TDispContext* pContext, CONNID dwConnID, BOOL bForce)
VOID CTcpAgent::HandleCmdDisconnect(CONNID dwConnID, BOOL bForce)
{
TAgentSocketObj* pSocketObj = FindSocketObj(dwConnID);
if(TAgentSocketObj::IsValid(pSocketObj))
m_ioDispatcher.ProcessIo(pContext, pSocketObj, EPOLLHUP);
m_ioDispatcher.ProcessIo(pSocketObj, EPOLLHUP);
}
BOOL CTcpAgent::OnReadyRead(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CTcpAgent::OnReadyRead(PVOID pv, UINT events)
{
return HandleReceive(pContext, (TAgentSocketObj*)pv, RETRIVE_EVENT_FLAG_H(events));
return HandleReceive((TAgentSocketObj*)pv, RETRIVE_EVENT_FLAG_H(events));
}
BOOL CTcpAgent::OnReadyWrite(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CTcpAgent::OnReadyWrite(PVOID pv, UINT events)
{
return HandleSend(pContext, (TAgentSocketObj*)pv, RETRIVE_EVENT_FLAG_H(events));
return HandleSend((TAgentSocketObj*)pv, RETRIVE_EVENT_FLAG_H(events));
}
BOOL CTcpAgent::OnHungUp(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CTcpAgent::OnHungUp(PVOID pv, UINT events)
{
return HandleClose(pContext, (TAgentSocketObj*)pv, SCF_CLOSE, events);
return HandleClose((TAgentSocketObj*)pv, SCF_CLOSE, events);
}
BOOL CTcpAgent::OnError(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CTcpAgent::OnError(PVOID pv, UINT events)
{
return HandleClose(pContext, (TAgentSocketObj*)pv, SCF_ERROR, events);
return HandleClose((TAgentSocketObj*)pv, SCF_ERROR, events);
}
VOID CTcpAgent::OnDispatchThreadStart(THR_ID tid)
@@ -1017,7 +991,7 @@ VOID CTcpAgent::OnDispatchThreadEnd(THR_ID tid)
OnWorkerThreadEnd(tid);
}
BOOL CTcpAgent::HandleClose(const TDispContext* pContext, TAgentSocketObj* pSocketObj, EnSocketCloseFlag enFlag, UINT events)
BOOL CTcpAgent::HandleClose(TAgentSocketObj* pSocketObj, EnSocketCloseFlag enFlag, UINT events)
{
EnSocketOperation enOperation = SO_CLOSE;
@@ -1038,7 +1012,7 @@ BOOL CTcpAgent::HandleClose(const TDispContext* pContext, TAgentSocketObj* pSock
return TRUE;
}
BOOL CTcpAgent::HandleConnect(const TDispContext* pContext, TAgentSocketObj* pSocketObj, UINT events)
BOOL CTcpAgent::HandleConnect(TAgentSocketObj* pSocketObj, UINT events)
{
int code = ::SSO_GetError(pSocketObj->socket);
@@ -1064,7 +1038,7 @@ BOOL CTcpAgent::HandleConnect(const TDispContext* pContext, TAgentSocketObj* pSo
UINT evts = (pSocketObj->IsPending() ? EPOLLOUT : 0) | (pSocketObj->IsPaused() ? 0 : EPOLLIN);
if(!m_ioDispatcher.ModFD(pSocketObj->socket, evts | EPOLLRDHUP, pSocketObj))
if(!m_ioDispatcher.ModFD(pSocketObj->socket, evts | EPOLLRDHUP | EPOLLONESHOT, pSocketObj))
{
AddFreeSocketObj(pSocketObj, SCF_ERROR, SO_CONNECT, ::WSAGetLastError());
return FALSE;
@@ -1073,13 +1047,13 @@ BOOL CTcpAgent::HandleConnect(const TDispContext* pContext, TAgentSocketObj* pSo
return TRUE;
}
BOOL CTcpAgent::HandleReceive(const TDispContext* pContext, TAgentSocketObj* pSocketObj, int flag)
BOOL CTcpAgent::HandleReceive(TAgentSocketObj* pSocketObj, int flag)
{
ASSERT(TAgentSocketObj::IsValid(pSocketObj));
if(m_bMarkSilence) pSocketObj->activeTime = ::TimeGetTime();
CBufferPtr& buffer = m_rcBuffers[pContext->GetIndex()];
CBufferPtr& buffer = *(m_rcBufferMap[SELF_THREAD_ID]);
int reads = flag ? -1 : MAX_CONTINUE_READS;
@@ -1122,7 +1096,7 @@ BOOL CTcpAgent::HandleReceive(const TDispContext* pContext, TAgentSocketObj* pSo
return TRUE;
}
BOOL CTcpAgent::HandleSend(const TDispContext* pContext, TAgentSocketObj* pSocketObj, int flag)
BOOL CTcpAgent::HandleSend(TAgentSocketObj* pSocketObj, int flag)
{
ASSERT(TAgentSocketObj::IsValid(pSocketObj));
@@ -1263,7 +1237,7 @@ BOOL CTcpAgent::DoSendPackets(TAgentSocketObj* pSocketObj, const WSABUF pBuffers
int CTcpAgent::SendInternal(TAgentSocketObj* pSocketObj, const WSABUF pBuffers[], int iCount)
{
BOOL bPending = pSocketObj->IsPending();
int iPending = pSocketObj->Pending();
for(int i = 0; i < iCount; i++)
{
@@ -1279,9 +1253,9 @@ int CTcpAgent::SendInternal(TAgentSocketObj* pSocketObj, const WSABUF pBuffers[]
}
}
if(!bPending && pSocketObj->IsPending())
if(iPending == 0 && pSocketObj->IsPending())
{
if(!m_ioDispatcher.SendCommandByFD(pSocketObj->socket, DISP_CMD_SEND, pSocketObj->connID))
if(!m_ioDispatcher.SendCommand(DISP_CMD_SEND, pSocketObj->connID))
return ::GetLastError();
}

View File

@@ -74,15 +74,15 @@ protected:
#endif
private:
virtual BOOL OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual VOID OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT events, BOOL rs) override;
virtual VOID OnCommand(const TDispContext* pContext, TDispCommand* pCmd) override;
virtual BOOL OnReadyRead(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnReadyWrite(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnHungUp(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnError(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual VOID OnDispatchThreadStart(THR_ID tid) override;
virtual VOID OnDispatchThreadEnd(THR_ID tid) override;
virtual BOOL OnBeforeProcessIo(PVOID pv, UINT events) override;
virtual VOID OnAfterProcessIo(PVOID pv, UINT events, BOOL rs) override;
virtual VOID OnCommand(TDispCommand* pCmd) override;
virtual BOOL OnReadyRead(PVOID pv, UINT events) override;
virtual BOOL OnReadyWrite(PVOID pv, UINT events) override;
virtual BOOL OnHungUp(PVOID pv, UINT events) override;
virtual BOOL OnError(PVOID pv, UINT events) override;
virtual VOID OnDispatchThreadStart(THR_ID tid) override;
virtual VOID OnDispatchThreadEnd(THR_ID tid) override;
public:
virtual BOOL IsSecure () {return FALSE;}
@@ -91,9 +91,8 @@ public:
virtual BOOL GetConnectionExtra(CONNID dwConnID, PVOID* ppExtra);
virtual void SetReuseAddressPolicy (EnReuseAddressPolicy enReusePolicy) {ENSURE_HAS_STOPPED(); m_enReusePolicy = enReusePolicy;}
virtual void SetSendPolicy (EnSendPolicy enSendPolicy) {ENSURE_HAS_STOPPED(); ASSERT(m_enSendPolicy == enSendPolicy);}
virtual void SetOnSendSyncPolicy (EnOnSendSyncPolicy enOnSendSyncPolicy) {ENSURE_HAS_STOPPED(); ASSERT(m_enOnSendSyncPolicy == enOnSendSyncPolicy);}
virtual void SetSyncConnectTimeout (DWORD dwSyncConnectTimeout) {ENSURE_HAS_STOPPED(); m_dwSyncConnectTimeout = dwSyncConnectTimeout;}
virtual void SetSendPolicy (EnSendPolicy enSendPolicy) {ENSURE_HAS_STOPPED(); m_enSendPolicy = enSendPolicy;}
virtual void SetOnSendSyncPolicy (EnOnSendSyncPolicy enOnSendSyncPolicy) {ENSURE_HAS_STOPPED(); m_enOnSendSyncPolicy = enOnSendSyncPolicy;}
virtual void SetMaxConnectionCount (DWORD dwMaxConnectionCount) {ENSURE_HAS_STOPPED(); m_dwMaxConnectionCount = dwMaxConnectionCount;}
virtual void SetWorkerThreadCount (DWORD dwWorkerThreadCount) {ENSURE_HAS_STOPPED(); m_dwWorkerThreadCount = dwWorkerThreadCount;}
virtual void SetSocketBufferSize (DWORD dwSocketBufferSize) {ENSURE_HAS_STOPPED(); m_dwSocketBufferSize = dwSocketBufferSize;}
@@ -110,7 +109,6 @@ public:
virtual EnReuseAddressPolicy GetReuseAddressPolicy () {return m_enReusePolicy;}
virtual EnSendPolicy GetSendPolicy () {return m_enSendPolicy;}
virtual EnOnSendSyncPolicy GetOnSendSyncPolicy () {return m_enOnSendSyncPolicy;}
virtual DWORD GetSyncConnectTimeout () {return m_dwSyncConnectTimeout;}
virtual DWORD GetMaxConnectionCount () {return m_dwMaxConnectionCount;}
virtual DWORD GetWorkerThreadCount () {return m_dwWorkerThreadCount;}
virtual DWORD GetSocketBufferSize () {return m_dwSocketBufferSize;}
@@ -173,8 +171,6 @@ protected:
virtual void OnWorkerThreadStart(THR_ID tid) {}
virtual void OnWorkerThreadEnd(THR_ID tid) {}
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE);
BOOL DoSendPackets(CONNID dwConnID, const WSABUF pBuffers[], int iCount);
BOOL DoSendPackets(TAgentSocketObj* pSocketObj, const WSABUF pBuffers[], int iCount);
TAgentSocketObj* FindSocketObj(CONNID dwConnID);
@@ -209,21 +205,22 @@ private:
void AddFreeSocketObj (TAgentSocketObj* pSocketObj, EnSocketCloseFlag enFlag = SCF_NONE, EnSocketOperation enOperation = SO_UNKNOWN, int iErrorCode = 0);
void DeleteSocketObj (TAgentSocketObj* pSocketObj);
BOOL InvalidSocketObj (TAgentSocketObj* pSocketObj);
void ReleaseGCSocketObj (BOOL bForce = FALSE);
void AddClientSocketObj (CONNID dwConnID, TAgentSocketObj* pSocketObj, const HP_SOCKADDR& remoteAddr, LPCTSTR lpszRemoteHostName, PVOID pExtra);
void CloseClientSocketObj(TAgentSocketObj* pSocketObj, EnSocketCloseFlag enFlag = SCF_NONE, EnSocketOperation enOperation = SO_UNKNOWN, int iErrorCode = 0, int iShutdownFlag = SHUT_WR);
private:
int CreateClientSocket(LPCTSTR lpszRemoteAddress, USHORT usPort, LPCTSTR lpszLocalAddress, USHORT usLocalPort, SOCKET& soClient, HP_SOCKADDR& addr);
int PrepareConnect (CONNID& dwConnID, SOCKET soClient);
int ConnectToServer (CONNID dwConnID, LPCTSTR lpszRemoteHostName, SOCKET& soClient, const HP_SOCKADDR& addr, PVOID pExtra);
int ConnectToServer (CONNID dwConnID, LPCTSTR lpszRemoteHostName, SOCKET soClient, const HP_SOCKADDR& addr, PVOID pExtra);
VOID HandleCmdSend (const TDispContext* pContext, CONNID dwConnID);
VOID HandleCmdUnpause (const TDispContext* pContext, CONNID dwConnID);
VOID HandleCmdDisconnect(const TDispContext* pContext, CONNID dwConnID, BOOL bForce);
BOOL HandleConnect (const TDispContext* pContext, TAgentSocketObj* pSocketObj, UINT events);
BOOL HandleReceive (const TDispContext* pContext, TAgentSocketObj* pSocketObj, int flag);
BOOL HandleSend (const TDispContext* pContext, TAgentSocketObj* pSocketObj, int flag);
BOOL HandleClose (const TDispContext* pContext, TAgentSocketObj* pSocketObj, EnSocketCloseFlag enFlag, UINT events);
VOID HandleCmdSend (CONNID dwConnID);
VOID HandleCmdUnpause (CONNID dwConnID);
VOID HandleCmdDisconnect(CONNID dwConnID, BOOL bForce);
BOOL HandleConnect (TAgentSocketObj* pSocketObj, UINT events);
BOOL HandleReceive (TAgentSocketObj* pSocketObj, int flag);
BOOL HandleSend (TAgentSocketObj* pSocketObj, int flag);
BOOL HandleClose (TAgentSocketObj* pSocketObj, EnSocketCloseFlag enFlag, UINT events);
int SendInternal (TAgentSocketObj* pSocketObj, const WSABUF pBuffers[], int iCount);
BOOL SendItem (TAgentSocketObj* pSocketObj, TItem* pItem, BOOL& bBlocked);
@@ -233,12 +230,10 @@ public:
: m_pListener (pListener)
, m_enLastError (SE_OK)
, m_enState (SS_STOPPED)
, m_fdGCTimer (INVALID_FD)
, m_bAsyncConnect (TRUE)
, m_enReusePolicy (RAP_ADDR_ONLY)
, m_enSendPolicy (SP_PACK)
, m_enOnSendSyncPolicy (OSSP_RECEIVE)
, m_dwSyncConnectTimeout (DEFAULT_SYNC_CONNECT_TIMEOUT)
, m_enOnSendSyncPolicy (OSSP_NONE)
, m_dwMaxConnectionCount (DEFAULT_CONNECTION_COUNT)
, m_dwWorkerThreadCount (DEFAULT_WORKER_THREAD_COUNT)
, m_dwSocketBufferSize (DEFAULT_TCP_SOCKET_BUFFER_SIZE)
@@ -265,7 +260,6 @@ private:
EnReuseAddressPolicy m_enReusePolicy;
EnSendPolicy m_enSendPolicy;
EnOnSendSyncPolicy m_enOnSendSyncPolicy;
DWORD m_dwSyncConnectTimeout;
DWORD m_dwMaxConnectionCount;
DWORD m_dwWorkerThreadCount;
DWORD m_dwSocketBufferSize;
@@ -288,19 +282,16 @@ private:
EnSocketError m_enLastError;
HP_SOCKADDR m_soAddr;
CReceiveBuffersPtr m_rcBuffers;
CPrivateHeap m_phSocket;
CBufferObjPool m_bfObjPool;
CSpinGuard m_csState;
FD m_fdGCTimer;
TAgentSocketObjPtrPool m_bfActiveSockets;
TAgentSocketObjPtrList m_lsFreeSocket;
TAgentSocketObjPtrQueue m_lsGCSocket;
TReceiveBufferMap m_rcBufferMap;
CIODispatcher m_ioDispatcher;
};

View File

@@ -73,8 +73,7 @@ BOOL CTcpClient::Start(LPCTSTR lpszRemoteAddress, USHORT usPort, BOOL bAsyncConn
BOOL CTcpClient::CheckParams()
{
if (((int)m_dwSyncConnectTimeout > 0) &&
((int)m_dwSocketBufferSize > 0) &&
if (((int)m_dwSocketBufferSize > 0) &&
((int)m_dwFreeBufferPoolSize >= 0) &&
((int)m_dwFreeBufferPoolHold >= 0) &&
((int)m_dwKeepAliveTime >= 1000 || m_dwKeepAliveTime == 0) &&
@@ -187,36 +186,32 @@ BOOL CTcpClient::ConnectToServer(const HP_SOCKADDR& addrRemote, BOOL bAsyncConne
{
BOOL isOK = FALSE;
VERIFY(::fcntl_SETFL(m_soClient, O_NOATIME | O_NONBLOCK | O_CLOEXEC));
int rc = ::connect(m_soClient, addrRemote.Addr(), addrRemote.AddrSize());
if(IS_NO_ERROR(rc) || IS_IO_PENDING_ERROR())
if(bAsyncConnect)
{
if(bAsyncConnect)
VERIFY(::fcntl_SETFL(m_soClient, O_NOATIME | O_NONBLOCK | O_CLOEXEC));
int rc = ::connect(m_soClient, addrRemote.Addr(), addrRemote.AddrSize());
if(IS_NO_ERROR(rc) || IS_IO_PENDING_ERROR())
{
m_nEvents = POLLOUT;
isOK = TRUE;
}
else
}
else
{
if(::connect(m_soClient, addrRemote.Addr(), addrRemote.AddrSize()) != SOCKET_ERROR)
{
if(IS_HAS_ERROR(rc))
rc = ::WaitForSocketWrite(m_soClient, m_dwSyncConnectTimeout);
VERIFY(::fcntl_SETFL(m_soClient, O_NOATIME | O_NONBLOCK | O_CLOEXEC));
if(!IS_NO_ERROR(rc))
::WSASetLastError(rc);
SetConnected();
if(TRIGGER(FireConnect()) == HR_ERROR)
::WSASetLastError(ENSURE_ERROR_CANCELLED);
else
{
SetConnected();
if(TRIGGER(FireConnect()) == HR_ERROR)
::WSASetLastError(ENSURE_ERROR_CANCELLED);
else
{
m_nEvents = (SHORT)((m_lsSend.IsEmpty() ? 0 : POLLOUT) | (m_bPaused ? 0 : POLLIN) | POLLRDHUP);
isOK = TRUE;
}
m_nEvents = (SHORT)((m_lsSend.IsEmpty() ? 0 : POLLOUT) | (m_bPaused ? 0 : POLLIN) | POLLRDHUP);
isOK = TRUE;
}
}
}

View File

@@ -68,7 +68,6 @@ public:
virtual BOOL IsSecure () {return FALSE;}
virtual void SetReuseAddressPolicy (EnReuseAddressPolicy enReusePolicy){ENSURE_HAS_STOPPED(); m_enReusePolicy = enReusePolicy;}
virtual void SetSyncConnectTimeout (DWORD dwSyncConnectTimeout) {ENSURE_HAS_STOPPED(); m_dwSyncConnectTimeout = dwSyncConnectTimeout;}
virtual void SetSocketBufferSize (DWORD dwSocketBufferSize) {ENSURE_HAS_STOPPED(); m_dwSocketBufferSize = dwSocketBufferSize;}
virtual void SetKeepAliveTime (DWORD dwKeepAliveTime) {ENSURE_HAS_STOPPED(); m_dwKeepAliveTime = dwKeepAliveTime;}
virtual void SetKeepAliveInterval (DWORD dwKeepAliveInterval) {ENSURE_HAS_STOPPED(); m_dwKeepAliveInterval = dwKeepAliveInterval;}
@@ -78,7 +77,6 @@ public:
virtual void SetExtra (PVOID pExtra) {m_pExtra = pExtra;}
virtual EnReuseAddressPolicy GetReuseAddressPolicy () {return m_enReusePolicy;}
virtual DWORD GetSyncConnectTimeout () {return m_dwSyncConnectTimeout;}
virtual DWORD GetSocketBufferSize () {return m_dwSocketBufferSize;}
virtual DWORD GetKeepAliveTime () {return m_dwKeepAliveTime;}
virtual DWORD GetKeepAliveInterval () {return m_dwKeepAliveInterval;}
@@ -183,7 +181,6 @@ public:
, m_pExtra (nullptr)
, m_pReserved (nullptr)
, m_enReusePolicy (RAP_ADDR_ONLY)
, m_dwSyncConnectTimeout(DEFAULT_SYNC_CONNECT_TIMEOUT)
, m_dwSocketBufferSize (DEFAULT_TCP_SOCKET_BUFFER_SIZE)
, m_dwFreeBufferPoolSize(DEFAULT_CLIENT_FREE_BUFFER_POOL_SIZE)
, m_dwFreeBufferPoolHold(DEFAULT_CLIENT_FREE_BUFFER_POOL_HOLD)
@@ -209,7 +206,6 @@ private:
CONNID m_dwConnID;
EnReuseAddressPolicy m_enReusePolicy;
DWORD m_dwSyncConnectTimeout;
DWORD m_dwSocketBufferSize;
DWORD m_dwFreeBufferPoolSize;
DWORD m_dwFreeBufferPoolHold;

View File

@@ -114,6 +114,8 @@ protected:
virtual BOOL BeforeUnpause(TAgentSocketObj* pSocketObj)
{
CReentrantCriSecLock locallock(pSocketObj->csIo);
if(!TAgentSocketObj::IsValid(pSocketObj))
return FALSE;
@@ -155,15 +157,6 @@ protected:
m_bfPool.Prepare();
}
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE)
{
__super::ReleaseGCSocketObj(bForce);
#ifdef USE_EXTERNAL_GC
m_bfPool.ReleaseGCBuffer(bForce);
#endif
}
public:
virtual void SetMaxPackSize (DWORD dwMaxPackSize) {ENSURE_HAS_STOPPED(); m_dwMaxPackSize = dwMaxPackSize;}
virtual void SetPackHeaderFlag (USHORT usPackHeaderFlag) {ENSURE_HAS_STOPPED(); m_usHeaderFlag = usPackHeaderFlag;}

View File

@@ -114,6 +114,8 @@ protected:
virtual BOOL BeforeUnpause(TSocketObj* pSocketObj)
{
CReentrantCriSecLock locallock(pSocketObj->csIo);
if(!TSocketObj::IsValid(pSocketObj))
return FALSE;
@@ -155,15 +157,6 @@ protected:
m_bfPool.Prepare();
}
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE)
{
__super::ReleaseGCSocketObj(bForce);
#ifdef USE_EXTERNAL_GC
m_bfPool.ReleaseGCBuffer(bForce);
#endif
}
public:
virtual void SetMaxPackSize (DWORD dwMaxPackSize) {ENSURE_HAS_STOPPED(); m_dwMaxPackSize = dwMaxPackSize;}
virtual void SetPackHeaderFlag (USHORT usPackHeaderFlag) {ENSURE_HAS_STOPPED(); m_usHeaderFlag = usPackHeaderFlag;}

View File

@@ -125,15 +125,6 @@ protected:
m_bfPool.Prepare();
}
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE)
{
__super::ReleaseGCSocketObj(bForce);
#ifdef USE_EXTERNAL_GC
m_bfPool.ReleaseGCBuffer(bForce);
#endif
}
private:
void ReleaseConnectionExtra(TAgentSocketObj* pSocketObj)
{

View File

@@ -125,15 +125,6 @@ protected:
m_bfPool.Prepare();
}
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE)
{
__super::ReleaseGCSocketObj(bForce);
#ifdef USE_EXTERNAL_GC
m_bfPool.ReleaseGCBuffer(bForce);
#endif
}
private:
void ReleaseConnectionExtra(TSocketObj* pSocketObj)
{

View File

@@ -83,12 +83,6 @@ void CTcpServer::PrepareStart()
m_bfObjPool.SetPoolHold(m_dwFreeBufferObjHold);
m_bfObjPool.Prepare();
m_rcBuffers = make_unique<CBufferPtr[]>(m_dwWorkerThreadCount);
for_each(m_rcBuffers.get(), m_rcBuffers.get() + m_dwWorkerThreadCount, [this](CBufferPtr& buff) {buff.Malloc(m_dwSocketBufferSize);});
m_soListens = make_unique<SOCKET[]>(m_dwWorkerThreadCount);
for_each(m_soListens.get(), m_soListens.get() + m_dwWorkerThreadCount, [](SOCKET& sock) {sock = INVALID_FD;});
}
BOOL CTcpServer::CheckStarting()
@@ -126,98 +120,68 @@ BOOL CTcpServer::CheckStoping()
BOOL CTcpServer::CreateListenSocket(LPCTSTR lpszBindAddress, USHORT usPort)
{
BOOL isOK = FALSE;
if(::IsStrEmpty(lpszBindAddress))
lpszBindAddress = DEFAULT_IPV4_BIND_ADDRESS;
HP_SOCKADDR addr;
if(!::sockaddr_A_2_IN(lpszBindAddress, usPort, addr))
if(::sockaddr_A_2_IN(lpszBindAddress, usPort, addr))
{
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
m_soListen = socket(addr.family, SOCK_STREAM, IPPROTO_TCP);
for(DWORD i = 0; i < m_dwWorkerThreadCount; i++)
{
m_soListens[i] = socket(addr.family, SOCK_STREAM, IPPROTO_TCP);
SOCKET soListen = m_soListens[i];
if(IS_INVALID_FD(soListen))
if(m_soListen != INVALID_SOCKET)
{
::fcntl_SETFL(m_soListen, O_NOATIME | O_NONBLOCK | O_CLOEXEC);
BOOL bOnOff = (m_dwKeepAliveTime > 0 && m_dwKeepAliveInterval > 0);
VERIFY(IS_NO_ERROR(::SSO_KeepAliveVals(m_soListen, bOnOff, m_dwKeepAliveTime, m_dwKeepAliveInterval)));
VERIFY(IS_NO_ERROR(::SSO_ReuseAddress(m_soListen, m_enReusePolicy)));
VERIFY(IS_NO_ERROR(::SSO_NoDelay(m_soListen, m_bNoDelay)));
if(::bind(m_soListen, addr.Addr(), addr.AddrSize()) != SOCKET_ERROR)
{
if(TRIGGER(FirePrepareListen(m_soListen)) != HR_ERROR)
{
if(::listen(m_soListen, m_dwSocketListenQueue) != SOCKET_ERROR)
{
isOK = TRUE;
}
else
SetLastError(SE_SOCKET_LISTEN, __FUNCTION__, ::WSAGetLastError());
}
else
SetLastError(SE_SOCKET_PREPARE, __FUNCTION__, ENSURE_ERROR_CANCELLED);
}
else
SetLastError(SE_SOCKET_BIND, __FUNCTION__, ::WSAGetLastError());
}
else
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
::fcntl_SETFL(soListen, O_NOATIME | O_NONBLOCK | O_CLOEXEC);
BOOL bOnOff = (m_dwKeepAliveTime > 0 && m_dwKeepAliveInterval > 0);
VERIFY(IS_NO_ERROR(::SSO_KeepAliveVals(soListen, bOnOff, m_dwKeepAliveTime, m_dwKeepAliveInterval)));
VERIFY(IS_NO_ERROR(::SSO_ReuseAddress(soListen, m_enReusePolicy)));
VERIFY(IS_NO_ERROR(::SSO_NoDelay(soListen, m_bNoDelay)));
if(IS_HAS_ERROR(::bind(soListen, addr.Addr(), addr.AddrSize())))
{
SetLastError(SE_SOCKET_BIND, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
if(TRIGGER(FirePrepareListen(soListen)) == HR_ERROR)
{
SetLastError(SE_SOCKET_PREPARE, __FUNCTION__, ENSURE_ERROR_CANCELLED);
return FALSE;
}
if(IS_HAS_ERROR(::listen(soListen, m_dwSocketListenQueue)))
{
SetLastError(SE_SOCKET_LISTEN, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
}
else
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ::WSAGetLastError());
return TRUE;
return isOK;
}
BOOL CTcpServer::CreateWorkerThreads()
{
DWORD dwWorkerThreadCount = m_dwWorkerThreadCount
#ifdef USE_EXTERNAL_GC
+ 1
#endif
;
if(!m_ioDispatcher.Start(this, m_dwAcceptSocketCount, dwWorkerThreadCount))
{
SetLastError(SE_WORKER_THREAD_CREATE, __FUNCTION__, ::WSAGetLastError());
if(!m_ioDispatcher.Start(this, m_dwAcceptSocketCount, m_dwWorkerThreadCount))
return FALSE;
}
const CIODispatcher::CWorkerThread* pWorkerThread = m_ioDispatcher.GetWorkerThreads();
for(DWORD i = 0; i < m_dwWorkerThreadCount; i++)
m_rcBufferMap[pWorkerThread[i].GetThreadID()] = new CBufferPtr(m_dwSocketBufferSize);
return TRUE;
}
BOOL CTcpServer::StartAccept()
{
for(int i = 0; i < (int)m_dwWorkerThreadCount; i++)
{
SOCKET& soListen = m_soListens[i];
if(!m_ioDispatcher.AddFD(i, soListen, EPOLLIN | EPOLLET, TO_PVOID(&soListen)))
{
SetLastError(SE_SOCKE_ATTACH_TO_CP, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
}
#ifdef USE_EXTERNAL_GC
m_fdGCTimer = m_ioDispatcher.AddTimer(m_dwWorkerThreadCount, GC_CHECK_INTERVAL, this);
if(IS_INVALID_FD(m_fdGCTimer))
{
SetLastError(SE_GC_START, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
#endif
return TRUE;
return m_ioDispatcher.AddFD(m_soListen, _EPOLL_READ_EVENTS | EPOLLET, TO_PVOID(&m_soListen));
}
BOOL CTcpServer::Stop()
@@ -244,16 +208,10 @@ BOOL CTcpServer::Stop()
void CTcpServer::CloseListenSocket()
{
if(m_soListens)
if(m_soListen != INVALID_SOCKET)
{
for_each(m_soListens.get(), m_soListens.get() + m_dwWorkerThreadCount, [](SOCKET& sock)
{
if(sock != INVALID_FD)
{
::ManualCloseSocket(sock);
sock = INVALID_FD;
}
});
::ManualCloseSocket(m_soListen);
m_soListen = INVALID_SOCKET;
::WaitFor(100);
}
@@ -292,14 +250,6 @@ void CTcpServer::ReleaseFreeSocket()
{
m_lsFreeSocket.Clear();
#ifdef USE_EXTERNAL_GC
if(IS_VALID_FD(m_fdGCTimer))
{
close(m_fdGCTimer);
m_fdGCTimer = INVALID_FD;
}
#endif
ReleaseGCSocketObj(TRUE);
VERIFY(m_lsGCSocket.IsEmpty());
}
@@ -309,8 +259,7 @@ void CTcpServer::Reset()
m_phSocket.Reset();
m_bfObjPool.Clear();
m_rcBuffers = nullptr;
m_soListens = nullptr;
::ClearPtrMap(m_rcBufferMap);
m_enState = SS_STOPPED;
@@ -359,9 +308,7 @@ void CTcpServer::AddFreeSocketObj(TSocketObj* pSocketObj, EnSocketCloseFlag enFl
m_bfActiveSockets.Remove(pSocketObj->connID);
TSocketObj::Release(pSocketObj);
#ifndef USE_EXTERNAL_GC
ReleaseGCSocketObj();
#endif
if(!m_lsFreeSocket.TryPut(pSocketObj))
m_lsGCSocket.PushBack(pSocketObj);
@@ -419,13 +366,7 @@ BOOL CTcpServer::GetListenAddress(TCHAR lpszAddress[], int& iAddressLen, USHORT&
{
ASSERT(lpszAddress != nullptr && iAddressLen > 0);
if(!HasStarted())
{
::SetLastError(ERROR_INVALID_STATE);
return FALSE;
}
return ::GetSocketLocalAddress(m_soListens[0], lpszAddress, iAddressLen, usPort);
return ::GetSocketLocalAddress(m_soListen, lpszAddress, iAddressLen, usPort);
}
BOOL CTcpServer::GetLocalAddress(CONNID dwConnID, TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort)
@@ -677,7 +618,7 @@ BOOL CTcpServer::Disconnect(CONNID dwConnID, BOOL bForce)
return FALSE;
}
return m_ioDispatcher.SendCommandByFD(pSocketObj->socket, DISP_CMD_DISCONNECT, dwConnID, bForce);
return m_ioDispatcher.SendCommand(DISP_CMD_DISCONNECT, dwConnID, bForce);
}
BOOL CTcpServer::DisconnectLongConnections(DWORD dwPeriod, BOOL bForce)
@@ -746,23 +687,16 @@ BOOL CTcpServer::PauseReceive(CONNID dwConnID, BOOL bPause)
pSocketObj->paused = bPause;
if(!bPause)
return m_ioDispatcher.SendCommandByFD(pSocketObj->socket, DISP_CMD_UNPAUSE, pSocketObj->connID);
return m_ioDispatcher.SendCommand(DISP_CMD_UNPAUSE, pSocketObj->connID);
return TRUE;
}
BOOL CTcpServer::OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CTcpServer::OnBeforeProcessIo(PVOID pv, UINT events)
{
if(pv == &m_soListens[pContext->GetIndex()])
if(pv == &m_soListen)
{
HandleAccept(pContext, events);
return FALSE;
}
else if(pv == this)
{
ReleaseGCSocketObj(FALSE);
::ReadTimer(m_fdGCTimer);
HandleAccept(events);
return FALSE;
}
@@ -775,17 +709,20 @@ BOOL CTcpServer::OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT
pSocketObj->SetConnected(FALSE);
pSocketObj->Increment();
pSocketObj->csIo.lock();
if(!TSocketObj::IsValid(pSocketObj))
{
pSocketObj->csIo.unlock();
pSocketObj->Decrement();
return FALSE;
}
return TRUE;
}
VOID CTcpServer::OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT events, BOOL rs)
VOID CTcpServer::OnAfterProcessIo(PVOID pv, UINT events, BOOL rs)
{
TSocketObj* pSocketObj = (TSocketObj*)(pv);
@@ -794,37 +731,38 @@ VOID CTcpServer::OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT e
ASSERT(rs && !(events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)));
UINT evts = (pSocketObj->IsPending() ? EPOLLOUT : 0) | (pSocketObj->IsPaused() ? 0 : EPOLLIN);
m_ioDispatcher.ModFD(pSocketObj->socket, evts | EPOLLRDHUP, pSocketObj);
m_ioDispatcher.ModFD(pSocketObj->socket, evts | EPOLLRDHUP | EPOLLONESHOT, pSocketObj);
}
pSocketObj->csIo.unlock();
pSocketObj->Decrement();
}
VOID CTcpServer::OnCommand(const TDispContext* pContext, TDispCommand* pCmd)
VOID CTcpServer::OnCommand(TDispCommand* pCmd)
{
switch(pCmd->type)
{
case DISP_CMD_SEND:
HandleCmdSend(pContext, (CONNID)(pCmd->wParam));
HandleCmdSend((CONNID)(pCmd->wParam));
break;
case DISP_CMD_UNPAUSE:
HandleCmdUnpause(pContext, (CONNID)(pCmd->wParam));
HandleCmdUnpause((CONNID)(pCmd->wParam));
break;
case DISP_CMD_DISCONNECT:
HandleCmdDisconnect(pContext, (CONNID)(pCmd->wParam), (BOOL)pCmd->lParam);
HandleCmdDisconnect((CONNID)(pCmd->wParam), (BOOL)pCmd->lParam);
break;
}
}
VOID CTcpServer::HandleCmdSend(const TDispContext* pContext, CONNID dwConnID)
VOID CTcpServer::HandleCmdSend(CONNID dwConnID)
{
TSocketObj* pSocketObj = FindSocketObj(dwConnID);
if(TSocketObj::IsValid(pSocketObj) && pSocketObj->IsPending())
m_ioDispatcher.ProcessIo(pContext, pSocketObj, EPOLLOUT);
m_ioDispatcher.ProcessIo(pSocketObj, EPOLLOUT);
}
VOID CTcpServer::HandleCmdUnpause(const TDispContext* pContext, CONNID dwConnID)
VOID CTcpServer::HandleCmdUnpause(CONNID dwConnID)
{
TSocketObj* pSocketObj = FindSocketObj(dwConnID);
@@ -832,37 +770,37 @@ VOID CTcpServer::HandleCmdUnpause(const TDispContext* pContext, CONNID dwConnID)
return;
if(BeforeUnpause(pSocketObj))
m_ioDispatcher.ProcessIo(pContext, pSocketObj, EPOLLIN);
m_ioDispatcher.ProcessIo(pSocketObj, EPOLLIN);
else
AddFreeSocketObj(pSocketObj, SCF_ERROR, SO_RECEIVE, ENSURE_ERROR_CANCELLED);
}
VOID CTcpServer::HandleCmdDisconnect(const TDispContext* pContext, CONNID dwConnID, BOOL bForce)
VOID CTcpServer::HandleCmdDisconnect(CONNID dwConnID, BOOL bForce)
{
TSocketObj* pSocketObj = FindSocketObj(dwConnID);
if(TSocketObj::IsValid(pSocketObj))
m_ioDispatcher.ProcessIo(pContext, pSocketObj, EPOLLHUP);
m_ioDispatcher.ProcessIo(pSocketObj, EPOLLHUP);
}
BOOL CTcpServer::OnReadyRead(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CTcpServer::OnReadyRead(PVOID pv, UINT events)
{
return HandleReceive(pContext, (TSocketObj*)pv, RETRIVE_EVENT_FLAG_H(events));
return HandleReceive((TSocketObj*)pv, RETRIVE_EVENT_FLAG_H(events));
}
BOOL CTcpServer::OnReadyWrite(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CTcpServer::OnReadyWrite(PVOID pv, UINT events)
{
return HandleSend(pContext, (TSocketObj*)pv, RETRIVE_EVENT_FLAG_H(events));
return HandleSend((TSocketObj*)pv, RETRIVE_EVENT_FLAG_H(events));
}
BOOL CTcpServer::OnHungUp(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CTcpServer::OnHungUp(PVOID pv, UINT events)
{
return HandleClose(pContext, (TSocketObj*)pv, SCF_CLOSE, events);
return HandleClose((TSocketObj*)pv, SCF_CLOSE, events);
}
BOOL CTcpServer::OnError(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CTcpServer::OnError(PVOID pv, UINT events)
{
return HandleClose(pContext, (TSocketObj*)pv, SCF_ERROR, events);
return HandleClose((TSocketObj*)pv, SCF_ERROR, events);
}
VOID CTcpServer::OnDispatchThreadStart(THR_ID tid)
@@ -875,7 +813,7 @@ VOID CTcpServer::OnDispatchThreadEnd(THR_ID tid)
OnWorkerThreadEnd(tid);
}
BOOL CTcpServer::HandleClose(const TDispContext* pContext, TSocketObj* pSocketObj, EnSocketCloseFlag enFlag, UINT events)
BOOL CTcpServer::HandleClose(TSocketObj* pSocketObj, EnSocketCloseFlag enFlag, UINT events)
{
EnSocketOperation enOperation = SO_CLOSE;
@@ -896,7 +834,7 @@ BOOL CTcpServer::HandleClose(const TDispContext* pContext, TSocketObj* pSocketOb
return TRUE;
}
BOOL CTcpServer::HandleAccept(const TDispContext* pContext, UINT events)
BOOL CTcpServer::HandleAccept(UINT events)
{
if(events & _EPOLL_ALL_ERROR_EVENTS)
{
@@ -909,7 +847,7 @@ BOOL CTcpServer::HandleAccept(const TDispContext* pContext, UINT events)
HP_SOCKADDR addr;
socklen_t addrLen = (socklen_t)addr.AddrSize();
SOCKET soClient = ::accept(m_soListens[pContext->GetIndex()], addr.Addr(), &addrLen);
SOCKET soClient = ::accept(m_soListen, addr.Addr(), &addrLen);
if(soClient == INVALID_SOCKET)
{
@@ -950,7 +888,7 @@ BOOL CTcpServer::HandleAccept(const TDispContext* pContext, UINT events)
UINT evts = (pSocketObj->IsPending() ? EPOLLOUT : 0) | (pSocketObj->IsPaused() ? 0 : EPOLLIN);
if(!m_ioDispatcher.AddFD(pSocketObj->socket, evts | EPOLLRDHUP, pSocketObj))
if(!m_ioDispatcher.AddFD(pSocketObj->socket, evts | EPOLLRDHUP | EPOLLONESHOT, pSocketObj))
{
AddFreeSocketObj(pSocketObj, SCF_ERROR, SO_ACCEPT, ::WSAGetLastError());
continue;
@@ -960,13 +898,13 @@ BOOL CTcpServer::HandleAccept(const TDispContext* pContext, UINT events)
return TRUE;
}
BOOL CTcpServer::HandleReceive(const TDispContext* pContext, TSocketObj* pSocketObj, int flag)
BOOL CTcpServer::HandleReceive(TSocketObj* pSocketObj, int flag)
{
ASSERT(TSocketObj::IsValid(pSocketObj));
if(m_bMarkSilence) pSocketObj->activeTime = ::TimeGetTime();
CBufferPtr& buffer = m_rcBuffers[pContext->GetIndex()];
CBufferPtr& buffer = *(m_rcBufferMap[SELF_THREAD_ID]);
int reads = flag ? -1 : MAX_CONTINUE_READS;
@@ -1009,7 +947,7 @@ BOOL CTcpServer::HandleReceive(const TDispContext* pContext, TSocketObj* pSocket
return TRUE;
}
BOOL CTcpServer::HandleSend(const TDispContext* pContext, TSocketObj* pSocketObj, int flag)
BOOL CTcpServer::HandleSend(TSocketObj* pSocketObj, int flag)
{
ASSERT(TSocketObj::IsValid(pSocketObj));
@@ -1144,7 +1082,7 @@ BOOL CTcpServer::DoSendPackets(TSocketObj* pSocketObj, const WSABUF pBuffers[],
int CTcpServer::SendInternal(TSocketObj* pSocketObj, const WSABUF pBuffers[], int iCount)
{
BOOL bPending = pSocketObj->IsPending();
int iPending = pSocketObj->Pending();
for(int i = 0; i < iCount; i++)
{
@@ -1160,9 +1098,9 @@ int CTcpServer::SendInternal(TSocketObj* pSocketObj, const WSABUF pBuffers[], in
}
}
if(!bPending && pSocketObj->IsPending())
if(iPending == 0 && pSocketObj->IsPending())
{
if(!m_ioDispatcher.SendCommandByFD(pSocketObj->socket, DISP_CMD_SEND, pSocketObj->connID))
if(!m_ioDispatcher.SendCommand(DISP_CMD_SEND, pSocketObj->connID))
return ::GetLastError();
}

View File

@@ -76,15 +76,15 @@ protected:
#endif
private:
virtual BOOL OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual VOID OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT events, BOOL rs) override;
virtual VOID OnCommand(const TDispContext* pContext, TDispCommand* pCmd) override;
virtual BOOL OnReadyRead(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnReadyWrite(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnHungUp(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnError(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual VOID OnDispatchThreadStart(THR_ID tid) override;
virtual VOID OnDispatchThreadEnd(THR_ID tid) override;
virtual BOOL OnBeforeProcessIo(PVOID pv, UINT events) override;
virtual VOID OnAfterProcessIo(PVOID pv, UINT events, BOOL rs) override;
virtual VOID OnCommand(TDispCommand* pCmd) override;
virtual BOOL OnReadyRead(PVOID pv, UINT events) override;
virtual BOOL OnReadyWrite(PVOID pv, UINT events) override;
virtual BOOL OnHungUp(PVOID pv, UINT events) override;
virtual BOOL OnError(PVOID pv, UINT events) override;
virtual VOID OnDispatchThreadStart(THR_ID tid) override;
virtual VOID OnDispatchThreadEnd(THR_ID tid) override;
public:
virtual BOOL IsSecure () {return FALSE;}
@@ -92,9 +92,9 @@ public:
virtual BOOL SetConnectionExtra(CONNID dwConnID, PVOID pExtra);
virtual BOOL GetConnectionExtra(CONNID dwConnID, PVOID* ppExtra);
virtual void SetReuseAddressPolicy (EnReuseAddressPolicy enReusePolicy) {ENSURE_HAS_STOPPED(); ASSERT(m_enReusePolicy == enReusePolicy);}
virtual void SetSendPolicy (EnSendPolicy enSendPolicy) {ENSURE_HAS_STOPPED(); ASSERT(m_enSendPolicy == enSendPolicy);}
virtual void SetOnSendSyncPolicy (EnOnSendSyncPolicy enOnSendSyncPolicy) {ENSURE_HAS_STOPPED(); ASSERT(m_enOnSendSyncPolicy == enOnSendSyncPolicy);}
virtual void SetReuseAddressPolicy (EnReuseAddressPolicy enReusePolicy) {ENSURE_HAS_STOPPED(); m_enReusePolicy = enReusePolicy;}
virtual void SetSendPolicy (EnSendPolicy enSendPolicy) {ENSURE_HAS_STOPPED(); m_enSendPolicy = enSendPolicy;}
virtual void SetOnSendSyncPolicy (EnOnSendSyncPolicy enOnSendSyncPolicy) {ENSURE_HAS_STOPPED(); m_enOnSendSyncPolicy = enOnSendSyncPolicy;}
virtual void SetMaxConnectionCount (DWORD dwMaxConnectionCount) {ENSURE_HAS_STOPPED(); m_dwMaxConnectionCount = dwMaxConnectionCount;}
virtual void SetWorkerThreadCount (DWORD dwWorkerThreadCount) {ENSURE_HAS_STOPPED(); m_dwWorkerThreadCount = dwWorkerThreadCount;}
virtual void SetSocketListenQueue (DWORD dwSocketListenQueue) {ENSURE_HAS_STOPPED(); m_dwSocketListenQueue = dwSocketListenQueue;}
@@ -174,10 +174,8 @@ protected:
virtual BOOL BeforeUnpause(TSocketObj* pSocketObj) {return TRUE;}
virtual void OnWorkerThreadStart(THR_ID tid) {}
virtual void OnWorkerThreadEnd(THR_ID tid) {}
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE);
virtual void OnWorkerThreadStart(THR_ID tid) {}
virtual void OnWorkerThreadEnd(THR_ID tid) {}
BOOL DoSendPackets(CONNID dwConnID, const WSABUF pBuffers[], int iCount);
BOOL DoSendPackets(TSocketObj* pSocketObj, const WSABUF pBuffers[], int iCount);
@@ -214,17 +212,18 @@ private:
void AddFreeSocketObj (TSocketObj* pSocketObj, EnSocketCloseFlag enFlag = SCF_NONE, EnSocketOperation enOperation = SO_UNKNOWN, int iErrorCode = 0);
void DeleteSocketObj (TSocketObj* pSocketObj);
BOOL InvalidSocketObj (TSocketObj* pSocketObj);
void ReleaseGCSocketObj (BOOL bForce = FALSE);
void AddClientSocketObj (CONNID dwConnID, TSocketObj* pSocketObj, const HP_SOCKADDR& remoteAddr);
void CloseClientSocketObj(TSocketObj* pSocketObj, EnSocketCloseFlag enFlag = SCF_NONE, EnSocketOperation enOperation = SO_UNKNOWN, int iErrorCode = 0, int iShutdownFlag = SHUT_WR);
private:
VOID HandleCmdSend (const TDispContext* pContext, CONNID dwConnID);
VOID HandleCmdUnpause (const TDispContext* pContext, CONNID dwConnID);
VOID HandleCmdDisconnect(const TDispContext* pContext, CONNID dwConnID, BOOL bForce);
BOOL HandleAccept (const TDispContext* pContext, UINT events);
BOOL HandleReceive (const TDispContext* pContext, TSocketObj* pSocketObj, int flag);
BOOL HandleSend (const TDispContext* pContext, TSocketObj* pSocketObj, int flag);
BOOL HandleClose (const TDispContext* pContext, TSocketObj* pSocketObj, EnSocketCloseFlag enFlag, UINT events);
VOID HandleCmdSend (CONNID dwConnID);
VOID HandleCmdUnpause (CONNID dwConnID);
VOID HandleCmdDisconnect(CONNID dwConnID, BOOL bForce);
BOOL HandleAccept (UINT events);
BOOL HandleReceive (TSocketObj* pSocketObj, int flag);
BOOL HandleSend (TSocketObj* pSocketObj, int flag);
BOOL HandleClose (TSocketObj* pSocketObj, EnSocketCloseFlag enFlag, UINT events);
int SendInternal (TSocketObj* pSocketObj, const WSABUF pBuffers[], int iCount);
BOOL SendItem (TSocketObj* pSocketObj, TItem* pItem, BOOL& bBlocked);
@@ -232,12 +231,12 @@ private:
public:
CTcpServer(ITcpServerListener* pListener)
: m_pListener (pListener)
, m_soListen (INVALID_SOCKET)
, m_enLastError (SE_OK)
, m_enState (SS_STOPPED)
, m_fdGCTimer (INVALID_FD)
, m_enReusePolicy (RAP_ADDR_AND_PORT)
, m_enReusePolicy (RAP_ADDR_ONLY)
, m_enSendPolicy (SP_PACK)
, m_enOnSendSyncPolicy (OSSP_RECEIVE)
, m_enOnSendSyncPolicy (OSSP_NONE)
, m_dwMaxConnectionCount (DEFAULT_CONNECTION_COUNT)
, m_dwWorkerThreadCount (DEFAULT_WORKER_THREAD_COUNT)
, m_dwSocketListenQueue (DEFAULT_TCP_SERVER_SOCKET_LISTEN_QUEUE)
@@ -284,23 +283,20 @@ private:
CSEM m_evWait;
ITcpServerListener* m_pListener;
ListenSocketsPtr m_soListens;
SOCKET m_soListen;
EnServiceState m_enState;
EnSocketError m_enLastError;
CReceiveBuffersPtr m_rcBuffers;
CPrivateHeap m_phSocket;
CBufferObjPool m_bfObjPool;
CSpinGuard m_csState;
FD m_fdGCTimer;
TSocketObjPtrPool m_bfActiveSockets;
TSocketObjPtrList m_lsFreeSocket;
TSocketObjPtrQueue m_lsGCSocket;
TReceiveBufferMap m_rcBufferMap;
CIODispatcher m_ioDispatcher;
};

View File

@@ -73,15 +73,6 @@ void CUdpArqServer::OnWorkerThreadStart(THR_ID dwThreadID)
::WaitFor(3);
}
void CUdpArqServer::ReleaseGCSocketObj(BOOL bForce)
{
__super::ReleaseGCSocketObj(bForce);
#ifdef USE_EXTERNAL_GC
m_ssPool.ReleaseGCSession(bForce);
#endif
}
BOOL CUdpArqServer::Send(CONNID dwConnID, const BYTE* pBuffer, int iLength, int iOffset)
{
ASSERT(pBuffer && iLength > 0 && iLength <= (int)m_arqAttr.dwMaxMessageSize);

View File

@@ -55,8 +55,6 @@ protected:
virtual void Reset();
virtual void OnWorkerThreadStart(THR_ID dwThreadID);
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE);
public:
virtual void SetNoDelay (BOOL bNoDelay) {ENSURE_HAS_STOPPED(); m_arqAttr.bNoDelay = bNoDelay;}
virtual void SetTurnoffCongestCtrl (BOOL bTurnOff) {ENSURE_HAS_STOPPED(); m_arqAttr.bTurnoffNc = bTurnOff;}

View File

@@ -24,7 +24,7 @@
#if defined(__GNUC__) && __GNUC__ >= 11
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#include "UdpNode.h"
@@ -40,16 +40,13 @@ BOOL CUdpNode::Start(LPCTSTR lpszBindAddress, USHORT usPort, EnCastMode enCastMo
PrepareStart();
HP_SOCKADDR bindAddr(AF_UNSPEC, TRUE);
if(ParseBindAddr(lpszBindAddress, usPort, lpszCastAddress, bindAddr))
if(CreateListenSocket(bindAddr))
if(CreateWorkerThreads())
if(StartAccept())
{
m_enState = SS_STARTED;
return TRUE;
}
if(CreateListenSocket(lpszBindAddress, usPort, lpszCastAddress))
if(CreateWorkerThreads())
if(StartAccept())
{
m_enState = SS_STARTED;
return TRUE;
}
EXECUTE_RESTORE_ERROR(Stop());
@@ -74,7 +71,7 @@ BOOL CUdpNode::CheckParams()
BOOL CUdpNode::CheckStarting()
{
CReentrantWriteLock locallock(m_lcState);
CSpinLock locallock(m_csState);
if(m_enState == SS_STOPPED)
m_enState = SS_STARTING;
@@ -94,24 +91,39 @@ void CUdpNode::PrepareStart()
m_bfObjPool.SetPoolHold(m_dwFreeBufferPoolHold);
m_bfObjPool.Prepare();
TNodeBufferObjList* pBufferObjList = (TNodeBufferObjList*)malloc(m_dwWorkerThreadCount * sizeof(TNodeBufferObjList));
for(int i = 0; i < (int)m_dwWorkerThreadCount; i++)
new (pBufferObjList + i) TNodeBufferObjList(m_bfObjPool);
m_sndBuffs.reset(pBufferObjList);
m_csSends = make_unique<CCriSec[]>(m_dwWorkerThreadCount);
m_rcBuffers = make_unique<CBufferPtr[]>(m_dwWorkerThreadCount);
for_each(m_rcBuffers.get(), m_rcBuffers.get() + m_dwWorkerThreadCount, [this](CBufferPtr& buff) {buff.Malloc(m_dwMaxDatagramSize);});
m_soListens = make_unique<SOCKET[]>(m_dwWorkerThreadCount);
for_each(m_soListens.get(), m_soListens.get() + m_dwWorkerThreadCount, [](SOCKET& sock) {sock = INVALID_FD;});
}
BOOL CUdpNode::ParseBindAddr(LPCTSTR lpszBindAddress, USHORT usPort, LPCTSTR lpszCastAddress, HP_SOCKADDR& bindAddr)
BOOL CUdpNode::CreateListenSocket(LPCTSTR lpszBindAddress, USHORT usPort, LPCTSTR lpszCastAddress)
{
HP_SOCKADDR bindAddr(AF_UNSPEC, TRUE);
if(CreateListenSocket(lpszBindAddress, usPort, lpszCastAddress, bindAddr))
{
if(BindListenSocket(bindAddr))
{
if(TRIGGER(FirePrepareListen(m_soListen)) != HR_ERROR)
{
if(ConnectToGroup(bindAddr))
{
return TRUE;
}
else
SetLastError(SE_CONNECT_SERVER, __FUNCTION__, ::WSAGetLastError());
}
else
SetLastError(SE_SOCKET_PREPARE, __FUNCTION__, ENSURE_ERROR_CANCELLED);
}
else
SetLastError(SE_SOCKET_BIND, __FUNCTION__, ::WSAGetLastError());
}
else
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
BOOL CUdpNode::CreateListenSocket(LPCTSTR lpszBindAddress, USHORT usPort, LPCTSTR lpszCastAddress, HP_SOCKADDR& bindAddr)
{
if(::IsStrEmpty(lpszCastAddress))
{
@@ -119,16 +131,13 @@ BOOL CUdpNode::ParseBindAddr(LPCTSTR lpszBindAddress, USHORT usPort, LPCTSTR lps
lpszCastAddress = DEFAULT_IPV4_BROAD_CAST_ADDRESS;
else if(m_enCastMode == CM_MULTICAST)
{
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ERROR_ADDRNOTAVAIL);
::WSASetLastError(ERROR_ADDRNOTAVAIL);
return FALSE;
}
}
if(m_enCastMode != CM_UNICAST && !::sockaddr_A_2_IN(lpszCastAddress, usPort, m_castAddr))
{
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
if(::IsStrEmpty(lpszBindAddress))
{
@@ -138,80 +147,58 @@ BOOL CUdpNode::ParseBindAddr(LPCTSTR lpszBindAddress, USHORT usPort, LPCTSTR lps
else
{
if(!::sockaddr_A_2_IN(lpszBindAddress, usPort, bindAddr))
{
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
}
if(m_enCastMode == CM_BROADCAST && bindAddr.IsIPv6())
{
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ERROR_PFNOSUPPORT);
::WSASetLastError(ERROR_PFNOSUPPORT);
return FALSE;
}
if(m_enCastMode != CM_UNICAST && m_castAddr.family != bindAddr.family)
{
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ERROR_AFNOSUPPORT);
::WSASetLastError(ERROR_AFNOSUPPORT);
return FALSE;
}
m_soListen = socket(bindAddr.family, SOCK_DGRAM, IPPROTO_UDP);
if(m_soListen == INVALID_SOCKET)
return FALSE;
VERIFY(::fcntl_SETFL(m_soListen, O_NOATIME | O_NONBLOCK | O_CLOEXEC));
VERIFY(::SSO_ReuseAddress(m_soListen, m_enReusePolicy) == NO_ERROR);
return TRUE;
}
BOOL CUdpNode::CreateListenSocket(const HP_SOCKADDR& bindAddr)
BOOL CUdpNode::BindListenSocket(HP_SOCKADDR& bindAddr)
{
for(DWORD i = 0; i < m_dwWorkerThreadCount; i++)
if(::bind(m_soListen, bindAddr.Addr(), bindAddr.AddrSize()) == SOCKET_ERROR)
return FALSE;
socklen_t dwAddrLen = (socklen_t)bindAddr.AddrSize();
ENSURE(::getsockname(m_soListen, m_localAddr.Addr(), &dwAddrLen) != SOCKET_ERROR);
return TRUE;
}
BOOL CUdpNode::ConnectToGroup(const HP_SOCKADDR& bindAddr)
{
if(m_enCastMode == CM_UNICAST)
return TRUE;
else if(m_enCastMode == CM_MULTICAST)
{
m_soListens[i] = socket(bindAddr.family, SOCK_DGRAM, IPPROTO_UDP);
SOCKET soListen = m_soListens[i];
if(IS_INVALID_FD(soListen))
{
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ::WSAGetLastError());
if(!::SetMultiCastSocketOptions(m_soListen, bindAddr, m_castAddr, m_iMCTtl, m_bMCLoop))
return FALSE;
}
}
else
{
ASSERT(m_castAddr.IsIPv4());
::fcntl_SETFL(soListen, O_NOATIME | O_NONBLOCK | O_CLOEXEC);
VERIFY(IS_NO_ERROR(::SSO_ReuseAddress(soListen, m_enReusePolicy)));
if(IS_HAS_ERROR(::bind(soListen, bindAddr.Addr(), bindAddr.AddrSize())))
{
SetLastError(SE_SOCKET_BIND, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
if(i == 0)
{
socklen_t dwAddrLen = (socklen_t)bindAddr.AddrSize();
ENSURE(IS_NO_ERROR(::getsockname(soListen, m_localAddr.Addr(), &dwAddrLen)));
}
if(m_enCastMode == CM_MULTICAST)
{
if(!::SetMultiCastSocketOptions(soListen, bindAddr, m_castAddr, m_iMCTtl, m_bMCLoop))
{
SetLastError(SE_CONNECT_SERVER, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
}
else if(m_enCastMode == CM_BROADCAST)
{
ASSERT(m_castAddr.IsIPv4());
BOOL bSet = TRUE;
if(IS_HAS_ERROR(::SSO_SetSocketOption(soListen, SOL_SOCKET, SO_BROADCAST, &bSet, sizeof(BOOL))))
{
SetLastError(SE_CONNECT_SERVER, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
}
if(TRIGGER(FirePrepareListen(soListen)) == HR_ERROR)
{
SetLastError(SE_SOCKET_PREPARE, __FUNCTION__, ENSURE_ERROR_CANCELLED);
return FALSE;
}
BOOL bSet = TRUE;
ENSURE(::SSO_SetSocketOption(m_soListen, SOL_SOCKET, SO_BROADCAST, &bSet, sizeof(BOOL)) != SOCKET_ERROR);
}
return TRUE;
@@ -224,15 +211,7 @@ BOOL CUdpNode::CreateWorkerThreads()
BOOL CUdpNode::StartAccept()
{
for(int i = 0; i < (int)m_dwWorkerThreadCount; i++)
{
SOCKET& soListen = m_soListens[i];
if(!m_ioDispatcher.AddFD(i, soListen, EPOLLIN | EPOLLOUT | EPOLLET, TO_PVOID(&soListen)))
return FALSE;
}
return TRUE;
return m_ioDispatcher.AddFD(m_soListen, _EPOLL_READ_EVENTS | EPOLLET, TO_PVOID(&m_soListen));
}
BOOL CUdpNode::Stop()
@@ -257,7 +236,7 @@ BOOL CUdpNode::CheckStoping()
{
if(m_enState != SS_STOPPED)
{
CReentrantWriteLock locallock(m_lcState);
CSpinLock locallock(m_csState);
if(HasStarted())
{
@@ -273,19 +252,13 @@ BOOL CUdpNode::CheckStoping()
void CUdpNode::CloseListenSocket()
{
if(m_soListens)
{
for_each(m_soListens.get(), m_soListens.get() + m_dwWorkerThreadCount, [](SOCKET& sock)
{
if(sock != INVALID_FD)
{
::ManualCloseSocket(sock);
sock = INVALID_FD;
}
});
if(m_soListen == INVALID_SOCKET)
return;
::WaitFor(100);
}
::ManualCloseSocket(m_soListen);
m_soListen = INVALID_SOCKET;
::WaitFor(100);
}
void CUdpNode::WaitForWorkerThreadEnd()
@@ -295,16 +268,14 @@ void CUdpNode::WaitForWorkerThreadEnd()
void CUdpNode::ReleaseFreeBuffer()
{
for_each(m_sndBuffs.get(), m_sndBuffs.get() + m_dwWorkerThreadCount, [](TNodeBufferObjList& sndBuff)
{
sndBuff.Clear();
sndBuff.~TNodeBufferObjList();
});
TNodeBufferObj* pBufferObj = nullptr;
free(m_sndBuffs.release());
while(m_recvQueue.PopFront(&pBufferObj))
m_bfObjPool.PutFreeItem(pBufferObj);
m_csSends = nullptr;
VERIFY(m_recvQueue.IsEmpty());
m_sndBuff.Clear();
m_bfObjPool.Clear();
}
@@ -313,20 +284,12 @@ void CUdpNode::Reset()
m_castAddr.Reset();
m_localAddr.Reset();
m_soListens = nullptr;
m_rcBuffers = nullptr;
m_iSending = 0;
m_enState = SS_STOPPED;
m_evWait.SyncNotifyAll();
}
int CUdpNode::GenerateBufferIndex(const HP_SOCKADDR& addrRemote)
{
return (int)(addrRemote.Hash() % m_dwWorkerThreadCount);
}
BOOL CUdpNode::Send(LPCTSTR lpszRemoteAddress, USHORT usRemotePort, const BYTE* pBuffer, int iLength, int iOffset)
{
HP_SOCKADDR addrRemote;
@@ -351,6 +314,7 @@ BOOL CUdpNode::SendCast(const BYTE* pBuffer, int iLength, int iOffset)
{
if(m_enCastMode == CM_UNICAST)
{
::SetLastError(ERROR_INVALID_OPERATION);
return FALSE;
}
@@ -362,14 +326,14 @@ BOOL CUdpNode::SendCastPackets(const WSABUF pBuffers[], int iCount)
{
if(m_enCastMode == CM_UNICAST)
{
::SetLastError(ERROR_INVALID_OPERATION);
::SetLastError(ERROR_INCORRECT_ADDRESS);
return FALSE;
}
return DoSendPackets(m_castAddr, pBuffers, iCount);
}
BOOL CUdpNode::DoSend(const HP_SOCKADDR& addrRemote, const BYTE* pBuffer, int iLength, int iOffset)
BOOL CUdpNode::DoSend(HP_SOCKADDR& addrRemote, const BYTE* pBuffer, int iLength, int iOffset)
{
ASSERT(pBuffer && iLength >= 0 && iLength <= (int)m_dwMaxDatagramSize);
@@ -403,7 +367,7 @@ BOOL CUdpNode::DoSend(const HP_SOCKADDR& addrRemote, const BYTE* pBuffer, int iL
return (result == NO_ERROR);
}
BOOL CUdpNode::DoSendPackets(const HP_SOCKADDR& addrRemote, const WSABUF pBuffers[], int iCount)
BOOL CUdpNode::DoSendPackets(HP_SOCKADDR& addrRemote, const WSABUF pBuffers[], int iCount)
{
ASSERT(pBuffers && iCount > 0);
@@ -457,81 +421,77 @@ BOOL CUdpNode::DoSendPackets(const HP_SOCKADDR& addrRemote, const WSABUF pBuffer
return (result == NO_ERROR);
}
int CUdpNode::SendInternal(const HP_SOCKADDR& addrRemote, TNodeBufferObjPtr& bufPtr)
int CUdpNode::SendInternal(HP_SOCKADDR& addrRemote, TNodeBufferObjPtr& bufPtr)
{
BOOL bPending;
int iBufferSize = bufPtr->Size();
int idx = GenerateBufferIndex(addrRemote);
addrRemote.Copy(bufPtr->remoteAddr);
BOOL bPending;
int iBufferSize;
{
CReentrantReadLock locallock(m_lcState);
CSpinLock locallock(m_csState);
if(!IsValid())
return ERROR_INVALID_STATE;
TNodeBufferObjList& sndBuff = m_sndBuffs[idx];
bPending = IsPending();
iBufferSize = bufPtr->Size();
CCriSecLock locallock2(m_csSends[idx]);
m_sndBuff.PushBack(bufPtr.Detach());
if(iBufferSize == 0) m_sndBuff.IncreaseLength(1);
bPending = IsPending(idx);
sndBuff.PushBack(bufPtr.Detach());
if(iBufferSize == 0) sndBuff.IncreaseLength(1);
ASSERT(sndBuff.Length() > 0);
ASSERT(m_sndBuff.Length() > 0);
}
if(!bPending && IsPending(idx))
VERIFY(m_ioDispatcher.SendCommandByIndex(idx, DISP_CMD_SEND));
if(!bPending && IsPending())
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_SEND));
return NO_ERROR;
}
BOOL CUdpNode::OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CUdpNode::OnBeforeProcessIo(PVOID pv, UINT events)
{
ASSERT(pv == &m_soListens[pContext->GetIndex()]);
ASSERT(pv == &m_soListen);
return TRUE;
}
VOID CUdpNode::OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT events, BOOL rs)
VOID CUdpNode::OnAfterProcessIo(PVOID pv, UINT events, BOOL rs)
{
}
VOID CUdpNode::OnCommand(const TDispContext* pContext, TDispCommand* pCmd)
VOID CUdpNode::OnCommand(TDispCommand* pCmd)
{
int idx = pContext->GetIndex();
int flag = (int)(pCmd->wParam);
switch(pCmd->type)
{
case DISP_CMD_SEND:
HandleCmdSend(idx, flag);
HandleCmdSend((int)(pCmd->wParam));
break;
case DISP_CMD_RECEIVE:
HandleCmdReceive((int)(pCmd->wParam));
break;
}
}
BOOL CUdpNode::OnReadyRead(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CUdpNode::OnReadyRead(PVOID pv, UINT events)
{
return HandleReceive(pContext, RETRIVE_EVENT_FLAG_H(events));
return HandleReceive(RETRIVE_EVENT_FLAG_H(events));
}
BOOL CUdpNode::OnReadyWrite(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CUdpNode::OnReadyWrite(PVOID pv, UINT events)
{
return HandleSend(pContext, RETRIVE_EVENT_FLAG_H(events), RETRIVE_EVENT_FLAG_R(events));
return HandleSend(RETRIVE_EVENT_FLAG_H(events), RETRIVE_EVENT_FLAG_R(events));
}
BOOL CUdpNode::OnHungUp(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CUdpNode::OnHungUp(PVOID pv, UINT events)
{
return HandleClose(pContext->GetIndex(), nullptr, SO_CLOSE, 0);
return HandleClose(nullptr, SO_CLOSE, 0);
}
BOOL CUdpNode::OnError(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CUdpNode::OnError(PVOID pv, UINT events)
{
return HandleClose(pContext->GetIndex(), nullptr, SO_CLOSE, -1);
return HandleClose(nullptr, SO_CLOSE, -1);
}
VOID CUdpNode::OnDispatchThreadStart(THR_ID tid)
@@ -544,44 +504,44 @@ VOID CUdpNode::OnDispatchThreadEnd(THR_ID tid)
OnWorkerThreadEnd(tid);
}
BOOL CUdpNode::HandleClose(int idx, TNodeBufferObj* pBufferObj, EnSocketOperation enOperation, int iErrorCode)
BOOL CUdpNode::HandleClose(TNodeBufferObj* pBufferObj, EnSocketOperation enOperation, int iErrorCode)
{
if(!HasStarted())
return FALSE;
if(iErrorCode == -1)
iErrorCode = ::SSO_GetError(m_soListens[idx]);
iErrorCode = ::SSO_GetError(m_soListen);
if(pBufferObj != nullptr)
TRIGGER(FireError(&pBufferObj->remoteAddr, pBufferObj->Ptr(), pBufferObj->Size(), enOperation, iErrorCode));
else
TRIGGER(FireError(nullptr, nullptr, 0, enOperation, iErrorCode));
TRIGGER(FireError(pBufferObj, enOperation, iErrorCode));
return TRUE;
}
BOOL CUdpNode::HandleReceive(const TDispContext* pContext, int flag)
BOOL CUdpNode::HandleReceive(int flag)
{
int idx = pContext->GetIndex();
CBufferPtr& buffer = m_rcBuffers[idx];
int iBufferLen = (int)buffer.Size();
while(TRUE)
{
HP_SOCKADDR addr;
socklen_t dwAddrLen = (socklen_t)addr.AddrSize();
TNodeBufferObjPtr itPtr(m_bfObjPool, m_bfObjPool.PickFreeItem());
int rc = (int)recvfrom(m_soListens[idx], buffer.Ptr(), iBufferLen, MSG_TRUNC, addr.Addr(), &dwAddrLen);
int iBufferLen = itPtr->Capacity();
socklen_t dwAddrLen = (socklen_t)itPtr->remoteAddr.AddrSize();
int rc = (int)recvfrom(m_soListen, itPtr->Ptr(), iBufferLen, MSG_TRUNC, itPtr->remoteAddr.Addr(), &dwAddrLen);
if(rc >= 0)
{
if(rc > iBufferLen)
{
TRIGGER(FireError(&addr, buffer.Ptr(), iBufferLen, SO_RECEIVE, ERROR_BAD_LENGTH));
itPtr->Increase(iBufferLen);
TRIGGER(FireError(itPtr, SO_RECEIVE, ERROR_BAD_LENGTH));
continue;
}
TRIGGER(FireReceive(&addr, buffer.Ptr(), rc));
itPtr->Increase(rc);
m_recvQueue.PushBack(itPtr.Detach());
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_RECEIVE, flag));
}
else if(rc == SOCKET_ERROR)
{
@@ -589,7 +549,7 @@ BOOL CUdpNode::HandleReceive(const TDispContext* pContext, int flag)
if(code == ERROR_WOULDBLOCK)
break;
else if(!HandleClose(idx, nullptr, SO_RECEIVE, code))
else if(!HandleClose(itPtr, SO_RECEIVE, code))
return FALSE;
}
else
@@ -601,51 +561,78 @@ BOOL CUdpNode::HandleReceive(const TDispContext* pContext, int flag)
return TRUE;
}
BOOL CUdpNode::HandleSend(const TDispContext* pContext, int flag, int rd)
VOID CUdpNode::HandleCmdReceive(int flag)
{
HandleCmdSend(pContext->GetIndex(), flag);
if(m_recvQueue.IsEmpty())
return;
int reads = flag ? -1 : MAX_CONTINUE_READS;
for(int i = 0; i < reads || reads < 0; i++)
{
TNodeBufferObjPtr itPtr(m_bfObjPool);
if(!m_recvQueue.PopFront(&itPtr.PtrRef()))
break;
TRIGGER(FireReceive(itPtr));
}
if(!m_recvQueue.IsEmpty())
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_RECEIVE, flag));
}
BOOL CUdpNode::HandleSend(int flag, int rd)
{
m_ioDispatcher.ModFD(m_soListen, _EPOLL_READ_EVENTS | EPOLLET, TO_PVOID(&m_soListen));
if(rd)
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_SEND));
else
HandleCmdSend(flag);
return TRUE;
}
VOID CUdpNode::HandleCmdSend(int idx, int flag)
VOID CUdpNode::HandleCmdSend(int flag)
{
BOOL bBlocked = FALSE;
TNodeBufferObjList& sndBuff = m_sndBuffs[idx];
BOOL bBlocked = FALSE;
TNodeBufferObjPtr bufPtr(m_bfObjPool);
while(IsPending(idx))
while(IsPending())
{
{
CCriSecLock locallock(m_csSends[idx]);
bufPtr = sndBuff.PopFront();
CSpinLock locallock(m_csState);
bufPtr = m_sndBuff.PopFront();
}
if(!bufPtr.IsValid())
break;
if(!SendItem(idx, sndBuff, bufPtr, bBlocked))
if(!SendItem(bufPtr, bBlocked))
return;
if(bBlocked)
{
{
CCriSecLock locallock(m_csSends[idx]);
sndBuff.PushFront(bufPtr.Detach());
CSpinLock locallock(m_csState);
m_sndBuff.PushFront(bufPtr.Detach());
}
m_ioDispatcher.ModFD(m_soListen, EPOLLOUT | _EPOLL_READ_EVENTS | EPOLLET, TO_PVOID(&m_soListen));
break;
}
}
if(!bBlocked && IsPending(idx))
VERIFY(m_ioDispatcher.SendCommandByIndex(idx, DISP_CMD_SEND));
if(!bBlocked && IsPending())
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_SEND));
}
BOOL CUdpNode::SendItem(int idx, TNodeBufferObjList& sndBuff, TNodeBufferObj* pBufferObj, BOOL& bBlocked)
BOOL CUdpNode::SendItem(TNodeBufferObj* pBufferObj, BOOL& bBlocked)
{
int rc = (int)sendto(m_soListens[idx], pBufferObj->Ptr(), pBufferObj->Size(), 0, pBufferObj->remoteAddr.Addr(), pBufferObj->remoteAddr.AddrSize());
int rc = (int)sendto(m_soListen, pBufferObj->Ptr(), pBufferObj->Size(), 0, pBufferObj->remoteAddr.Addr(), pBufferObj->remoteAddr.AddrSize());
if(rc >= 0)
{
@@ -653,8 +640,8 @@ BOOL CUdpNode::SendItem(int idx, TNodeBufferObjList& sndBuff, TNodeBufferObj* pB
if(rc == 0)
{
CCriSecLock locallock(m_csSends[idx]);
sndBuff.ReduceLength(1);
CSpinLock locallock(m_csState);
m_sndBuff.ReduceLength(1);
}
TRIGGER(FireSend(pBufferObj));
@@ -665,7 +652,7 @@ BOOL CUdpNode::SendItem(int idx, TNodeBufferObjList& sndBuff, TNodeBufferObj* pB
if(code == ERROR_WOULDBLOCK)
bBlocked = TRUE;
else if(!HandleClose(idx, pBufferObj, SO_SEND, code))
else if(!HandleClose(pBufferObj, SO_SEND, code))
return FALSE;
}
else
@@ -694,26 +681,10 @@ void CUdpNode::SetLastError(EnSocketError code, LPCSTR func, int ec)
::SetLastError(ec);
}
BOOL CUdpNode::GetPendingDataLength(int& iPending)
{
iPending = 0;
{
CReentrantReadLock locallock(m_lcState);
if(!IsValid())
return FALSE;
for_each(m_sndBuffs.get(), m_sndBuffs.get() + m_dwWorkerThreadCount, [&iPending](TNodeBufferObjList& sndBuff) { iPending += sndBuff.Length(); });
}
return TRUE;
}
EnHandleResult CUdpNode::FireSend(TNodeBufferObj* pBufferObj)
{
TCHAR szAddress[60];
int iAddressLen = ARRAY_SIZE(szAddress);
int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
ADDRESS_FAMILY usFamily;
USHORT usPort;
@@ -722,32 +693,33 @@ EnHandleResult CUdpNode::FireSend(TNodeBufferObj* pBufferObj)
return m_pListener->OnSend(this, szAddress, usPort, pBufferObj->Ptr(), pBufferObj->Size());
}
EnHandleResult CUdpNode::FireReceive(const HP_SOCKADDR* pRemoteAddr, const BYTE* pData, int iLength)
EnHandleResult CUdpNode::FireReceive(TNodeBufferObj* pBufferObj)
{
TCHAR szAddress[60];
int iAddressLen = ARRAY_SIZE(szAddress);
int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
ADDRESS_FAMILY usFamily;
USHORT usPort;
::sockaddr_IN_2_A(*pRemoteAddr, usFamily, szAddress, iAddressLen, usPort);
return m_pListener->OnReceive(this, szAddress, usPort, pData, iLength);
::sockaddr_IN_2_A(pBufferObj->remoteAddr, usFamily, szAddress, iAddressLen, usPort);
return m_pListener->OnReceive(this, szAddress, usPort, pBufferObj->Ptr(), pBufferObj->Size());
}
EnHandleResult CUdpNode::FireError(const HP_SOCKADDR* pRemoteAddr, const BYTE* pData, int iLength, EnSocketOperation enOperation, int iErrorCode)
EnHandleResult CUdpNode::FireError(TNodeBufferObj* pBufferObj, EnSocketOperation enOperation, int iErrorCode)
{
TCHAR szAddress[60];
int iAddressLen = ARRAY_SIZE(szAddress);
int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
ADDRESS_FAMILY usFamily;
USHORT usPort;
if(pRemoteAddr == nullptr)
if(pBufferObj == nullptr)
{
::sockaddr_IN_2_A(m_localAddr, usFamily, szAddress, iAddressLen, usPort);
return m_pListener->OnError(this, enOperation, iErrorCode, szAddress, usPort, nullptr, 0);
}
::sockaddr_IN_2_A(*pRemoteAddr, usFamily, szAddress, iAddressLen, usPort);
return m_pListener->OnError(this, enOperation, iErrorCode, szAddress, usPort, pData, iLength);
::sockaddr_IN_2_A(pBufferObj->remoteAddr, usFamily, szAddress, iAddressLen, usPort);
return m_pListener->OnError(this, enOperation, iErrorCode, szAddress, usPort, pBufferObj->Ptr(), pBufferObj->Size());
}
#endif

View File

@@ -45,23 +45,23 @@ public:
virtual BOOL GetLocalAddress (TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort);
virtual BOOL GetCastAddress (TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort);
virtual BOOL GetPendingDataLength (int& iPending) {iPending = m_sndBuff.Length(); return HasStarted();}
virtual EnSocketError GetLastError () {return m_enLastError;}
virtual LPCTSTR GetLastErrorDesc () {return ::GetSocketErrorDesc(m_enLastError);}
virtual BOOL GetPendingDataLength (int& iPending);
private:
virtual BOOL OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual VOID OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT events, BOOL rs) override;
virtual VOID OnCommand(const TDispContext* pContext, TDispCommand* pCmd) override;
virtual BOOL OnReadyRead(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnReadyWrite(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnHungUp(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnError(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual VOID OnDispatchThreadStart(THR_ID tid) override;
virtual VOID OnDispatchThreadEnd(THR_ID tid) override;
virtual BOOL OnBeforeProcessIo(PVOID pv, UINT events) override;
virtual VOID OnAfterProcessIo(PVOID pv, UINT events, BOOL rs) override;
virtual VOID OnCommand(TDispCommand* pCmd) override;
virtual BOOL OnReadyRead(PVOID pv, UINT events) override;
virtual BOOL OnReadyWrite(PVOID pv, UINT events) override;
virtual BOOL OnHungUp(PVOID pv, UINT events) override;
virtual BOOL OnError(PVOID pv, UINT events) override;
virtual VOID OnDispatchThreadStart(THR_ID tid) override;
virtual VOID OnDispatchThreadEnd(THR_ID tid) override;
public:
virtual void SetReuseAddressPolicy (EnReuseAddressPolicy enReusePolicy){ENSURE_HAS_STOPPED(); ASSERT(m_enReusePolicy == enReusePolicy);}
virtual void SetReuseAddressPolicy (EnReuseAddressPolicy enReusePolicy){ENSURE_HAS_STOPPED(); m_enReusePolicy = enReusePolicy;}
virtual void SetWorkerThreadCount (DWORD dwWorkerThreadCount) {ENSURE_HAS_STOPPED(); m_dwWorkerThreadCount = dwWorkerThreadCount;}
virtual void SetFreeBufferPoolSize (DWORD dwFreeBufferPoolSize) {ENSURE_HAS_STOPPED(); m_dwFreeBufferPoolSize = dwFreeBufferPoolSize;}
virtual void SetFreeBufferPoolHold (DWORD dwFreeBufferPoolHold) {ENSURE_HAS_STOPPED(); m_dwFreeBufferPoolHold = dwFreeBufferPoolHold;}
@@ -89,8 +89,8 @@ protected:
{return m_pListener->OnShutdown(this);}
EnHandleResult FireSend(TNodeBufferObj* pBufferObj);
EnHandleResult FireReceive(const HP_SOCKADDR* pRemoteAddr, const BYTE* pData, int iLength);
EnHandleResult FireError(const HP_SOCKADDR* pRemoteAddr, const BYTE* pData, int iLength, EnSocketOperation enOperation, int iErrorCode);
EnHandleResult FireReceive(TNodeBufferObj* pBufferObj);
EnHandleResult FireError(TNodeBufferObj* pBufferObj, EnSocketOperation enOperation, int iErrorCode);
void SetLastError(EnSocketError code, LPCSTR func, int ec);
virtual BOOL CheckParams();
@@ -100,15 +100,17 @@ protected:
virtual void OnWorkerThreadStart(THR_ID dwThreadID) {}
virtual void OnWorkerThreadEnd(THR_ID dwThreadID) {}
BOOL DoSend(const HP_SOCKADDR& addrRemote, const BYTE* pBuffer, int iLength, int iOffset = 0);
BOOL DoSendPackets(const HP_SOCKADDR& addrRemote, const WSABUF pBuffers[], int iCount);
int SendInternal(const HP_SOCKADDR& addrRemote, TNodeBufferObjPtr& bufPtr);
BOOL DoSend(HP_SOCKADDR& addrRemote, const BYTE* pBuffer, int iLength, int iOffset = 0);
BOOL DoSendPackets(HP_SOCKADDR& addrRemote, const WSABUF pBuffers[], int iCount);
int SendInternal(HP_SOCKADDR& addrRemote, TNodeBufferObjPtr& bufPtr);
private:
BOOL CheckStarting();
BOOL CheckStoping();
BOOL ParseBindAddr(LPCTSTR lpszBindAddress, USHORT usPort, LPCTSTR lpszCastAddress, HP_SOCKADDR& bindAddr);
BOOL CreateListenSocket(const HP_SOCKADDR& bindAddr);
BOOL CreateListenSocket(LPCTSTR lpszBindAddress, USHORT usPort, LPCTSTR lpszCastAddress);
BOOL CreateListenSocket(LPCTSTR lpszBindAddress, USHORT usPort, LPCTSTR lpszCastAddress, HP_SOCKADDR& bindAddr);
BOOL BindListenSocket(HP_SOCKADDR& bindAddr);
BOOL ConnectToGroup(const HP_SOCKADDR& bindAddr);
BOOL CreateWorkerThreads();
BOOL StartAccept();
@@ -116,28 +118,29 @@ private:
void WaitForWorkerThreadEnd();
void ReleaseFreeBuffer();
int GenerateBufferIndex(const HP_SOCKADDR& addrRemote);
private:
BOOL HandleReceive(int flag = 0);
BOOL HandleSend(int flag = 0, int rd = 0);
BOOL HandleClose(TNodeBufferObj* pBufferObj, EnSocketOperation enOperation, int iErrorCode);
VOID HandleCmdReceive(int flag);
VOID HandleCmdSend(int flag);
BOOL SendItem(TNodeBufferObj* pBufferObj, BOOL& bBlocked);
private:
BOOL HandleReceive(const TDispContext* pContext, int flag = 0);
BOOL HandleSend(const TDispContext* pContext, int flag = 0, int rd = 0);
BOOL HandleClose(int idx, TNodeBufferObj* pBufferObj, EnSocketOperation enOperation, int iErrorCode);
VOID HandleCmdSend(int idx, int flag);
BOOL SendItem(int idx, TNodeBufferObjList& sndBuff, TNodeBufferObj* pBufferObj, BOOL& bBlocked);
private:
BOOL IsValid () {return m_enState == SS_STARTED;}
BOOL IsPending (int idx) {return m_sndBuffs[idx].Length() > 0;}
BOOL IsValid () {return m_enState == SS_STARTED;}
BOOL IsPending () {return m_sndBuff.Length() > 0;}
public:
CUdpNode(IUdpNodeListener* pListener)
: m_pListener (pListener)
, m_sndBuff (m_bfObjPool)
, m_soListen (INVALID_SOCKET)
, m_iSending (0)
, m_enLastError (SE_OK)
, m_enState (SS_STOPPED)
, m_enReusePolicy (RAP_ADDR_AND_PORT)
, m_enReusePolicy (RAP_ADDR_ONLY)
, m_dwWorkerThreadCount (DEFAULT_WORKER_THREAD_COUNT)
, m_dwFreeBufferPoolSize (DEFAULT_FREE_BUFFEROBJ_POOL)
, m_dwFreeBufferPoolHold (DEFAULT_FREE_BUFFEROBJ_HOLD)
@@ -178,17 +181,15 @@ private:
HP_SOCKADDR m_localAddr;
CNodeBufferObjPool m_bfObjPool;
CNodeCriSecs m_csSends;
TNodeBufferObjLists m_sndBuffs;
TNodeBufferObjList m_sndBuff;
CNodeRecvQueue m_recvQueue;
IUdpNodeListener* m_pListener;
ListenSocketsPtr m_soListens;
SOCKET m_soListen;
EnServiceState m_enState;
EnSocketError m_enLastError;
CReceiveBuffersPtr m_rcBuffers;
CRWLock m_lcState;
CSpinGuard m_csState;
volatile long m_iSending;

View File

@@ -61,7 +61,7 @@ void CUdpServer::SetLastError(EnSocketError code, LPCSTR func, int ec)
BOOL CUdpServer::CheckParams()
{
if ((m_enSendPolicy >= SP_PACK && m_enSendPolicy <= SP_DIRECT) &&
(m_enOnSendSyncPolicy >= OSSP_NONE && m_enOnSendSyncPolicy <= OSSP_RECEIVE) &&
(m_enOnSendSyncPolicy >= OSSP_NONE && m_enOnSendSyncPolicy <= OSSP_CLOSE) &&
((int)m_dwMaxConnectionCount > 0 && m_dwMaxConnectionCount <= MAX_CONNECTION_COUNT) &&
((int)m_dwWorkerThreadCount > 0 && m_dwWorkerThreadCount <= MAX_WORKER_THREAD_COUNT) &&
((int)m_dwFreeSocketObjLockTime >= 1000) &&
@@ -89,14 +89,6 @@ void CUdpServer::PrepareStart()
m_bfObjPool.SetPoolHold(m_dwFreeBufferObjHold);
m_bfObjPool.Prepare();
m_quSends = make_unique<CSendQueue[]>(m_dwWorkerThreadCount);
m_rcBuffers = make_unique<CBufferPtr[]>(m_dwWorkerThreadCount);
for_each(m_rcBuffers.get(), m_rcBuffers.get() + m_dwWorkerThreadCount, [this](CBufferPtr& buff) {buff.Malloc(m_dwMaxDatagramSize);});
m_soListens = make_unique<SOCKET[]>(m_dwWorkerThreadCount);
for_each(m_soListens.get(), m_soListens.get() + m_dwWorkerThreadCount, [](SOCKET& sock) {sock = INVALID_FD;});
}
BOOL CUdpServer::CheckStarting()
@@ -134,98 +126,49 @@ BOOL CUdpServer::CheckStoping()
BOOL CUdpServer::CreateListenSocket(LPCTSTR lpszBindAddress, USHORT usPort)
{
BOOL isOK = FALSE;
if(::IsStrEmpty(lpszBindAddress))
lpszBindAddress = DEFAULT_IPV4_BIND_ADDRESS;
HP_SOCKADDR addr;
if(!::sockaddr_A_2_IN(lpszBindAddress, usPort, addr))
if(::sockaddr_A_2_IN(lpszBindAddress, usPort, addr))
{
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
m_soListen = socket(addr.family, SOCK_DGRAM, IPPROTO_UDP);
for(DWORD i = 0; i < m_dwWorkerThreadCount; i++)
{
m_soListens[i] = socket(addr.family, SOCK_DGRAM, IPPROTO_UDP);
SOCKET soListen = m_soListens[i];
if(IS_INVALID_FD(soListen))
if(m_soListen != INVALID_SOCKET)
{
::fcntl_SETFL(m_soListen, O_NOATIME | O_NONBLOCK | O_CLOEXEC);
VERIFY(IS_NO_ERROR(::SSO_ReuseAddress(m_soListen, m_enReusePolicy)));
if(::bind(m_soListen, addr.Addr(), addr.AddrSize()) != SOCKET_ERROR)
{
if(TRIGGER(FirePrepareListen(m_soListen)) != HR_ERROR)
isOK = TRUE;
else
SetLastError(SE_SOCKET_PREPARE, __FUNCTION__, ENSURE_ERROR_CANCELLED);
}
else
SetLastError(SE_SOCKET_BIND, __FUNCTION__, ::WSAGetLastError());
}
else
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
::fcntl_SETFL(soListen, O_NOATIME | O_NONBLOCK | O_CLOEXEC);
VERIFY(IS_NO_ERROR(::SSO_ReuseAddress(soListen, m_enReusePolicy)));
if(IS_HAS_ERROR(::bind(soListen, addr.Addr(), addr.AddrSize())))
{
SetLastError(SE_SOCKET_BIND, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
if(TRIGGER(FirePrepareListen(soListen)) == HR_ERROR)
{
SetLastError(SE_SOCKET_PREPARE, __FUNCTION__, ENSURE_ERROR_CANCELLED);
return FALSE;
}
}
else
SetLastError(SE_SOCKET_CREATE, __FUNCTION__, ::WSAGetLastError());
return TRUE;
return isOK;
}
BOOL CUdpServer::CreateWorkerThreads()
{
DWORD dwWorkerThreadCount = m_dwWorkerThreadCount
#ifdef USE_EXTERNAL_GC
+ 1
#endif
;
if(!m_ioDispatcher.Start(this, m_dwPostReceiveCount, dwWorkerThreadCount))
{
SetLastError(SE_WORKER_THREAD_CREATE, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
#ifdef USE_EXTERNAL_GC
m_fdGCTimer = m_ioDispatcher.AddTimer(m_dwWorkerThreadCount, GC_CHECK_INTERVAL, this);
if(IS_INVALID_FD(m_fdGCTimer))
{
SetLastError(SE_GC_START, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
#endif
return TRUE;
return m_ioDispatcher.Start(this, m_dwPostReceiveCount, m_dwWorkerThreadCount);
}
BOOL CUdpServer::StartAccept()
{
for(int i = 0; i < (int)m_dwWorkerThreadCount; i++)
{
SOCKET& soListen = m_soListens[i];
if(!m_ioDispatcher.AddFD(i, soListen, EPOLLIN | EPOLLOUT | EPOLLET, TO_PVOID(&soListen)))
{
SetLastError(SE_SOCKE_ATTACH_TO_CP, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
}
#ifdef USE_EXTERNAL_GC
m_fdGCTimer = m_ioDispatcher.AddTimer(m_dwWorkerThreadCount, GC_CHECK_INTERVAL, this);
if(IS_INVALID_FD(m_fdGCTimer))
{
SetLastError(SE_GC_START, __FUNCTION__, ::WSAGetLastError());
return FALSE;
}
#endif
return TRUE;
return m_ioDispatcher.AddFD(m_soListen, _EPOLL_READ_EVENTS | EPOLLET, TO_PVOID(&m_soListen));
}
BOOL CUdpServer::Stop()
@@ -247,7 +190,6 @@ BOOL CUdpServer::Stop()
FireShutdown();
ReleaseFreeSocket();
ClearSendQueues();
Reset();
@@ -256,7 +198,7 @@ BOOL CUdpServer::Stop()
void CUdpServer::SendCloseNotify()
{
if(!m_soListens)
if(m_soListen == INVALID_SOCKET)
return;
if(m_bfActiveSockets.Elements() == 0)
return;
@@ -270,7 +212,7 @@ void CUdpServer::SendCloseNotify()
TUdpSocketObj* pSocketObj = FindSocketObj(connID);
if(TUdpSocketObj::IsValid(pSocketObj))
::SendUdpCloseNotify(m_soListens[pSocketObj->index], pSocketObj->remoteAddr);
::SendUdpCloseNotify(m_soListen, pSocketObj->remoteAddr);
}
::WaitFor(30);
@@ -278,19 +220,13 @@ void CUdpServer::SendCloseNotify()
void CUdpServer::CloseListenSocket()
{
if(m_soListens)
{
for_each(m_soListens.get(), m_soListens.get() + m_dwWorkerThreadCount, [](SOCKET& sock)
{
if(sock != INVALID_FD)
{
::ManualCloseSocket(sock);
sock = INVALID_FD;
}
});
if(m_soListen == INVALID_SOCKET)
return;
::WaitFor(70);
}
::ManualCloseSocket(m_soListen);
m_soListen = INVALID_SOCKET;
::WaitFor(70);
}
void CUdpServer::DisconnectClientSocket()
@@ -329,31 +265,15 @@ void CUdpServer::ReleaseFreeSocket()
{
m_lsFreeSocket.Clear();
#ifdef USE_EXTERNAL_GC
if(IS_VALID_FD(m_fdGCTimer))
{
close(m_fdGCTimer);
m_fdGCTimer = INVALID_FD;
}
#endif
ReleaseGCSocketObj(TRUE);
VERIFY(m_lsGCSocket.IsEmpty());
}
void CUdpServer::ClearSendQueues()
{
if(m_quSends) for_each(m_quSends.get(), m_quSends.get() + m_dwWorkerThreadCount, [](CSendQueue& queue) {queue.UnsafeClear();});
}
void CUdpServer::Reset()
{
m_phSocket.Reset();
m_bfObjPool.Clear();
m_soListens = nullptr;
m_rcBuffers = nullptr;
m_quSends = nullptr;
m_quSend.UnsafeClear();
m_enState = SS_STOPPED;
@@ -406,12 +326,10 @@ void CUdpServer::AddFreeSocketObj(TUdpSocketObj* pSocketObj, EnSocketCloseFlag e
m_mpClientAddr.erase(&pSocketObj->remoteAddr);
}
m_ioDispatcher.DelTimer(pSocketObj->index, pSocketObj->fdTimer);
m_ioDispatcher.DelTimer(pSocketObj->fdTimer);
TUdpSocketObj::Release(pSocketObj);
#ifndef USE_EXTERNAL_GC
ReleaseGCSocketObj();
#endif
if(!m_lsFreeSocket.TryPut(pSocketObj))
m_lsGCSocket.PushBack(pSocketObj);
@@ -427,18 +345,17 @@ BOOL CUdpServer::InvalidSocketObj(TUdpSocketObj* pSocketObj)
return TUdpSocketObj::InvalidSocketObj(pSocketObj);
}
void CUdpServer::AddClientSocketObj(int idx, CONNID dwConnID, TUdpSocketObj* pSocketObj, const HP_SOCKADDR& remoteAddr)
void CUdpServer::AddClientSocketObj(CONNID dwConnID, TUdpSocketObj* pSocketObj, const HP_SOCKADDR& remoteAddr)
{
ASSERT(FindSocketObj(dwConnID) == nullptr);
pSocketObj->index = idx;
if(IsNeedDetectConnection())
pSocketObj->fdTimer = m_ioDispatcher.AddTimer(m_dwDetectInterval, pSocketObj);
pSocketObj->pHolder = this;
pSocketObj->connTime = ::TimeGetTime();
pSocketObj->activeTime = pSocketObj->connTime;
if(IsNeedDetectConnection())
pSocketObj->fdTimer = m_ioDispatcher.AddTimer(pSocketObj->index, m_dwDetectInterval, pSocketObj);
remoteAddr.Copy(pSocketObj->remoteAddr);
pSocketObj->SetConnected();
@@ -475,10 +392,8 @@ void CUdpServer::CloseClientSocketObj(TUdpSocketObj* pSocketObj, EnSocketCloseFl
{
ASSERT(TUdpSocketObj::IsExist(pSocketObj));
SOCKET soListen = m_soListens[pSocketObj->index];
if(bNotify && soListen != INVALID_SOCKET)
::SendUdpCloseNotify(soListen, pSocketObj->remoteAddr);
if(bNotify && m_soListen != INVALID_SOCKET)
::SendUdpCloseNotify(m_soListen, pSocketObj->remoteAddr);
if(enFlag == SCF_CLOSE)
FireClose(pSocketObj, SO_CLOSE, SE_OK);
@@ -490,13 +405,7 @@ BOOL CUdpServer::GetListenAddress(TCHAR lpszAddress[], int& iAddressLen, USHORT&
{
ASSERT(lpszAddress != nullptr && iAddressLen > 0);
if(!HasStarted())
{
::SetLastError(ERROR_INVALID_STATE);
return FALSE;
}
return ::GetSocketLocalAddress(m_soListens[0], lpszAddress, iAddressLen, usPort);
return ::GetSocketLocalAddress(m_soListen, lpszAddress, iAddressLen, usPort);
}
BOOL CUdpServer::GetLocalAddress(CONNID dwConnID, TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort)
@@ -511,7 +420,7 @@ BOOL CUdpServer::GetLocalAddress(CONNID dwConnID, TCHAR lpszAddress[], int& iAdd
return FALSE;
}
return ::GetSocketLocalAddress(m_soListens[pSocketObj->index], lpszAddress, iAddressLen, usPort);
return ::GetSocketLocalAddress(m_soListen, lpszAddress, iAddressLen, usPort);
}
BOOL CUdpServer::GetRemoteAddress(CONNID dwConnID, TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort)
@@ -742,7 +651,7 @@ BOOL CUdpServer::Disconnect(CONNID dwConnID, BOOL bForce)
return FALSE;
}
return m_ioDispatcher.SendCommandByIndex(pSocketObj->index, DISP_CMD_DISCONNECT, dwConnID, bForce);
return m_ioDispatcher.SendCommand(DISP_CMD_DISCONNECT, dwConnID, bForce);
}
BOOL CUdpServer::DisconnectLongConnections(DWORD dwPeriod, BOOL bForce)
@@ -801,17 +710,10 @@ BOOL CUdpServer::PauseReceive(CONNID dwConnID, BOOL bPause)
return FALSE;
}
BOOL CUdpServer::OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CUdpServer::OnBeforeProcessIo(PVOID pv, UINT events)
{
if(pv == &m_soListens[pContext->GetIndex()])
if(pv == &m_soListen)
return TRUE;
else if(pv == this)
{
ReleaseGCSocketObj(FALSE);
::ReadTimer(m_fdGCTimer);
return FALSE;
}
if(!(events & _EPOLL_ALL_ERROR_EVENTS))
DetectConnection(pv);
@@ -819,25 +721,26 @@ BOOL CUdpServer::OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT
return FALSE;
}
VOID CUdpServer::OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT events, BOOL rs)
VOID CUdpServer::OnAfterProcessIo(PVOID pv, UINT events, BOOL rs)
{
}
VOID CUdpServer::OnCommand(const TDispContext* pContext, TDispCommand* pCmd)
VOID CUdpServer::OnCommand(TDispCommand* pCmd)
{
CONNID dwConnID = (CONNID)(pCmd->wParam);
switch(pCmd->type)
{
case DISP_CMD_SEND:
HandleCmdSend(dwConnID, (int)(pCmd->lParam));
HandleCmdSend((CONNID)(pCmd->wParam), (int)(pCmd->lParam));
break;
case DISP_CMD_RECEIVE:
HandleCmdReceive((CONNID)(pCmd->wParam), (int)(pCmd->lParam));
break;
case DISP_CMD_DISCONNECT:
HandleCmdDisconnect(dwConnID, (BOOL)pCmd->lParam);
HandleCmdDisconnect((CONNID)(pCmd->wParam), (BOOL)pCmd->lParam);
break;
case DISP_CMD_TIMEOUT:
HandleCmdTimeout(dwConnID);
HandleCmdTimeout((CONNID)(pCmd->wParam));
break;
}
}
@@ -852,22 +755,22 @@ VOID CUdpServer::HandleCmdTimeout(CONNID dwConnID)
AddFreeSocketObj(FindSocketObj(dwConnID), SCF_CLOSE, SO_UNKNOWN, 0, FALSE);
}
BOOL CUdpServer::OnReadyRead(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CUdpServer::OnReadyRead(PVOID pv, UINT events)
{
return HandleReceive(pContext, RETRIVE_EVENT_FLAG_H(events));
return HandleReceive(RETRIVE_EVENT_FLAG_H(events));
}
BOOL CUdpServer::OnReadyWrite(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CUdpServer::OnReadyWrite(PVOID pv, UINT events)
{
return HandleSend(pContext, RETRIVE_EVENT_FLAG_H(events));
return HandleSend(RETRIVE_EVENT_FLAG_H(events));
}
BOOL CUdpServer::OnHungUp(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CUdpServer::OnHungUp(PVOID pv, UINT events)
{
return HandleClose(nullptr, SO_CLOSE, 0);
}
BOOL CUdpServer::OnError(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CUdpServer::OnError(PVOID pv, UINT events)
{
return HandleClose(nullptr, SO_CLOSE, -1);
}
@@ -893,7 +796,7 @@ BOOL CUdpServer::HandleClose(TUdpSocketObj* pSocketObj, EnSocketOperation enOper
}
if(iErrorCode == -1)
iErrorCode = ::SSO_GetError(m_soListens[pSocketObj->index]);
iErrorCode = ::SSO_GetError(m_soListen);
EnSocketCloseFlag enFlag = IS_NO_ERROR(iErrorCode) ? SCF_CLOSE : SCF_ERROR;
@@ -902,18 +805,17 @@ BOOL CUdpServer::HandleClose(TUdpSocketObj* pSocketObj, EnSocketOperation enOper
return FALSE;
}
BOOL CUdpServer::HandleReceive(const TDispContext* pContext, int flag)
BOOL CUdpServer::HandleReceive(int flag)
{
int idx = pContext->GetIndex();
CBufferPtr& buffer = m_rcBuffers[idx];
int iBufferLen = (int)buffer.Size();
while(TRUE)
{
HP_SOCKADDR addr;
socklen_t dwAddrLen = (socklen_t)addr.AddrSize();
int rc = (int)recvfrom(m_soListens[idx], buffer.Ptr(), iBufferLen, MSG_TRUNC, addr.Addr(), &dwAddrLen);
TItemPtr itPtr(m_bfObjPool, m_bfObjPool.PickFreeItem());
int iBufferLen = itPtr->Capacity();
int rc = (int)recvfrom(m_soListen, itPtr->Ptr(), iBufferLen, MSG_TRUNC, addr.Addr(), &dwAddrLen);
if(rc >= 0)
{
@@ -924,12 +826,11 @@ BOOL CUdpServer::HandleReceive(const TDispContext* pContext, int flag)
if(rc > iBufferLen)
continue;
if((dwConnID = HandleAccept(pContext, addr)) == 0)
if((dwConnID = HandleAccept(addr)) == 0)
continue;
}
TUdpSocketObj* pSocketObj = FindSocketObj(dwConnID);
ASSERT(pSocketObj->index == idx);
if(!TUdpSocketObj::IsValid(pSocketObj))
continue;
@@ -946,19 +847,25 @@ BOOL CUdpServer::HandleReceive(const TDispContext* pContext, int flag)
continue;
}
if(::IsUdpCloseNotify(buffer.Ptr(), rc))
if(::IsUdpCloseNotify(itPtr->Ptr(), rc))
{
AddFreeSocketObj(pSocketObj, SCF_CLOSE, SO_CLOSE, SE_OK, FALSE);
continue;
}
if(TRIGGER(FireReceive(pSocketObj, buffer.Ptr(), rc)) == HR_ERROR)
itPtr->Increase(rc);
{
TRACE("<S-CNNID: %zu> OnReceive() event return 'HR_ERROR', connection will be closed !", dwConnID);
CLocalSafeCounter localcounter(*pSocketObj);
CReentrantReadLock locallock(pSocketObj->lcIo);
AddFreeSocketObj(pSocketObj, SCF_ERROR, SO_RECEIVE, ENSURE_ERROR_CANCELLED);;
continue;
if(!TUdpSocketObj::IsValid(pSocketObj))
continue;
pSocketObj->recvQueue.PushBack(itPtr.Detach());
}
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_RECEIVE, dwConnID, flag));
}
else if(rc == SOCKET_ERROR)
{
@@ -978,20 +885,32 @@ BOOL CUdpServer::HandleReceive(const TDispContext* pContext, int flag)
return TRUE;
}
CONNID CUdpServer::HandleAccept(const TDispContext* pContext, HP_SOCKADDR& addr)
CONNID CUdpServer::HandleAccept(HP_SOCKADDR& addr)
{
int idx = pContext->GetIndex();
CONNID dwConnID = 0;
TUdpSocketObj* pSocketObj = nullptr;
if(!m_bfActiveSockets.AcquireLock(dwConnID))
{
::SendUdpCloseNotify(m_soListens[idx], addr);
return 0;
}
CCriSecLock locallock(m_csAccept);
pSocketObj = GetFreeSocketObj(dwConnID);
AddClientSocketObj(idx, dwConnID, pSocketObj, addr);
dwConnID = FindConnectionID(&addr);
if(dwConnID != 0)
return dwConnID;
else
{
if(!m_bfActiveSockets.AcquireLock(dwConnID))
{
::SendUdpCloseNotify(m_soListen, addr);
return 0;
}
pSocketObj = GetFreeSocketObj(dwConnID);
pSocketObj->lcIo.WaitToWrite();
AddClientSocketObj(dwConnID, pSocketObj, addr);
}
}
if(TriggerFireAccept(pSocketObj) == HR_ERROR)
{
@@ -999,6 +918,8 @@ CONNID CUdpServer::HandleAccept(const TDispContext* pContext, HP_SOCKADDR& addr)
dwConnID = 0;
}
pSocketObj->lcIo.WriteDone();
return dwConnID;
}
@@ -1011,18 +932,71 @@ void CUdpServer::HandleZeroBytes(TUdpSocketObj* pSocketObj)
#if defined(DEBUG_TRACE)
int rc = (int)
#endif
sendto(m_soListens[pSocketObj->index], nullptr, 0, 0, pSocketObj->remoteAddr.Addr(), pSocketObj->remoteAddr.AddrSize());
sendto(m_soListen, nullptr, 0, 0, pSocketObj->remoteAddr.Addr(), pSocketObj->remoteAddr.AddrSize());
TRACE("<S-CNNID: %zu> send 0 bytes (detect ack package - %s)", pSocketObj->connID, IS_HAS_ERROR(rc) ? "fail" : "succ");
}
BOOL CUdpServer::HandleSend(const TDispContext* pContext, int flag)
VOID CUdpServer::HandleCmdReceive(CONNID dwConnID, int flag)
{
CSendQueue& quSend = m_quSends[pContext->GetIndex()];
CONNID dwConnID = 0;
TUdpSocketObj* pSocketObj = FindSocketObj(dwConnID);
while(quSend.PopFront(&dwConnID))
HandleCmdSend(dwConnID, flag);
if(!TUdpSocketObj::IsValid(pSocketObj))
return;
if(pSocketObj->recvQueue.IsEmpty())
return;
BOOL bCancel = FALSE;
{
CLocalSafeCounter localcounter(*pSocketObj);
CReentrantReadLock locallock(pSocketObj->lcIo);
if(!TUdpSocketObj::IsValid(pSocketObj))
return;
if(pSocketObj->recvQueue.IsEmpty())
return;
pSocketObj->detectFails = 0;
if(m_bMarkSilence) pSocketObj->activeTime = ::TimeGetTime();
int reads = flag ? -1 : MAX_CONTINUE_READS;
for(int i = 0; i < reads || reads < 0; i++)
{
TItemPtr itPtr(m_bfObjPool);
if(!pSocketObj->recvQueue.PopFront(&itPtr.PtrRef()))
break;
if(TRIGGER(FireReceive(pSocketObj, itPtr->Ptr(), itPtr->Size())) == HR_ERROR)
{
TRACE("<S-CNNID: %zu> OnReceive() event return 'HR_ERROR', connection will be closed !", dwConnID);
bCancel = TRUE;
break;
}
}
}
if(bCancel)
AddFreeSocketObj(pSocketObj, SCF_ERROR, SO_RECEIVE, ENSURE_ERROR_CANCELLED);
else
{
if(TUdpSocketObj::IsValid(pSocketObj) && pSocketObj->HasRecvData())
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_RECEIVE, dwConnID, flag));
}
}
BOOL CUdpServer::HandleSend(int flag)
{
m_ioDispatcher.ModFD(m_soListen, _EPOLL_READ_EVENTS | EPOLLET, TO_PVOID(&m_soListen));
CONNID dwConnID = 0;
while(m_quSend.PopFront(&dwConnID))
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_SEND, dwConnID));
return TRUE;
}
@@ -1034,47 +1008,63 @@ VOID CUdpServer::HandleCmdSend(CONNID dwConnID, int flag)
if(!TUdpSocketObj::IsValid(pSocketObj) || !pSocketObj->IsPending())
return;
BOOL bClose = FALSE;
BOOL bBlocked = FALSE;
int writes = flag ? -1 : MAX_CONTINUE_WRITES;
TBufferObjList& sndBuff = pSocketObj->sndBuff;
TItemPtr itPtr(sndBuff);
for(int i = 0; i < writes || writes < 0; i++)
{
{
CReentrantCriSecLock locallock(pSocketObj->csSend);
itPtr = sndBuff.PopFront();
}
CLocalSafeCounter localcounter(*pSocketObj);
CReentrantReadLock locallock(pSocketObj->lcSend);
if(!itPtr.IsValid())
break;
ASSERT(!itPtr->IsEmpty());
if(!SendItem(pSocketObj, itPtr, bBlocked))
if(!TUdpSocketObj::IsValid(pSocketObj) || !pSocketObj->IsPending())
return;
if(bBlocked)
for(int i = 0; i < writes || writes < 0; i++)
{
{
CReentrantCriSecLock locallock(pSocketObj->csSend);
sndBuff.PushFront(itPtr.Detach());
CCriSecLock locallock(pSocketObj->csSend);
itPtr = sndBuff.PopFront();
}
m_quSends[pSocketObj->index].PushBack(dwConnID);
if(!itPtr.IsValid())
break;
break;
ASSERT(!itPtr->IsEmpty());
if(!SendItem(pSocketObj, itPtr, bBlocked))
{
bClose = TRUE;
break;
}
if(bBlocked)
{
{
CCriSecLock locallock(pSocketObj->csSend);
sndBuff.PushFront(itPtr.Detach());
}
m_quSend.PushBack(dwConnID);
m_ioDispatcher.ModFD(m_soListen, EPOLLOUT | _EPOLL_READ_EVENTS | EPOLLET, TO_PVOID(&m_soListen));
break;
}
}
}
if(!bBlocked && pSocketObj->IsPending())
VERIFY(m_ioDispatcher.SendCommandByIndex(pSocketObj->index, DISP_CMD_SEND, dwConnID));
if(bClose)
HandleClose(pSocketObj, SO_SEND, ::WSAGetLastError());
else if(!bBlocked && pSocketObj->IsPending())
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_SEND, dwConnID));
}
BOOL CUdpServer::SendItem(TUdpSocketObj* pSocketObj, TItem* pItem, BOOL& bBlocked)
{
int rc = (int)sendto(m_soListens[pSocketObj->index], pItem->Ptr(), pItem->Size(), 0, pSocketObj->remoteAddr.Addr(), pSocketObj->remoteAddr.AddrSize());
int rc = (int)sendto(m_soListen, pItem->Ptr(), pItem->Size(), 0, pSocketObj->remoteAddr.Addr(), pSocketObj->remoteAddr.AddrSize());
if(rc > 0)
{
@@ -1092,7 +1082,7 @@ BOOL CUdpServer::SendItem(TUdpSocketObj* pSocketObj, TItem* pItem, BOOL& bBlocke
if(code == ERROR_WOULDBLOCK)
bBlocked = TRUE;
else if(!HandleClose(pSocketObj, SO_SEND, code))
else
return FALSE;
}
else
@@ -1194,7 +1184,7 @@ int CUdpServer::SendInternal(TUdpSocketObj* pSocketObj, TItemPtr& itPtr)
{
CLocalSafeCounter localcounter(*pSocketObj);
CReentrantCriSecLock locallock(pSocketObj->csSend);
CCriSecLock locallock(pSocketObj->csSend);
if(!TUdpSocketObj::IsValid(pSocketObj))
return ERROR_OBJECT_NOT_FOUND;
@@ -1205,8 +1195,8 @@ int CUdpServer::SendInternal(TUdpSocketObj* pSocketObj, TItemPtr& itPtr)
ASSERT(pSocketObj->sndBuff.Length() > 0);
}
if(!bPending && pSocketObj->IsPending())
VERIFY(m_ioDispatcher.SendCommandByIndex(pSocketObj->index, DISP_CMD_SEND, pSocketObj->connID));
if(!bPending)
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_SEND, pSocketObj->connID));
return NO_ERROR;
}
@@ -1220,7 +1210,7 @@ void CUdpServer::DetectConnection(PVOID pv)
CUdpServer* pServer = (CUdpServer*)pSocketObj->pHolder;
if(pSocketObj->detectFails >= pServer->m_dwDetectAttempts)
VERIFY(m_ioDispatcher.SendCommandByIndex(pSocketObj->index, DISP_CMD_TIMEOUT, pSocketObj->connID));
VERIFY(m_ioDispatcher.SendCommand(DISP_CMD_TIMEOUT, pSocketObj->connID));
else
::InterlockedIncrement(&pSocketObj->detectFails);

View File

@@ -31,9 +31,8 @@
class CUdpServer : public IUdpServer, private CIOHandler
{
using CWorkerThread = CThread<CUdpServer, VOID, UINT>;
using CSendQueue = CCASSimpleQueue<CONNID>;
using CSendQueuesPtr = unique_ptr<CSendQueue[]>;
using CWorkerThread = CThread<CUdpServer, VOID, UINT>;
using CSendQueue = CCASSimpleQueue<CONNID>;
public:
virtual BOOL Start (LPCTSTR lpszBindAddress, USHORT usPort);
@@ -62,25 +61,25 @@ public:
virtual LPCTSTR GetLastErrorDesc () {return ::GetSocketErrorDesc(m_enLastError);}
private:
virtual BOOL OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual VOID OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT events, BOOL rs) override;
virtual VOID OnCommand(const TDispContext* pContext, TDispCommand* pCmd) override;
virtual BOOL OnReadyRead(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnReadyWrite(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnHungUp(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual BOOL OnError(const TDispContext* pContext, PVOID pv, UINT events) override;
virtual VOID OnDispatchThreadStart(THR_ID tid) override;
virtual VOID OnDispatchThreadEnd(THR_ID tid) override;
virtual BOOL OnBeforeProcessIo(PVOID pv, UINT events) override;
virtual VOID OnAfterProcessIo(PVOID pv, UINT events, BOOL rs) override;
virtual VOID OnCommand(TDispCommand* pCmd) override;
virtual BOOL OnReadyRead(PVOID pv, UINT events) override;
virtual BOOL OnReadyWrite(PVOID pv, UINT events) override;
virtual BOOL OnHungUp(PVOID pv, UINT events) override;
virtual BOOL OnError(PVOID pv, UINT events) override;
virtual VOID OnDispatchThreadStart(THR_ID tid) override;
virtual VOID OnDispatchThreadEnd(THR_ID tid) override;
public:
virtual BOOL IsSecure () {return FALSE;}
virtual BOOL IsSecure () {return FALSE;}
virtual BOOL SetConnectionExtra(CONNID dwConnID, PVOID pExtra);
virtual BOOL GetConnectionExtra(CONNID dwConnID, PVOID* ppExtra);
virtual void SetReuseAddressPolicy (EnReuseAddressPolicy enReusePolicy) {ENSURE_HAS_STOPPED(); ASSERT(m_enReusePolicy == enReusePolicy);}
virtual void SetSendPolicy (EnSendPolicy enSendPolicy) {ENSURE_HAS_STOPPED(); ASSERT(m_enSendPolicy == enSendPolicy);}
virtual void SetOnSendSyncPolicy (EnOnSendSyncPolicy enOnSendSyncPolicy) {ENSURE_HAS_STOPPED(); ASSERT(m_enOnSendSyncPolicy == enOnSendSyncPolicy);}
virtual void SetReuseAddressPolicy (EnReuseAddressPolicy enReusePolicy) {ENSURE_HAS_STOPPED(); m_enReusePolicy = enReusePolicy;}
virtual void SetSendPolicy (EnSendPolicy enSendPolicy) {ENSURE_HAS_STOPPED(); m_enSendPolicy = enSendPolicy;}
virtual void SetOnSendSyncPolicy (EnOnSendSyncPolicy enOnSendSyncPolicy) {ENSURE_HAS_STOPPED(); m_enOnSendSyncPolicy = enOnSendSyncPolicy;}
virtual void SetMaxConnectionCount (DWORD dwMaxConnectionCount) {ENSURE_HAS_STOPPED(); m_dwMaxConnectionCount = dwMaxConnectionCount;}
virtual void SetWorkerThreadCount (DWORD dwWorkerThreadCount) {ENSURE_HAS_STOPPED(); m_dwWorkerThreadCount = dwWorkerThreadCount;}
virtual void SetFreeSocketObjLockTime (DWORD dwFreeSocketObjLockTime) {ENSURE_HAS_STOPPED(); m_dwFreeSocketObjLockTime = dwFreeSocketObjLockTime;}
@@ -154,10 +153,8 @@ protected:
virtual void PrepareStart();
virtual void Reset();
virtual void OnWorkerThreadStart(THR_ID tid) {}
virtual void OnWorkerThreadEnd(THR_ID tid) {}
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE);
virtual void OnWorkerThreadStart(THR_ID tid) {}
virtual void OnWorkerThreadEnd(THR_ID tid) {}
TUdpSocketObj* FindSocketObj(CONNID dwConnID);
int SendInternal(TUdpSocketObj* pSocketObj, TItemPtr& itPtr);
@@ -189,7 +186,6 @@ private:
void WaitForClientSocketClose();
void ReleaseClientSocket();
void ReleaseFreeSocket();
void ClearSendQueues();
void WaitForWorkerThreadEnd();
TUdpSocketObj* GetFreeSocketObj(CONNID dwConnID);
@@ -198,36 +194,38 @@ private:
void AddFreeSocketObj(TUdpSocketObj* pSocketObj, EnSocketCloseFlag enFlag = SCF_NONE, EnSocketOperation enOperation = SO_UNKNOWN, int iErrorCode = 0, BOOL bNotify = TRUE);
void DeleteSocketObj(TUdpSocketObj* pSocketObj);
BOOL InvalidSocketObj(TUdpSocketObj* pSocketObj);
void AddClientSocketObj(int idx, CONNID dwConnID, TUdpSocketObj* pSocketObj, const HP_SOCKADDR& remoteAddr);
void ReleaseGCSocketObj(BOOL bForce = FALSE);
void AddClientSocketObj(CONNID dwConnID, TUdpSocketObj* pSocketObj, const HP_SOCKADDR& remoteAddr);
void CloseClientSocketObj(TUdpSocketObj* pSocketObj, EnSocketCloseFlag enFlag = SCF_NONE, EnSocketOperation enOperation = SO_UNKNOWN, int iErrorCode = 0, BOOL bNotify = TRUE);
EnHandleResult TriggerFireAccept(TUdpSocketObj* pSocketObj);
private:
VOID HandleCmdSend (CONNID dwConnID, int flag);
VOID HandleCmdReceive (CONNID dwConnID, int flag);
VOID HandleCmdDisconnect(CONNID dwConnID, BOOL bForce);
VOID HandleCmdTimeout (CONNID dwConnID);
CONNID HandleAccept (const TDispContext* pContext, HP_SOCKADDR& addr);
BOOL HandleReceive (const TDispContext* pContext, int flag = 0);
BOOL HandleSend (const TDispContext* pContext, int flag = 0);
CONNID HandleAccept (HP_SOCKADDR& addr);
BOOL HandleReceive (int flag = 0);
BOOL HandleSend (int flag = 0);
BOOL HandleClose (TUdpSocketObj* pSocketObj, EnSocketOperation enOperation, int iErrorCode);
void HandleZeroBytes (TUdpSocketObj* pSocketObj);
BOOL SendItem (TUdpSocketObj* pSocketObj, TItem* pItem, BOOL& bBlocked);
void DetectConnection (PVOID pv);
BOOL IsNeedDetectConnection () const {return m_dwDetectAttempts > 0 && m_dwDetectInterval > 0;}
BOOL IsNeedDetectConnection () {return m_dwDetectAttempts > 0 && m_dwDetectInterval > 0;}
public:
CUdpServer(IUdpServerListener* pListener)
: m_pListener (pListener)
, m_soListen (INVALID_SOCKET)
, m_enLastError (SE_OK)
, m_enState (SS_STOPPED)
, m_fdGCTimer (INVALID_FD)
, m_enSendPolicy (SP_PACK)
, m_enOnSendSyncPolicy (OSSP_RECEIVE)
, m_enReusePolicy (RAP_ADDR_AND_PORT)
, m_enOnSendSyncPolicy (OSSP_NONE)
, m_enReusePolicy (RAP_ADDR_ONLY)
, m_dwMaxConnectionCount (DEFAULT_CONNECTION_COUNT)
, m_dwWorkerThreadCount (DEFAULT_WORKER_THREAD_COUNT)
, m_dwFreeSocketObjLockTime (DEFAULT_FREE_SOCKETOBJ_LOCK_TIME)
@@ -273,17 +271,15 @@ private:
CSEM m_evWait;
IUdpServerListener* m_pListener;
ListenSocketsPtr m_soListens;
SOCKET m_soListen;
EnServiceState m_enState;
EnSocketError m_enLastError;
CReceiveBuffersPtr m_rcBuffers;
CPrivateHeap m_phSocket;
CSpinGuard m_csState;
FD m_fdGCTimer;
CCriSec m_csAccept;
TUdpSocketObjPtrPool m_bfActiveSockets;
@@ -293,7 +289,7 @@ private:
TUdpSocketObjPtrList m_lsFreeSocket;
TUdpSocketObjPtrQueue m_lsGCSocket;
CSendQueuesPtr m_quSends;
CSendQueue m_quSend;
CIODispatcher m_ioDispatcher;
};

View File

@@ -208,9 +208,8 @@ void CBufferPool::PutFreeBuffer(TBuffer* pBuffer)
{
m_itPool.PutFreeItem(pBuffer->items);
#ifndef USE_EXTERNAL_GC
ReleaseGCBuffer();
#endif
if(!m_lsFreeBuffer.TryPut(pBuffer))
m_lsGCBuffer.PushBack(pBuffer);
}

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include "Singleton.h"
#include "STLHelper.h"
#include "RingBuffer.h"
@@ -800,6 +800,7 @@ public:
void Prepare ();
void Clear ();
private:
void ReleaseGCBuffer (BOOL bForce = FALSE);
public:

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include <memory.h>
#include <malloc.h>

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include "Singleton.h"
#include "FuncHelper.h"

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include "Singleton.h"
#include "FuncHelper.h"
#include "PollHelper.h"

View File

@@ -23,8 +23,8 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "hpsocket/GlobalErrno.h"
#include "../hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalErrno.h"
#include "SysHelper.h"
#include <stdlib.h>
@@ -102,7 +102,7 @@ using namespace std;
#define IS_OK(rs) ((BOOL)(rs))
#define IS_NOT_OK(rs) (!IS_OK(rs))
#define IS_ERROR(code) (::GetLastError() == (code))
#define IS_ERROR(code) (::GetLastError() == code)
#define CONTINUE_IF_ERROR(code) {if(IS_ERROR(code)) continue;}
#define BREAK_IF_ERROR(code) {if(IS_ERROR(code)) break;}
@@ -133,7 +133,7 @@ inline void PrintError(LPCSTR subject) {perror(subject);}
#define EXECUTE_RESTORE_ERROR(expr) {int __le_ = ::GetLastError(); (expr); ::SetLastError(__le_);}
#define EXECUTE_RESTORE_ERROR_RT(T, expr)\
({int __le_ = ::GetLastError(); T __rs_ = (expr); ::SetLastError(__le_); __rs_;})
#define ENSURE_ERROR(def_code) ({int __le_ = ::GetLastError(); if(__le_ == NO_ERROR) __le_ = (def_code); __le_;})
#define ENSURE_ERROR(def_code) ({int __le_ = ::GetLastError(); if(__le_ == 0) __le_ = (def_code); __le_;})
#define ENSURE_ERROR_CANCELLED ENSURE_ERROR(ERROR_CANCELLED)
#define TRIGGER(expr) EXECUTE_RESET_ERROR((expr))
@@ -171,9 +171,6 @@ inline void PrintError(LPCSTR subject) {perror(subject);}
#define TO_PVOID(v) ((PVOID)(UINT_PTR)(v))
#define FROM_PVOID(T, pv) ((T)(UINT_PTR)(pv))
#define IS_NULL(v) ((v) == nullptr)
#define IS_NOT_NULL(v) (!IS_NULL(v))
#define stricmp strcasecmp
#define strnicmp strncasecmp
#define wcsicmp wcscasecmp

View File

@@ -23,8 +23,8 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "hpsocket/GlobalErrno.h"
#include "../hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalErrno.h"
#include "Singleton.h"
#include "STLHelper.h"
#include "FuncHelper.h"

View File

@@ -27,10 +27,10 @@
#include <signal.h>
#include <pthread.h>
volatile UINT CIODispatcher::sm_uiNum = MAXUINT;
volatile UINT CIODispatcher::sm_uiNum = 0;
LPCTSTR CIODispatcher::WORKER_THREAD_PREFIX = _T("io-disp-");
BOOL CIODispatcher::Start(IIOHandler* pHandler, int iWorkerMaxEvents, int iWorkers)
BOOL CIODispatcher::Start(IIOHandler* pHandler, int iWorkerMaxEvents, int iWorkers, LLONG llTimerInterval)
{
ASSERT_CHECK_EINVAL(pHandler && iWorkerMaxEvents >= 0 && iWorkers >= 0);
CHECK_ERROR(!HasStarted(), ERROR_INVALID_STATE);
@@ -42,42 +42,44 @@ BOOL CIODispatcher::Start(IIOHandler* pHandler, int iWorkerMaxEvents, int iWorke
m_iWorkers = iWorkers;
m_pHandler = pHandler;
m_epoll = epoll_create1(EPOLL_CLOEXEC);
CHECK_ERROR_FD(m_epoll);
m_evCmd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
if(IS_INVALID_FD(m_evCmd))
goto START_ERROR;
if(!VERIFY(AddFD(m_evCmd, EPOLLIN | EPOLLET, &m_evCmd)))
goto START_ERROR;
m_evExit = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC | EFD_SEMAPHORE);
if(IS_INVALID_FD(m_evExit))
goto START_ERROR;
m_pContexts = make_unique<TDispContext[]>(m_iWorkers);
if(!VERIFY(AddFD(m_evExit, EPOLLIN, &m_evExit)))
goto START_ERROR;
if(llTimerInterval > 0)
{
m_evTimer = AddTimer(llTimerInterval, &m_evTimer);
if(IS_INVALID_FD(m_evTimer))
goto START_ERROR;
}
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGPIPE);
VERIFY_IS_NO_ERROR(pthread_sigmask(SIG_BLOCK, &ss, nullptr));
m_pWorkers = make_unique<CWorkerThread[]>(m_iWorkers);
for(int i = 0; i < m_iWorkers; i++)
{
TDispContext& ctx = m_pContexts[i];
ctx.m_iIndex = i;
ctx.m_epoll = epoll_create1(EPOLL_CLOEXEC);
CHECK_ERROR_FD(ctx.m_epoll);
ctx.m_evCmd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
if(IS_INVALID_FD(ctx.m_evCmd))
goto START_ERROR;
if(!VERIFY(AddFD(i, ctx.m_evCmd, EPOLLIN | EPOLLET, &ctx.m_evCmd)))
goto START_ERROR;
if(!VERIFY(AddFD(i, m_evExit, EPOLLIN, &m_evExit)))
goto START_ERROR;
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGPIPE);
VERIFY_IS_NO_ERROR(pthread_sigmask(SIG_BLOCK, &ss, nullptr));
ctx.m_pWorker = make_unique<CWorkerThread>();
if(!VERIFY(ctx.m_pWorker->Start(this, &CIODispatcher::WorkerProc, &ctx)))
if(!VERIFY(m_pWorkers[i].Start(this, &CIODispatcher::WorkerProc)))
goto START_ERROR;
}
@@ -94,38 +96,36 @@ BOOL CIODispatcher::Stop(BOOL bCheck)
BOOL isOK = TRUE;
if(m_pContexts)
if(m_pWorkers)
{
isOK &= IS_NO_ERROR(eventfd_write(m_evExit, m_iWorkers));
for(int i = 0; i < m_iWorkers; i++)
{
TDispContext& ctx = m_pContexts[i];
isOK &= m_pWorkers[i].Join();
}
if(ctx.m_pWorker)
isOK &= ctx.m_pWorker->Join();
if(!m_queue.IsEmpty())
{
TDispCommand* pCmd = nullptr;
if(!ctx.m_queue.IsEmpty())
{
TDispCommand* pCmd = nullptr;
while(m_queue.PopFront(&pCmd))
TDispCommand::Destruct(pCmd);
while(ctx.m_queue.PopFront(&pCmd))
TDispCommand::Destruct(pCmd);
VERIFY(ctx.m_queue.IsEmpty());
}
if(IS_VALID_FD(ctx.m_evCmd))
isOK &= IS_NO_ERROR(close(ctx.m_evCmd));
if(IS_VALID_FD(ctx.m_epoll))
isOK &= IS_NO_ERROR(close(ctx.m_epoll));
}
VERIFY(m_queue.IsEmpty());
}
if(IS_VALID_FD(m_evExit))
isOK &= IS_NO_ERROR(close(m_evExit));
if(IS_VALID_FD(m_evCmd))
isOK &= IS_NO_ERROR(close(m_evCmd));
if(IS_VALID_FD(m_evTimer))
isOK &= IS_NO_ERROR(close(m_evTimer));
if(IS_VALID_FD(m_epoll))
isOK &= IS_NO_ERROR(close(m_epoll));
Reset();
return isOK;
@@ -133,78 +133,54 @@ BOOL CIODispatcher::Stop(BOOL bCheck)
VOID CIODispatcher::Reset()
{
m_uiSeq = MAXUINT;
m_uiSeq = 0;
m_iWorkers = 0;
m_iMaxEvents= 0;
m_evExit = INVALID_FD;
m_pHandler = nullptr;
m_pContexts = nullptr;
m_pWorkers = nullptr;
m_epoll = INVALID_FD;
m_evCmd = INVALID_FD;
m_evExit = INVALID_FD;
m_evTimer = INVALID_FD;
}
VOID CIODispatcher::MakePrefix()
void CIODispatcher::MakePrefix()
{
UINT uiNumber = ::InterlockedIncrement(&sm_uiNum);
m_strPrefix.Format(_T("%s%u-"), WORKER_THREAD_PREFIX, uiNumber);
}
TDispContext& CIODispatcher::GetContext(int idx, FD fd)
BOOL CIODispatcher::SendCommand(USHORT t, UINT_PTR wp, UINT_PTR lp)
{
if(idx < 0) idx = fd;
ASSERT(idx >= 0);
if(idx >= m_iWorkers) idx %= m_iWorkers;
return m_pContexts[idx];
return SendCommand(TDispCommand::Construct(t, wp, lp));
}
BOOL CIODispatcher::SendCommandByIndex(int idx, USHORT t, UINT_PTR wp, UINT_PTR lp)
BOOL CIODispatcher::SendCommand(TDispCommand* pCmd)
{
return SendCommandByIndex(idx, TDispCommand::Construct(t, wp, lp));
m_queue.PushBack(pCmd);
return VERIFY_IS_NO_ERROR(eventfd_write(m_evCmd, 1));
}
BOOL CIODispatcher::SendCommandByIndex(int idx, TDispCommand* pCmd)
BOOL CIODispatcher::CtlFD(FD fd, int op, UINT mask, PVOID pv)
{
TDispContext& ctx = GetContextByIndex(idx);
return SendCommand(ctx, pCmd);
}
BOOL CIODispatcher::SendCommandByFD(FD fd, USHORT t, UINT_PTR wp, UINT_PTR lp)
{
return SendCommandByFD(fd, TDispCommand::Construct(t, wp, lp));
}
BOOL CIODispatcher::SendCommandByFD(FD fd, TDispCommand* pCmd)
{
TDispContext& ctx = GetContextByFD(fd);
return SendCommand(ctx, pCmd);
}
BOOL CIODispatcher::SendCommand(TDispContext& ctx, TDispCommand* pCmd)
{
ctx.m_queue.PushBack(pCmd);
return VERIFY_IS_NO_ERROR(eventfd_write(ctx.m_evCmd, 1));
}
BOOL CIODispatcher::CtlFD(int idx, FD fd, int op, UINT mask, PVOID pv)
{
const TDispContext& ctx = GetContext(idx, fd);
epoll_event evt = {mask, pv};
return IS_NO_ERROR(epoll_ctl(ctx.m_epoll, op, fd, &evt));
return IS_NO_ERROR(epoll_ctl(m_epoll, op, fd, &evt));
}
int CIODispatcher::WorkerProc(TDispContext* pContext)
int CIODispatcher::WorkerProc(PVOID pv)
{
::SetSequenceThreadName(SELF_THREAD_ID, m_strPrefix, m_uiSeq);
m_pHandler->OnDispatchThreadStart(SELF_THREAD_ID);
BOOL bRun = TRUE;
unique_ptr<epoll_event[]> pEvents = make_unique<epoll_event[]>(m_iMaxEvents);
BOOL bRun = TRUE;
unique_ptr<epoll_event[]> pEvents = make_unique<epoll_event[]>(m_iMaxEvents);
while(bRun)
{
int rs = NO_EINTR_INT(epoll_pwait(pContext->m_epoll, pEvents.get(), m_iMaxEvents, INFINITE, nullptr));
int rs = NO_EINTR_INT(epoll_pwait(m_epoll, pEvents.get(), m_iMaxEvents, INFINITE, nullptr));
if(rs <= TIMEOUT)
ERROR_ABORT();
@@ -214,12 +190,14 @@ int CIODispatcher::WorkerProc(TDispContext* pContext)
UINT events = pEvents[i].events;
PVOID ptr = pEvents[i].data.ptr;
if(ptr == &pContext->m_evCmd)
ProcessCommand(pContext, events);
if(ptr == &m_evCmd)
ProcessCommand(events);
else if(ptr == &m_evTimer)
ProcessTimer(events);
else if(ptr == &m_evExit)
bRun = ProcessExit(pContext, events);
bRun = ProcessExit(events);
else
ProcessIo(pContext, ptr, events);
ProcessIo(ptr, events);
}
}
@@ -228,7 +206,7 @@ int CIODispatcher::WorkerProc(TDispContext* pContext)
return 0;
}
BOOL CIODispatcher::ProcessCommand(TDispContext* pContext, UINT events)
BOOL CIODispatcher::ProcessCommand(UINT events)
{
if(events & _EPOLL_ALL_ERROR_EVENTS)
ERROR_ABORT();
@@ -240,7 +218,7 @@ BOOL CIODispatcher::ProcessCommand(TDispContext* pContext, UINT events)
eventfd_t v;
int rs = eventfd_read(pContext->m_evCmd, &v);
int rs = eventfd_read(m_evCmd, &v);
if(IS_NO_ERROR(rs))
{
@@ -248,9 +226,9 @@ BOOL CIODispatcher::ProcessCommand(TDispContext* pContext, UINT events)
TDispCommand* pCmd = nullptr;
while(pContext->m_queue.PopFront(&pCmd))
while(m_queue.PopFront(&pCmd))
{
m_pHandler->OnCommand(pContext, pCmd);
m_pHandler->OnCommand(pCmd);
TDispCommand::Destruct(pCmd);
}
}
@@ -264,7 +242,26 @@ BOOL CIODispatcher::ProcessCommand(TDispContext* pContext, UINT events)
return isOK;
}
BOOL CIODispatcher::ProcessExit(const TDispContext* pContext, UINT events)
BOOL CIODispatcher::ProcessTimer(UINT events)
{
if(events & _EPOLL_ALL_ERROR_EVENTS)
ERROR_ABORT();
if(!(events & EPOLLIN))
return TRUE;
BOOL isOK = FALSE;
ULLONG ullExpirations;
if(::ReadTimer(m_evTimer, &ullExpirations, &isOK) && isOK)
m_pHandler->OnTimer(ullExpirations);
else
ASSERT(IS_WOULDBLOCK_ERROR());
return isOK;
}
BOOL CIODispatcher::ProcessExit(UINT events)
{
if(events & _EPOLL_ALL_ERROR_EVENTS)
ERROR_ABORT();
@@ -289,40 +286,40 @@ BOOL CIODispatcher::ProcessExit(const TDispContext* pContext, UINT events)
return bRun;
}
BOOL CIODispatcher::ProcessIo(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CIODispatcher::ProcessIo(PVOID pv, UINT events)
{
if(!m_pHandler->OnBeforeProcessIo(pContext, pv, events))
if(!m_pHandler->OnBeforeProcessIo(pv, events))
return FALSE;
BOOL rs = DoProcessIo(pContext, pv, events);
m_pHandler->OnAfterProcessIo(pContext, pv, events, rs);
BOOL rs = DoProcessIo(pv, events);
m_pHandler->OnAfterProcessIo(pv, events, rs);
return rs;
}
BOOL CIODispatcher::DoProcessIo(const TDispContext* pContext, PVOID pv, UINT events)
BOOL CIODispatcher::DoProcessIo(PVOID pv, UINT events)
{
if(events & EPOLLERR)
return m_pHandler->OnError(pContext, pv, events);
if((events & EPOLLPRI) && !m_pHandler->OnReadyPrivilege(pContext, pv, events))
return m_pHandler->OnError(pv, events);
if((events & EPOLLPRI) && !m_pHandler->OnReadyPrivilege(pv, events))
return FALSE;
if((events & EPOLLIN) && !m_pHandler->OnReadyRead(pContext, pv, events))
if((events & EPOLLIN) && !m_pHandler->OnReadyRead(pv, events))
return FALSE;
if((events & EPOLLOUT) && !m_pHandler->OnReadyWrite(pContext, pv, events))
if((events & EPOLLOUT) && !m_pHandler->OnReadyWrite(pv, events))
return FALSE;
if((events & (_EPOLL_HUNGUP_EVENTS)) && !m_pHandler->OnHungUp(pContext, pv, events))
if((events & (_EPOLL_HUNGUP_EVENTS)) && !m_pHandler->OnHungUp(pv, events))
return FALSE;
return TRUE;
}
FD CIODispatcher::AddTimer(int idx, LLONG llInterval, PVOID pv)
FD CIODispatcher::AddTimer(LLONG llInterval, PVOID pv)
{
FD fdTimer = ::CreateTimer(llInterval);
if(IS_VALID_FD(fdTimer))
{
if(!AddFD(idx, fdTimer, EPOLLIN | EPOLLET, pv))
if(!AddFD(fdTimer, EPOLLIN | EPOLLET, pv))
{
close(fdTimer);
fdTimer = INVALID_FD;
@@ -332,13 +329,13 @@ FD CIODispatcher::AddTimer(int idx, LLONG llInterval, PVOID pv)
return fdTimer;
}
BOOL CIODispatcher::DelTimer(int idx, FD fdTimer)
BOOL CIODispatcher::DelTimer(FD fdTimer)
{
BOOL isOK = FALSE;
if(IS_VALID_FD(fdTimer))
{
if(DelFD(idx, fdTimer))
if(DelFD(fdTimer))
isOK = TRUE;
close(fdTimer);

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include "Singleton.h"
#include "RingBuffer.h"
#include "Thread.h"
@@ -48,61 +48,16 @@ using namespace std;
#define _EPOLL_ALL_NORMAL_EVENTS (_EPOLL_NORMAL_RW_EVENTS | _EPOLL_ALL_ERROR_EVENTS)
#define _EPOLL_ALL_EVENTS (_EPOLL_ALL_RW_EVENTS | _EPOLL_ALL_ERROR_EVENTS)
#define DISP_EVENT_FLAG_R 0x1
#define DISP_EVENT_FLAG_W 0x2
#define DISP_EVENT_FLAG_H 0x4
#define DISP_EVENT_FLAG_R 1
#define DISP_EVENT_FLAG_W 2
#define DISP_EVENT_FLAG_H 4
#define RETRIVE_EVENT_FLAG_R(evt) ((evt) & (_EPOLL_ALL_READ_EVENTS) ? DISP_EVENT_FLAG_R : 0)
#define RETRIVE_EVENT_FLAG_W(evt) ((evt) & (_EPOLL_WRITE_EVENTS) ? DISP_EVENT_FLAG_W : 0)
#define RETRIVE_EVENT_FLAG_RW(evt) (RETRIVE_EVENT_FLAG_R(evt) | RETRIVE_EVENT_FLAG_W(evt))
#define RETRIVE_EVENT_FLAG_H(evt) ((evt) & (_EPOLL_HUNGUP_EVENTS) ? DISP_EVENT_FLAG_H : 0)
#ifndef EPOLLEXCLUSIVE
#define EPOLLEXCLUSIVE (1u << 28)
#endif
#define MAYBE_EPOLLEXCLUSIVE (::IsKernelVersionAbove(4, 5, 0) ? EPOLLEXCLUSIVE : 0)
// ------------------------------------------------------------------------------------------------------------------------------------------------------- //
struct TDispCommand;
class CIODispatcher;
struct TDispContext
{
friend class CIODispatcher;
using CCommandQueue = CCASQueue<TDispCommand>;
using CWorkerThread = CThread<CIODispatcher, TDispContext, int>;
public:
int GetIndex() const {return m_iIndex;}
THR_ID GetThreadId() const {return m_pWorker != nullptr ? m_pWorker->GetThreadID() : 0;}
public:
TDispContext() {Reset();}
~TDispContext() = default;
DECLARE_NO_COPY_CLASS(TDispContext)
private:
VOID Reset()
{
m_iIndex = -1;
m_epoll = INVALID_FD;
m_evCmd = INVALID_FD;
m_pWorker = nullptr;
}
private:
int m_iIndex;
FD m_epoll;
FD m_evCmd;
CCommandQueue m_queue;
unique_ptr<CWorkerThread> m_pWorker;
};
struct TDispCommand
{
USHORT type;
@@ -129,18 +84,20 @@ private:
class IIOHandler
{
public:
virtual VOID OnCommand(const TDispContext* pContext, TDispCommand* pCmd) = 0;
virtual BOOL OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT events) = 0;
virtual VOID OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT events, BOOL rs) = 0;
virtual BOOL OnReadyRead(const TDispContext* pContext, PVOID pv, UINT events) = 0;
virtual BOOL OnReadyWrite(const TDispContext* pContext, PVOID pv, UINT events) = 0;
virtual BOOL OnHungUp(const TDispContext* pContext, PVOID pv, UINT events) = 0;
virtual BOOL OnError(const TDispContext* pContext, PVOID pv, UINT events) = 0;
virtual BOOL OnReadyPrivilege(const TDispContext* pContext, PVOID pv, UINT events) = 0;
virtual VOID OnCommand(TDispCommand* pCmd) = 0;
virtual VOID OnTimer(ULLONG llExpirations) = 0;
virtual VOID OnDispatchThreadStart(THR_ID tid) = 0;
virtual VOID OnDispatchThreadEnd(THR_ID tid) = 0;
virtual BOOL OnBeforeProcessIo(PVOID pv, UINT events) = 0;
virtual VOID OnAfterProcessIo(PVOID pv, UINT events, BOOL rs) = 0;
virtual BOOL OnReadyRead(PVOID pv, UINT events) = 0;
virtual BOOL OnReadyWrite(PVOID pv, UINT events) = 0;
virtual BOOL OnHungUp(PVOID pv, UINT events) = 0;
virtual BOOL OnError(PVOID pv, UINT events) = 0;
virtual BOOL OnReadyPrivilege(PVOID pv, UINT events) = 0;
virtual VOID OnDispatchThreadStart(THR_ID tid) = 0;
virtual VOID OnDispatchThreadEnd(THR_ID tid) = 0;
public:
virtual ~IIOHandler() = default;
@@ -149,17 +106,17 @@ public:
class CIOHandler : public IIOHandler
{
public:
virtual VOID OnCommand(const TDispContext* pContext, TDispCommand* pCmd) override {}
virtual VOID OnCommand(TDispCommand* pCmd) override {}
virtual VOID OnTimer(ULLONG llExpirations) override {}
virtual BOOL OnBeforeProcessIo(const TDispContext* pContext, PVOID pv, UINT events) override {return TRUE;}
virtual VOID OnAfterProcessIo(const TDispContext* pContext, PVOID pv, UINT events, BOOL rs) override {}
virtual BOOL OnReadyWrite(const TDispContext* pContext, PVOID pv, UINT events) override {return TRUE;}
virtual BOOL OnHungUp(const TDispContext* pContext, PVOID pv, UINT events) override {return TRUE;}
virtual BOOL OnError(const TDispContext* pContext, PVOID pv, UINT events) override {return TRUE;}
virtual BOOL OnReadyPrivilege(const TDispContext* pContext, PVOID pv, UINT events) override {return TRUE;}
virtual VOID OnDispatchThreadStart(THR_ID tid) override {}
virtual VOID OnDispatchThreadEnd(THR_ID tid) override {}
virtual BOOL OnBeforeProcessIo(PVOID pv, UINT events) override {return TRUE;}
virtual VOID OnAfterProcessIo(PVOID pv, UINT events, BOOL rs) override {}
virtual BOOL OnReadyWrite(PVOID pv, UINT events) override {return TRUE;}
virtual BOOL OnHungUp(PVOID pv, UINT events) override {return TRUE;}
virtual BOOL OnError(PVOID pv, UINT events) override {return TRUE;}
virtual BOOL OnReadyPrivilege(PVOID pv, UINT events) override {return TRUE;}
virtual VOID OnDispatchThreadStart(THR_ID tid) override {}
virtual VOID OnDispatchThreadEnd(THR_ID tid) override {}
};
// ------------------------------------------------------------------------------------------------------------------------------------------------------- //
@@ -169,91 +126,55 @@ class CIODispatcher
public:
static const int DEF_WORKER_MAX_EVENTS = 64;
using CCommandQueue = TDispContext::CCommandQueue;
using CWorkerThread = TDispContext::CWorkerThread;
using CCommandQueue = CCASQueue<TDispCommand>;
using CWorkerThread = CThread<CIODispatcher, VOID, int>;
public:
BOOL Start(IIOHandler* pHandler, int iWorkerMaxEvents = DEF_WORKER_MAX_EVENTS, int iWorkers = 0);
BOOL Start(IIOHandler* pHandler, int iWorkerMaxEvents = DEF_WORKER_MAX_EVENTS, int iWorkers = 0, LLONG llTimerInterval = 0);
BOOL Stop(BOOL bCheck = TRUE);
BOOL SendCommandByIndex(int idx, TDispCommand* pCmd);
BOOL SendCommandByIndex(int idx, USHORT t, UINT_PTR wp = 0, UINT_PTR lp = 0);
BOOL SendCommandByFD(FD fd, TDispCommand* pCmd);
BOOL SendCommandByFD(FD fd, USHORT t, UINT_PTR wp = 0, UINT_PTR lp = 0);
BOOL SendCommand(TDispContext& ctx, TDispCommand* pCmd);
BOOL SendCommand(TDispCommand* pCmd);
BOOL SendCommand(USHORT t, UINT_PTR wp = 0, UINT_PTR lp = 0);
template<class _List, typename = enable_if_t<is_same<remove_reference_t<typename _List::reference>, TDispCommand*>::value>>
BOOL SendCommandsByIndex(int idx, const _List& cmds)
{
TDispContext& ctx = GetContextByIndex(idx);
return SendCommands(ctx, cmds);
}
template<class _List, typename = enable_if_t<is_same<remove_reference_t<typename _List::reference>, TDispCommand*>::value>>
BOOL SendCommandsByFD(FD fd, const _List& cmds)
{
TDispContext& ctx = GetContextByFD(fd);
return SendCommands(ctx, cmds);
}
template<class _List, typename = enable_if_t<is_same<remove_reference_t<typename _List::reference>, TDispCommand*>::value>>
BOOL SendCommands(TDispContext& ctx, const _List& cmds)
BOOL SendCommands(const _List& cmds)
{
size_t size = cmds.size();
if(size == 0) return FALSE;
for(auto it = cmds.begin(), end = cmds.end(); it != end; ++it)
ctx.m_queue.PushBack(*it);
m_queue.PushBack(*it);
return VERIFY_IS_NO_ERROR(eventfd_write(ctx.m_evCmd, size));
return VERIFY_IS_NO_ERROR(eventfd_write(m_evCmd, size));
}
BOOL AddFD(int idx, FD fd, UINT mask, PVOID pv) {return CtlFD(idx, fd, EPOLL_CTL_ADD, mask, pv);}
BOOL ModFD(int idx, FD fd, UINT mask, PVOID pv) {return CtlFD(idx, fd, EPOLL_CTL_MOD, mask, pv);}
BOOL DelFD(int idx, FD fd) {return CtlFD(idx, fd, EPOLL_CTL_DEL, 0, nullptr);}
BOOL CtlFD(int idx, FD fd, int op, UINT mask, PVOID pv);
BOOL AddFD(FD fd, UINT mask, PVOID pv) {return CtlFD(fd, EPOLL_CTL_ADD, mask, pv);}
BOOL ModFD(FD fd, UINT mask, PVOID pv) {return CtlFD(fd, EPOLL_CTL_MOD, mask, pv);}
BOOL DelFD(FD fd) {return CtlFD(fd, EPOLL_CTL_DEL, 0, nullptr);}
BOOL CtlFD(FD fd, int op, UINT mask, PVOID pv);
BOOL ProcessIo(PVOID pv, UINT events);
BOOL AddFD(FD fd, UINT mask, PVOID pv) {return CtlFD(-1, fd, EPOLL_CTL_ADD, mask, pv);}
BOOL ModFD(FD fd, UINT mask, PVOID pv) {return CtlFD(-1, fd, EPOLL_CTL_MOD, mask, pv);}
BOOL DelFD(FD fd) {return CtlFD(-1, fd, EPOLL_CTL_DEL, 0, nullptr);}
BOOL CtlFD(FD fd, int op, UINT mask, PVOID pv) {return CtlFD(-1, fd, op, mask, pv);}
BOOL ProcessIo(const TDispContext* pContext, PVOID pv, UINT events);
FD AddTimer (int idx, LLONG llInterval, PVOID pv);
BOOL DelTimer (int idx, FD fdTimer);
FD AddTimer (LLONG llInterval, PVOID pv) {return AddTimer(-1, llInterval, pv);}
BOOL DelTimer (FD fdTimer) {return DelTimer(-1, fdTimer);}
FD AddTimer (LLONG llInterval, PVOID pv);
BOOL DelTimer (FD fdTimer);
private:
int WorkerProc(TDispContext* pContext);
BOOL ProcessExit(const TDispContext* pContext, UINT events);
BOOL ProcessCommand(TDispContext* pContext, UINT events);
BOOL DoProcessIo(const TDispContext* pContext, PVOID pv, UINT events);
int WorkerProc(PVOID pv = nullptr);
BOOL ProcessExit(UINT events);
BOOL ProcessTimer(UINT events);
BOOL ProcessCommand(UINT events);
BOOL DoProcessIo(PVOID pv, UINT events);
VOID Reset();
VOID MakePrefix();
TDispContext& GetContextByIndex(int idx) {return GetContext(idx, -1);}
TDispContext& GetContextByFD(FD fd) {return GetContext(-1, fd);}
TDispContext& GetContext(int idx, FD fd);
public:
const TDispContext& GetContextRefByIndex(int idx) {return GetContextByIndex(idx);}
const TDispContext& GetContextRefByFD(FD fd) {return GetContextByFD(fd);}
const TDispContext& GetContextRef(int idx, FD fd) {return GetContext(idx, fd);}
BOOL HasStarted() {return m_pHandler && m_pContexts;}
int GetWorkers() {return m_iWorkers;}
const TDispContext* GetContexts() {return m_pContexts.get();}
BOOL HasStarted() {return m_pHandler && m_pWorkers;}
const CWorkerThread* GetWorkerThreads() {return m_pWorkers.get();}
CIODispatcher() {MakePrefix(); Reset();}
~CIODispatcher() {if(HasStarted()) Stop();}
DECLARE_NO_COPY_CLASS(CIODispatcher)
private:
static LPCTSTR WORKER_THREAD_PREFIX;
static volatile UINT sm_uiNum;
@@ -262,11 +183,14 @@ private:
CString m_strPrefix;
private:
int m_iWorkers;
int m_iMaxEvents;
IIOHandler* m_pHandler;
FD m_epoll;
FD m_evCmd;
FD m_evExit;
FD m_evTimer;
int m_iWorkers;
int m_iMaxEvents;
FD m_evExit;
IIOHandler* m_pHandler;
unique_ptr<TDispContext[]> m_pContexts;
CCommandQueue m_queue;
unique_ptr<CWorkerThread[]> m_pWorkers;
};

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include <poll.h>
#include <signal.h>

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include "Singleton.h"
#include <malloc.h>

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include "CriSec.h"
#include <shared_mutex>

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include "Singleton.h"
#include "STLHelper.h"
#include "FuncHelper.h"

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include "Singleton.h"
#include "StringT.h"
@@ -31,7 +31,6 @@
#include <functional>
#include <algorithm>
#include <random>
#include <vector>
#include <deque>
#include <queue>
@@ -1018,51 +1017,3 @@ typedef str_sort_func<TCHAR*, false, true> tchar_ptr_desc_case_sort_func;
typedef str_sort_func<CString, false, true> string_desc_case_sort_func;
typedef str_sort_func<TCHAR*, false, false> tchar_ptr_desc_ucase_sort_func;
typedef str_sort_func<CString, false, false> string_desc_ucase_sort_func;
template<typename _IntType = int, typename = enable_if_t<is_integral<_IntType>::value>>
class CRandomIntegralT
{
public:
_IntType Generate() {return dist(gen);}
_IntType operator()() {return Generate();}
public:
CRandomIntegralT(_IntType from, _IntType to) : gen(rd()), dist(from, to)
{
}
private:
random_device rd;
mt19937 gen;
uniform_int_distribution<_IntType> dist;
};
template<typename _RealType = double, typename = enable_if_t<is_floating_point<_RealType>::value>>
class CRandomRealTypeT
{
public:
_RealType Generate() {return dist(gen);}
_RealType operator()() {return Generate();}
public:
CRandomRealTypeT(_RealType from, _RealType to) : gen(rd()), dist(from, to)
{
}
private:
random_device rd;
mt19937 gen;
uniform_real_distribution<_RealType> dist;
};
typedef CRandomIntegralT<int> CRandomInt;
typedef CRandomIntegralT<long> CRandomLong;
typedef CRandomIntegralT<unsigned int> CRandomUint;
typedef CRandomIntegralT<unsigned long> CRandomUlong;
typedef CRandomIntegralT<int64_t> CRandomInt64;
typedef CRandomIntegralT<uint64_t> CRandomUint64;
typedef CRandomRealTypeT<float> CRandomFloat;
typedef CRandomRealTypeT<double> CRandomDouble;

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include "CriSec.h"
#include <condition_variable>

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include "Thread.h"
#include <signal.h>

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#define SINGLETON_THIS(ClassName) ClassName::GetThis()
#define SINGLETON_INSTANCE(ClassName) ClassName::GetInstance()

View File

@@ -23,7 +23,7 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalDef.h"
#include <unistd.h>
#include <sched.h>
@@ -49,9 +49,6 @@ using namespace std;
/* 默认内存块缓存池回收阀值 */
#define DEFAULT_BUFFER_CACHE_POOL_HOLD 1024
/* 使用外部垃圾回收 */
#define USE_EXTERNAL_GC 1
#define SysGetSystemConfig sysconf
#define SysGetSystemInfo sysinfo

View File

@@ -23,8 +23,8 @@
#pragma once
#include "hpsocket/GlobalDef.h"
#include "hpsocket/GlobalErrno.h"
#include "../hpsocket/GlobalDef.h"
#include "../hpsocket/GlobalErrno.h"
#include "RWLock.h"
#include "STLHelper.h"

2374
common/crypto/Crypto.cpp Normal file

File diff suppressed because it is too large Load Diff

258
common/crypto/Crypto.h Normal file
View File

@@ -0,0 +1,258 @@
#pragma once
#include "../../hpsocket/GlobalDef.h"
#include <stddef.h>
// -------------------------------------------------- BASE64 -------------------------------------------------- //
// Returns the size of the output. If called with out = NULL, will just return
// the size of what the output would have been (without a terminating NULL).
size_t base64_encode(const BYTE in[], BYTE out[], size_t len, int newline_flag);
// Returns the size of the output. If called with out = NULL, will just return
// the size of what the output would have been (without a terminating NULL).
size_t base64_decode(const BYTE in[], BYTE out[], size_t len);
// -------------------------------------------------- URL -------------------------------------------------- //
int url_encode(const char* src, const int src_size, char* dest, const int dest_size);
int url_decode(const char* src, const int src_size, char* dest, const int dest_size);
// -------------------------------------------------- AES -------------------------------------------------- //
/****************************** MACROS ******************************/
#define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time
/**************************** DATA TYPES ****************************/
//typedef unsigned char BYTE; // 8-bit byte
//typedef unsigned int UINT; // 32-bit word, change to "long" for 16-bit machines
/*********************** FUNCTION DECLARATIONS **********************/
///////////////////
// AES
///////////////////
// Key setup must be done before any AES en/de-cryption functions can be used.
void aes_key_setup(const BYTE key[], // The key, must be 128, 192, or 256 bits
UINT w[], // Output key schedule to be used later
int keysize); // Bit length of the key, 128, 192, or 256
void aes_encrypt(const BYTE in[], // 16 bytes of plaintext
BYTE out[], // 16 bytes of ciphertext
const UINT key[], // From the key setup
int keysize); // Bit length of the key, 128, 192, or 256
void aes_decrypt(const BYTE in[], // 16 bytes of ciphertext
BYTE out[], // 16 bytes of plaintext
const UINT key[], // From the key setup
int keysize); // Bit length of the key, 128, 192, or 256
///////////////////
// AES - CBC
///////////////////
int aes_encrypt_cbc(const BYTE in[], // Plaintext
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
BYTE out[], // Ciphertext, same length as plaintext
const UINT key[], // From the key setup
int keysize, // Bit length of the key, 128, 192, or 256
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
// Only output the CBC-MAC of the input.
int aes_encrypt_cbc_mac(const BYTE in[], // plaintext
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
BYTE out[], // Output MAC
const UINT key[], // From the key setup
int keysize, // Bit length of the key, 128, 192, or 256
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
///////////////////
// AES - CTR
///////////////////
void increment_iv(BYTE iv[], // Must be a multiple of AES_BLOCK_SIZE
int counter_size); // Bytes of the IV used for counting (low end)
void aes_encrypt_ctr(const BYTE in[], // Plaintext
size_t in_len, // Any byte length
BYTE out[], // Ciphertext, same length as plaintext
const UINT key[], // From the key setup
int keysize, // Bit length of the key, 128, 192, or 256
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
void aes_decrypt_ctr(const BYTE in[], // Ciphertext
size_t in_len, // Any byte length
BYTE out[], // Plaintext, same length as ciphertext
const UINT key[], // From the key setup
int keysize, // Bit length of the key, 128, 192, or 256
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
///////////////////
// AES - CCM
///////////////////
// Returns True if the input parameters do not violate any constraint.
int aes_encrypt_ccm(const BYTE plaintext[], // IN - Plaintext.
UINT plaintext_len, // IN - Plaintext length.
const BYTE associated_data[], // IN - Associated Data included in authentication, but not encryption.
unsigned short associated_data_len, // IN - Associated Data length in bytes.
const BYTE nonce[], // IN - The Nonce to be used for encryption.
unsigned short nonce_len, // IN - Nonce length in bytes.
BYTE ciphertext[], // OUT - Ciphertext, a concatination of the plaintext and the MAC.
UINT *ciphertext_len, // OUT - The length of the ciphertext, always plaintext_len + mac_len.
UINT mac_len, // IN - The desired length of the MAC, must be 4, 6, 8, 10, 12, 14, or 16.
const BYTE key[], // IN - The AES key for encryption.
int keysize); // IN - The length of the key in bits. Valid values are 128, 192, 256.
// Returns True if the input parameters do not violate any constraint.
// Use mac_auth to ensure decryption/validation was preformed correctly.
// If authentication does not succeed, the plaintext is zeroed out. To overwride
// this, call with mac_auth = NULL. The proper proceedure is to decrypt with
// authentication enabled (mac_auth != NULL) and make a second call to that
// ignores authentication explicitly if the first call failes.
int aes_decrypt_ccm(const BYTE ciphertext[], // IN - Ciphertext, the concatination of encrypted plaintext and MAC.
UINT ciphertext_len, // IN - Ciphertext length in bytes.
const BYTE assoc[], // IN - The Associated Data, required for authentication.
unsigned short assoc_len, // IN - Associated Data length in bytes.
const BYTE nonce[], // IN - The Nonce to use for decryption, same one as for encryption.
unsigned short nonce_len, // IN - Nonce length in bytes.
BYTE plaintext[], // OUT - The plaintext that was decrypted. Will need to be large enough to hold ciphertext_len - mac_len.
UINT *plaintext_len, // OUT - Length in bytes of the output plaintext, always ciphertext_len - mac_len .
UINT mac_len, // IN - The length of the MAC that was calculated.
int *mac_auth, // OUT - TRUE if authentication succeeded, FALSE if it did not. NULL pointer will ignore the authentication.
const BYTE key[], // IN - The AES key for decryption.
int keysize); // IN - The length of the key in BITS. Valid values are 128, 192, 256.
// -------------------------------------------------- DES -------------------------------------------------- //
/****************************** MACROS ******************************/
#define DES_BLOCK_SIZE 8 // DES operates on 8 bytes at a time
/**************************** DATA TYPES ****************************/
typedef enum {
DES_ENCRYPT,
DES_DECRYPT
} DES_MODE;
/*********************** FUNCTION DECLARATIONS **********************/
void des_key_setup(const BYTE key[], BYTE schedule[][6], DES_MODE mode);
void des_crypt(const BYTE in[], BYTE out[], const BYTE key[][6]);
void three_des_key_setup(const BYTE key[], BYTE schedule[][16][6], DES_MODE mode);
void three_des_crypt(const BYTE in[], BYTE out[], const BYTE key[][16][6]);
// -------------------------------------------------- MD2 -------------------------------------------------- //
/****************************** MACROS ******************************/
#define MD2_BLOCK_SIZE 16
/**************************** DATA TYPES ****************************/
typedef struct {
BYTE data[16];
BYTE state[48];
BYTE checksum[16];
int len;
} _MD2_CTX;
/*********************** FUNCTION DECLARATIONS **********************/
void md2_init(_MD2_CTX *ctx);
void md2_update(_MD2_CTX *ctx, const BYTE data[], size_t len);
void md2_final(_MD2_CTX *ctx, BYTE hash[]); // size of hash must be MD2_BLOCK_SIZE
// -------------------------------------------------- MD5 -------------------------------------------------- //
/****************************** MACROS ******************************/
#define MD5_BLOCK_SIZE 16 // MD5 outputs a 16 byte digest
/**************************** DATA TYPES ****************************/
typedef struct {
BYTE data[64];
UINT datalen;
unsigned long long bitlen;
UINT state[4];
} _MD5_CTX;
/*********************** FUNCTION DECLARATIONS **********************/
void md5_init(_MD5_CTX *ctx);
void md5_update(_MD5_CTX *ctx, const BYTE data[], size_t len);
void md5_final(_MD5_CTX *ctx, BYTE hash[]);
// -------------------------------------------------- SHA1 -------------------------------------------------- //
/****************************** MACROS ******************************/
#define SHA1_BLOCK_SIZE 20 // SHA1 outputs a 20 byte digest
/**************************** DATA TYPES ****************************/
typedef struct {
BYTE data[64];
UINT datalen;
unsigned long long bitlen;
UINT state[5];
UINT k[4];
} _SHA1_CTX;
/*********************** FUNCTION DECLARATIONS **********************/
void sha1_init(_SHA1_CTX *ctx);
void sha1_update(_SHA1_CTX *ctx, const BYTE data[], size_t len);
void sha1_final(_SHA1_CTX *ctx, BYTE hash[]);
// -------------------------------------------------- SHA256 -------------------------------------------------- //
/****************************** MACROS ******************************/
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
/**************************** DATA TYPES ****************************/
typedef struct {
BYTE data[64];
UINT datalen;
unsigned long long bitlen;
UINT state[8];
} _SHA256_CTX;
/*********************** FUNCTION DECLARATIONS **********************/
void sha256_init(_SHA256_CTX *ctx);
void sha256_update(_SHA256_CTX *ctx, const BYTE data[], size_t len);
void sha256_final(_SHA256_CTX *ctx, BYTE hash[]);
// -------------------------------------------------- ARCFOUR -------------------------------------------------- //
/**************************** DATA TYPES ****************************/
/*********************** FUNCTION DECLARATIONS **********************/
// Input: state - the state used to generate the keystream
// key - Key to use to initialize the state
// len - length of key in bytes (valid lenth is 1 to 256)
void arcfour_key_setup(BYTE state[], const BYTE key[], int len);
// Pseudo-Random Generator Algorithm
// Input: state - the state used to generate the keystream
// out - Must be allocated to be of at least "len" length
// len - number of bytes to generate
void arcfour_generate_stream(BYTE state[], BYTE out[], size_t len);
// -------------------------------------------------- BLOWFISH -------------------------------------------------- //
/****************************** MACROS ******************************/
#define BLOWFISH_BLOCK_SIZE 8 // Blowfish operates on 8 bytes at a time
/**************************** DATA TYPES ****************************/
typedef struct {
WORD p[18];
WORD s[4][256];
} _BLOWFISH_KEY;
/*********************** FUNCTION DECLARATIONS **********************/
void blowfish_key_setup(const BYTE user_key[], _BLOWFISH_KEY *keystruct, size_t len);
void blowfish_encrypt(const BYTE in[], BYTE out[], const _BLOWFISH_KEY *keystruct);
void blowfish_decrypt(const BYTE in[], BYTE out[], const _BLOWFISH_KEY *keystruct);
// -------------------------------------------------- ROT-13 -------------------------------------------------- //
/*********************** FUNCTION DECLARATIONS **********************/
// Performs IN PLACE rotation of the input. Assumes input is NULL terminated.
// Preserves each charcter's case. Ignores non alphabetic characters.
void rot13(char str[]);

View File

@@ -3,8 +3,8 @@
#define INCLUDE_LLHTTP_H_
#define LLHTTP_VERSION_MAJOR 9
#define LLHTTP_VERSION_MINOR 2
#define LLHTTP_VERSION_PATCH 1
#define LLHTTP_VERSION_MINOR 1
#define LLHTTP_VERSION_PATCH 3
#ifndef INCLUDE_LLHTTP_ITSELF_H_
#define INCLUDE_LLHTTP_ITSELF_H_
@@ -181,8 +181,7 @@ enum llhttp_method {
HTTP_SET_PARAMETER = 42,
HTTP_REDIRECT = 43,
HTTP_RECORD = 44,
HTTP_FLUSH = 45,
HTTP_QUERY = 46
HTTP_FLUSH = 45
};
typedef enum llhttp_method llhttp_method_t;
@@ -363,7 +362,6 @@ typedef enum llhttp_status llhttp_status_t;
XX(31, LINK, LINK) \
XX(32, UNLINK, UNLINK) \
XX(33, SOURCE, SOURCE) \
XX(46, QUERY, QUERY) \
#define RTSP_METHOD_MAP(XX) \
@@ -430,7 +428,6 @@ typedef enum llhttp_status llhttp_status_t;
XX(43, REDIRECT, REDIRECT) \
XX(44, RECORD, RECORD) \
XX(45, FLUSH, FLUSH) \
XX(46, QUERY, QUERY) \
#define HTTP_STATUS_MAP(XX) \
@@ -550,8 +547,6 @@ extern "C" {
#if defined(__wasm__)
#define LLHTTP_EXPORT __attribute__((visibility("default")))
//#elif defined(_WIN32)
//#define LLHTTP_EXPORT __declspec(dllexport)
#else
#define LLHTTP_EXPORT
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -79,7 +79,6 @@
#define ERROR_OUT_OF_RANGE ERANGE
#define ERROR_DESTINATION_ELEMENT_FULL EXFULL
#define ERROR_ALREADY_INITIALIZED EALREADY
#define ERROR_CANT_WAIT EIO
#define EXIT_CODE_OK EX_OK
#define EXIT_CODE_CONFIG EX_CONFIG

View File

@@ -1032,8 +1032,6 @@ HPSOCKET_API BOOL __HP_CALL HP_TcpAgent_SendSmallFile(HP_Agent pAgent, HP_CONNID
/**********************************************************************************/
/***************************** TCP Agent 属性访问方法 *****************************/
/* 设置同步连接超时时间(毫秒) */
HPSOCKET_API void __HP_CALL HP_TcpAgent_SetSyncConnectTimeout(HP_TcpAgent pAgent, DWORD dwSyncConnectTimeout);
/* 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) */
HPSOCKET_API void __HP_CALL HP_TcpAgent_SetSocketBufferSize(HP_TcpAgent pAgent, DWORD dwSocketBufferSize);
/* 设置正常心跳包间隔毫秒0 则不发送心跳包默认60 * 1000 */
@@ -1043,8 +1041,6 @@ HPSOCKET_API void __HP_CALL HP_TcpAgent_SetKeepAliveInterval(HP_TcpAgent pAgent,
/* 设置是否开启 nodelay 模式默认FALSE不开启 */
HPSOCKET_API void __HP_CALL HP_TcpAgent_SetNoDelay(HP_TcpAgent pAgent, BOOL bNoDelay);
/* 获取同步连接超时时间 */
HPSOCKET_API DWORD __HP_CALL HP_TcpAgent_GetSyncConnectTimeout(HP_TcpAgent pAgent);
/* 获取通信数据缓冲区大小 */
HPSOCKET_API DWORD __HP_CALL HP_TcpAgent_GetSocketBufferSize(HP_TcpAgent pAgent);
/* 获取正常心跳包间隔 */
@@ -1225,8 +1221,6 @@ HPSOCKET_API BOOL __HP_CALL HP_TcpClient_SendSmallFile(HP_Client pClient, LPCTST
/**********************************************************************************/
/***************************** TCP Client 属性访问方法 *****************************/
/* 设置同步连接超时时间(毫秒) */
HPSOCKET_API void __HP_CALL HP_TcpClient_SetSyncConnectTimeout(HP_TcpClient pClient, DWORD dwSyncConnectTimeout);
/* 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为:(N * 1024) - sizeof(TBufferObj) */
HPSOCKET_API void __HP_CALL HP_TcpClient_SetSocketBufferSize(HP_TcpClient pClient, DWORD dwSocketBufferSize);
/* 设置正常心跳包间隔毫秒0 则不发送心跳包默认60 * 1000 */
@@ -1236,8 +1230,6 @@ HPSOCKET_API void __HP_CALL HP_TcpClient_SetKeepAliveInterval(HP_TcpClient pClie
/* 设置是否开启 nodelay 模式默认FALSE不开启 */
HPSOCKET_API void __HP_CALL HP_TcpClient_SetNoDelay(HP_TcpClient pClient, BOOL bNoDelay);
/* 获取同步连接超时时间 */
HPSOCKET_API DWORD __HP_CALL HP_TcpClient_GetSyncConnectTimeout(HP_TcpClient pClient);
/* 获取通信数据缓冲区大小 */
HPSOCKET_API DWORD __HP_CALL HP_TcpClient_GetSocketBufferSize(HP_TcpClient pClient);
/* 获取正常心跳包间隔 */

View File

@@ -26,9 +26,9 @@
#include "GlobalDef.h"
/* HP-Socket 版本号 */
#define HP_VERSION_MAJOR 6 // 主版本号
#define HP_VERSION_MINOR 0 // 子版本号
#define HP_VERSION_REVISE 3 // 修正版本号
#define HP_VERSION_MAJOR 5 // 主版本号
#define HP_VERSION_MINOR 9 // 子版本号
#define HP_VERSION_REVISE 6 // 修正版本号
#define HP_VERSION_BUILD 1 // 构建编号
//#define _UDP_DISABLED // 禁用 UDP
@@ -204,7 +204,6 @@ typedef enum EnSocketError
SE_NETWORK = 12, // 网络错误
SE_DATA_PROC = 13, // 数据处理错误
SE_DATA_SEND = 14, // 数据发送失败
SE_GC_START = 15, // 垃圾回收启动失败
/***** SSL Socket 扩展操作结果代码 *****/
SE_SSL_ENV_NOT_READY = 101, // SSL 环境未就绪

View File

@@ -758,8 +758,6 @@ public:
/***********************************************************************/
/***************************** 属性访问方法 *****************************/
/* 设置同步连接超时时间(毫秒) */
virtual void SetSyncConnectTimeout (DWORD dwSyncConnectTimeout) = 0;
/* 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) */
virtual void SetSocketBufferSize (DWORD dwSocketBufferSize) = 0;
/* 设置正常心跳包间隔毫秒0 则不发送心跳包默认60 * 1000 */
@@ -769,8 +767,6 @@ public:
/* 设置是否开启 nodelay 模式默认FALSE不开启 */
virtual void SetNoDelay (BOOL bNoDelay) = 0;
/* 获取同步连接超时时间 */
virtual DWORD GetSyncConnectTimeout () = 0;
/* 获取通信数据缓冲区大小 */
virtual DWORD GetSocketBufferSize () = 0;
/* 获取正常心跳包间隔 */
@@ -1017,19 +1013,15 @@ public:
/***********************************************************************/
/***************************** 属性访问方法 *****************************/
/* 设置同步连接超时时间(毫秒) */
virtual void SetSyncConnectTimeout (DWORD dwSyncConnectTimeout) = 0;
/* 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为:(N * 1024) - sizeof(TBufferObj) */
virtual void SetSocketBufferSize (DWORD dwSocketBufferSize) = 0;
virtual void SetSocketBufferSize (DWORD dwSocketBufferSize) = 0;
/* 设置正常心跳包间隔毫秒0 则不发送心跳包默认60 * 1000 */
virtual void SetKeepAliveTime (DWORD dwKeepAliveTime) = 0;
virtual void SetKeepAliveTime (DWORD dwKeepAliveTime) = 0;
/* 设置异常心跳包间隔毫秒0 不发送心跳包默认20 * 1000如果超过若干次 [默认WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) */
virtual void SetKeepAliveInterval (DWORD dwKeepAliveInterval) = 0;
virtual void SetKeepAliveInterval (DWORD dwKeepAliveInterval) = 0;
/* 设置是否开启 nodelay 模式默认FALSE不开启 */
virtual void SetNoDelay (BOOL bNoDelay) = 0;
virtual void SetNoDelay (BOOL bNoDelay) = 0;
/* 获取同步连接超时时间 */
virtual DWORD GetSyncConnectTimeout () = 0;
/* 获取通信数据缓冲区大小 */
virtual DWORD GetSocketBufferSize () = 0;
/* 获取正常心跳包间隔 */