改为V5.9.6
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);}
|
||||
|
||||
|
||||
@@ -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 '['
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -70,8 +70,6 @@ protected:
|
||||
|
||||
virtual void OnWorkerThreadEnd(THR_ID dwThreadID);
|
||||
|
||||
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE);
|
||||
|
||||
protected:
|
||||
virtual BOOL StartSSLHandShake(TAgentSocketObj* pSocketObj);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -336,6 +336,7 @@ public:
|
||||
void Prepare ();
|
||||
void Clear ();
|
||||
|
||||
private:
|
||||
void ReleaseGCSession (BOOL bForce = FALSE);
|
||||
|
||||
public:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -78,8 +78,6 @@ protected:
|
||||
|
||||
virtual void OnWorkerThreadEnd(THR_ID dwThreadID);
|
||||
|
||||
virtual void ReleaseGCSocketObj(BOOL bForce = FALSE);
|
||||
|
||||
protected:
|
||||
virtual BOOL StartSSLHandShake(TSocketObj* pSocketObj);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
173
SocketHelper.h
173
SocketHelper.h
@@ -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);
|
||||
|
||||
198
TcpAgent.cpp
198
TcpAgent.cpp
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
53
TcpAgent.h
53
TcpAgent.h
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;}
|
||||
|
||||
@@ -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;}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
230
TcpServer.cpp
230
TcpServer.cpp
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
58
TcpServer.h
58
TcpServer.h
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;}
|
||||
|
||||
410
UdpNode.cpp
410
UdpNode.cpp
@@ -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
|
||||
|
||||
75
UdpNode.h
75
UdpNode.h
@@ -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;
|
||||
|
||||
|
||||
408
UdpServer.cpp
408
UdpServer.cpp
@@ -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);
|
||||
|
||||
|
||||
64
UdpServer.h
64
UdpServer.h
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hpsocket/GlobalDef.h"
|
||||
#include "../hpsocket/GlobalDef.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <malloc.h>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hpsocket/GlobalDef.h"
|
||||
#include "../hpsocket/GlobalDef.h"
|
||||
#include "Singleton.h"
|
||||
#include "FuncHelper.h"
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hpsocket/GlobalDef.h"
|
||||
#include "../hpsocket/GlobalDef.h"
|
||||
#include "Singleton.h"
|
||||
#include "FuncHelper.h"
|
||||
#include "PollHelper.h"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hpsocket/GlobalDef.h"
|
||||
#include "../hpsocket/GlobalDef.h"
|
||||
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hpsocket/GlobalDef.h"
|
||||
#include "../hpsocket/GlobalDef.h"
|
||||
#include "Singleton.h"
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hpsocket/GlobalDef.h"
|
||||
#include "../hpsocket/GlobalDef.h"
|
||||
#include "CriSec.h"
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hpsocket/GlobalDef.h"
|
||||
#include "../hpsocket/GlobalDef.h"
|
||||
#include "Singleton.h"
|
||||
#include "STLHelper.h"
|
||||
#include "FuncHelper.h"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hpsocket/GlobalDef.h"
|
||||
#include "../hpsocket/GlobalDef.h"
|
||||
#include "CriSec.h"
|
||||
|
||||
#include <condition_variable>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hpsocket/GlobalDef.h"
|
||||
#include "../hpsocket/GlobalDef.h"
|
||||
#include "Thread.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
2374
common/crypto/Crypto.cpp
Normal file
File diff suppressed because it is too large
Load Diff
258
common/crypto/Crypto.h
Normal file
258
common/crypto/Crypto.h
Normal 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[]);
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
/* 获取正常心跳包间隔 */
|
||||
|
||||
@@ -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 环境未就绪
|
||||
|
||||
@@ -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;
|
||||
/* 获取正常心跳包间隔 */
|
||||
|
||||
Reference in New Issue
Block a user