فهرست منبع

添加HPSocket库头文件。

Jeff 6 سال پیش
والد
کامیت
1d7ff2d111

+ 26 - 0
source/hook/hp-src/CriticalSection.cpp

@@ -0,0 +1,26 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+#include "CriticalSection.h"

+ 311 - 0
source/hook/hp-src/CriticalSection.h

@@ -0,0 +1,311 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <intrin.h>
+
+#pragma intrinsic(_ReadBarrier)
+#pragma intrinsic(_WriteBarrier)
+#pragma intrinsic(_ReadWriteBarrier)
+
+#define DEFAULT_CRISEC_SPIN_COUNT	4096
+
+#if defined (_WIN64)
+	#define DEFAULT_PAUSE_RETRY		16
+	#define DEFAULT_PAUSE_YIELD		128
+	#define DEFAULT_PAUSE_CYCLE		8192
+#else
+	#define DEFAULT_PAUSE_RETRY		4
+	#define DEFAULT_PAUSE_YIELD		32
+	#define DEFAULT_PAUSE_CYCLE		4096
+#endif
+
+#ifndef YieldProcessor
+	#pragma intrinsic(_mm_pause)
+	#define YieldProcessor _mm_pause
+#endif
+
+static inline void YieldThread(UINT i = DEFAULT_PAUSE_RETRY)
+{
+	if		(i < DEFAULT_PAUSE_RETRY)		;
+	else if	(i < DEFAULT_PAUSE_YIELD)		YieldProcessor();
+	else if	(i < DEFAULT_PAUSE_CYCLE - 1)	SwitchToThread();
+	else if	(i < DEFAULT_PAUSE_CYCLE)		Sleep(1);
+	else									YieldThread(i & (DEFAULT_PAUSE_CYCLE - 1));
+}
+
+class CInterCriSec
+{
+public:
+	CInterCriSec(DWORD dwSpinCount = DEFAULT_CRISEC_SPIN_COUNT)
+		{VERIFY(::InitializeCriticalSectionAndSpinCount(&m_crisec, dwSpinCount));}
+	~CInterCriSec()
+		{::DeleteCriticalSection(&m_crisec);}
+
+	void Lock()								{::EnterCriticalSection(&m_crisec);}
+	void Unlock()							{::LeaveCriticalSection(&m_crisec);}
+	BOOL TryLock()							{return ::TryEnterCriticalSection(&m_crisec);}
+	DWORD SetSpinCount(DWORD dwSpinCount)	{return ::SetCriticalSectionSpinCount(&m_crisec, dwSpinCount);}
+
+	CRITICAL_SECTION* GetObject()			{return &m_crisec;}
+
+private:
+	CInterCriSec(const CInterCriSec& cs);
+	CInterCriSec operator = (const CInterCriSec& cs);
+
+private:
+	CRITICAL_SECTION m_crisec;
+};
+
+class CInterCriSec2
+{
+public:
+	CInterCriSec2(DWORD dwSpinCount = DEFAULT_CRISEC_SPIN_COUNT, BOOL bInitialize = TRUE)
+	{
+		if(bInitialize)
+		{
+			m_pcrisec = new CRITICAL_SECTION;
+			VERIFY(::InitializeCriticalSectionAndSpinCount(m_pcrisec, dwSpinCount));
+		}
+		else
+			m_pcrisec = nullptr;
+	}
+
+	~CInterCriSec2() {Reset();}
+
+	void Attach(CRITICAL_SECTION* pcrisec)
+	{
+		Reset();
+		m_pcrisec = pcrisec;
+	}
+
+	CRITICAL_SECTION* Detach()
+	{
+		CRITICAL_SECTION* pcrisec = m_pcrisec;
+		m_pcrisec = nullptr;
+		return pcrisec;
+	}
+
+	void Lock()								{::EnterCriticalSection(m_pcrisec);}
+	void Unlock()							{::LeaveCriticalSection(m_pcrisec);}
+	BOOL TryLock()							{return ::TryEnterCriticalSection(m_pcrisec);}
+	DWORD SetSpinCount(DWORD dwSpinCount)	{return ::SetCriticalSectionSpinCount(m_pcrisec, dwSpinCount);}
+
+	CRITICAL_SECTION* GetObject()			{return m_pcrisec;}
+
+private:
+	CInterCriSec2(const CInterCriSec2& cs);
+	CInterCriSec2 operator = (const CInterCriSec2& cs);
+
+	void Reset()
+	{
+		if(m_pcrisec)
+		{
+			::DeleteCriticalSection(m_pcrisec);
+			delete m_pcrisec;
+			m_pcrisec = nullptr;
+		}
+	}
+
+private:
+	CRITICAL_SECTION* m_pcrisec;
+};
+
+class CMTX
+{
+public:
+	CMTX(BOOL bInitialOwner = FALSE, LPCTSTR pszName = nullptr, LPSECURITY_ATTRIBUTES pSecurity = nullptr)	
+	{
+		m_hMutex = ::CreateMutex(pSecurity, bInitialOwner, pszName);
+		ASSERT(IsValid());
+	}
+
+	~CMTX()
+	{
+		if(IsValid())
+			::CloseHandle(m_hMutex);
+	}
+
+	BOOL Open(DWORD dwAccess, BOOL bInheritHandle, LPCTSTR pszName)
+	{
+		if(IsValid())
+			VERIFY(::CloseHandle(m_hMutex));
+
+		m_hMutex = ::OpenMutex(dwAccess, bInheritHandle, pszName);
+		return(IsValid());
+	}
+
+	void Lock(DWORD dwMilliseconds = INFINITE)	{::WaitForSingleObject(m_hMutex, dwMilliseconds);}
+	void Unlock()								{::ReleaseMutex(m_hMutex);}
+
+	HANDLE& GetHandle	() 	{return m_hMutex;}
+	operator HANDLE		()	{return m_hMutex;}
+	BOOL IsValid		()	{return m_hMutex != nullptr;}
+
+private:
+	CMTX(const CMTX& mtx);
+	CMTX operator = (const CMTX& mtx);
+
+private:
+	HANDLE m_hMutex;
+};
+
+class CSpinGuard
+{
+public:
+	CSpinGuard() : m_lFlag(0)
+	{
+
+	}
+
+	~CSpinGuard()
+	{
+		ASSERT(m_lFlag == 0);
+	}
+
+	void Lock()
+	{
+		for(UINT i = 0; !TryLock(); ++i)
+			YieldThread(i);
+	}
+
+	BOOL TryLock()
+	{
+		if(::InterlockedCompareExchange(&m_lFlag, 1, 0) == 0)
+		{
+			::_ReadWriteBarrier();
+			return TRUE;
+		}
+
+		return FALSE;
+	}
+
+	void Unlock()
+	{
+		ASSERT(m_lFlag == 1);
+		m_lFlag = 0;
+	}
+
+private:
+	CSpinGuard(const CSpinGuard& cs);
+	CSpinGuard operator = (const CSpinGuard& cs);
+
+private:
+	volatile LONG m_lFlag;
+};
+
+class CReentrantSpinGuard
+{
+public:
+	CReentrantSpinGuard()
+	: m_dwThreadID	(0)
+	, m_iCount		(0)
+	{
+
+	}
+
+	~CReentrantSpinGuard()
+	{
+		ASSERT(m_dwThreadID	== 0);
+		ASSERT(m_iCount		== 0);
+	}
+
+	void Lock()
+	{
+		for(UINT i = 0; !_TryLock(i == 0); ++i)
+			YieldThread(i);
+	}
+
+	BOOL TryLock()
+	{
+		return _TryLock(TRUE);
+	}
+
+	void Unlock()
+	{
+		ASSERT(m_dwThreadID == ::GetCurrentThreadId());
+
+		if((--m_iCount) == 0)
+			m_dwThreadID = 0;
+	}
+
+private:
+	CReentrantSpinGuard(const CReentrantSpinGuard& cs);
+	CReentrantSpinGuard operator = (const CReentrantSpinGuard& cs);
+
+	BOOL _TryLock(BOOL bFirst)
+	{
+		DWORD dwCurrentThreadID = ::GetCurrentThreadId();
+
+		if(bFirst && m_dwThreadID == dwCurrentThreadID)
+		{
+			++m_iCount;
+			return TRUE;
+		}
+
+		if(::InterlockedCompareExchange(&m_dwThreadID, dwCurrentThreadID, 0) == 0)
+		{
+			::_ReadWriteBarrier();
+			ASSERT(m_iCount == 0);
+
+			m_iCount = 1;
+
+			return TRUE;
+		}
+
+		return FALSE;
+	}
+
+private:
+	volatile DWORD	m_dwThreadID;
+	int				m_iCount;
+};
+
+class CFakeGuard
+{
+public:
+	void Lock()		{}
+	void Unlock()	{}
+	BOOL TryLock()	{return TRUE;}
+};
+
+template<class CLockObj> class CLocalLock
+{
+public:
+	CLocalLock(CLockObj& obj) : m_lock(obj) {m_lock.Lock();}
+	~CLocalLock() {m_lock.Unlock();}
+private:
+	CLockObj& m_lock;
+};
+
+typedef CInterCriSec					CCriSec;
+
+typedef CLocalLock<CCriSec>				CCriSecLock;
+typedef CLocalLock<CInterCriSec>		CInterCriSecLock;
+typedef CLocalLock<CInterCriSec2>		CInterCriSecLock2;
+typedef CLocalLock<CMTX>				CMutexLock;
+typedef CLocalLock<CSpinGuard>			CSpinLock;
+typedef CLocalLock<CReentrantSpinGuard>	CReentrantSpinLock;
+typedef	CLocalLock<CFakeGuard>			CFakeLock;

+ 26 - 0
source/hook/hp-src/Event.cpp

@@ -0,0 +1,26 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+#include "Event.h"

+ 66 - 0
source/hook/hp-src/Event.h

@@ -0,0 +1,66 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+class CEvt
+{
+public:
+	CEvt(BOOL bManualReset = FALSE, BOOL bInitialState = FALSE, LPCTSTR pszName = nullptr, LPSECURITY_ATTRIBUTES pSecurity = nullptr)
+	{
+		m_hEvent = ::CreateEvent(pSecurity, bManualReset, bInitialState, pszName);
+		ASSERT(IsValid());
+	}
+
+	~CEvt()
+	{
+		if(IsValid())
+			VERIFY(::CloseHandle(m_hEvent));
+	}
+
+	BOOL Open(DWORD dwAccess, BOOL bInheritHandle, LPCTSTR pszName)
+	{
+		if(IsValid())
+			VERIFY(::CloseHandle(m_hEvent));
+
+		m_hEvent = ::OpenEvent(dwAccess, bInheritHandle, pszName);
+		return(IsValid());
+	}
+
+	BOOL Pulse()	{return(::PulseEvent(m_hEvent));}
+	BOOL Reset()	{return(::ResetEvent(m_hEvent));}
+	BOOL Set()		{return(::SetEvent(m_hEvent));}
+
+	HANDLE& GetHandle	() 	{return m_hEvent;}
+	operator HANDLE		()	{return m_hEvent;}
+	BOOL IsValid		()	{return m_hEvent != nullptr;}
+
+private:
+	CEvt(const CEvt&);
+	CEvt operator = (const CEvt&);
+
+private:
+	HANDLE m_hEvent;
+};
+

+ 234 - 0
source/hook/hp-src/GeneralHelper.h

@@ -0,0 +1,234 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/*
+
+Optional Macros:
+
+Windows:
+++++++++++++++++++++++
+_WIN32_WINNT		: Windows NT 版本	(默认:_WIN32_WINNT_WINXP / _WIN32_WINNT_WIN7)
+WINVER				: Windows 版本		(默认:_WIN32_WINNT)
+_USE_MFC			: 使用 MFC
+_WINSOCK_SUPPORT	: 支持 Windows Socket
+_NO_RIBBONS_SUPPORT	: 不支持 Ribbons 界面风格
+_DETECT_MEMORY_LEAK	: DEBUG 状态下支持内存泄露检查
+
+Windows CE:
+++++++++++++++++++++++
+WINVER				: Windows 版本
+_USE_MFC			: 使用 MFC
+_WINSOCK_SUPPORT	: 支持 Windows Socket
+_DETECT_MEMORY_LEAK	: DEBUG 状态下支持内存泄露检查
+_ONLY_DETECT_CONFIRMED_MEMORY_LEAK_	: 只报告能够确认的内存泄露(不能确定的不报告)
+---------------------------
+VC 2015
+	_MSC_VER == 1900
+VC 2013
+	_MSC_VER == 1800
+VC 2012
+	_MSC_VER == 1700
+VC 2010
+	_MSC_VER == 1600
+VC 2008
+	_MSC_VER == 1500
+VC 2005
+	_MSC_VER == 1400
+VC 7.1
+	_MSC_VER == 1310
+VC 7.0
+	_MSC_VER == 1300
+VC 6.0
+	_MSC_VER == 1200
+---------------------------
+Windows Versions:
+_WIN32_WINNT_NT4		x0400
+_WIN32_WINNT_WIN2K		0x0500
+_WIN32_WINNT_WINXP		0x0501
+_WIN32_WINNT_WS03		0x0502
+_WIN32_WINNT_WIN6		0x0600
+_WIN32_WINNT_VISTA		0x0600
+_WIN32_WINNT_WS08		0x0600
+_WIN32_WINNT_LONGHORN	0x0600
+_WIN32_WINNT_WIN7		0x0601
+_WIN32_WINNT_WIN8		0x0602
+_WIN32_WINNT_WINBLUE	0x0603
+_WIN32_WINNT_WIN10		0x0A00
+---------------------------
+*/
+
+#pragma once
+
+#ifndef VC_EXTRALEAN
+	#define VC_EXTRALEAN
+#endif
+
+#ifndef WIN32_LEAN_AND_MEAN
+	#define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifndef _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
+	#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
+#endif
+
+#if _MSC_VER >= 1400
+
+	#if defined _DEBUG && _MSC_VER < 1600
+		#ifndef _SECURE_SCL
+			#define _SECURE_SCL					0
+		#endif
+		#ifndef _HAS_ITERATOR_DEBUGGING
+			#define _HAS_ITERATOR_DEBUGGING		0
+		#endif
+	#endif
+
+	#ifndef _CRT_SECURE_NO_DEPRECATE
+		#define _CRT_SECURE_NO_DEPRECATE		1
+	#endif
+
+	#ifndef _SCL_SECURE_NO_DEPRECATE
+		#define _SCL_SECURE_NO_DEPRECATE		1
+	#endif
+
+	#ifndef _ATL_SECURE_NO_WARNINGS
+		#define _ATL_SECURE_NO_WARNINGS			1
+	#endif
+
+	#ifndef _CRT_NON_CONFORMING_SWPRINTFS
+		#define _CRT_NON_CONFORMING_SWPRINTFS	1
+	#endif
+
+	#ifndef _SECURE_ATL
+		#define _SECURE_ATL						1
+	#endif
+
+	#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
+		#define _WINSOCK_DEPRECATED_NO_WARNINGS	1
+	#endif
+
+#endif
+
+#ifndef _WIN32_WINNT
+	#if defined (_WIN64)
+		#define _WIN32_WINNT	_WIN32_WINNT_WIN7
+	#else
+		#define _WIN32_WINNT	_WIN32_WINNT_WINXP
+	#endif
+#endif
+
+#ifndef WINVER
+	#define WINVER	_WIN32_WINNT
+#endif
+
+#if _MSC_VER >= 1600
+	#include <SDKDDKVer.h>
+#else
+	#if !defined(nullptr)
+		#define nullptr	NULL
+	#endif
+#endif
+
+#ifdef _DETECT_MEMORY_LEAK
+	#ifndef _CRTDBG_MAP_ALLOC
+		#define _CRTDBG_MAP_ALLOC
+	#endif
+#endif
+
+#ifdef _USE_MFC
+
+	#ifndef _AFX_ALL_WARNINGS
+		#define _AFX_ALL_WARNINGS
+	#endif
+
+	#include <afxwin.h>
+	#include <afxext.h>
+	#include <afxdisp.h>
+
+	#ifndef _AFX_NO_OLE_SUPPORT
+		#include <afxdtctl.h>
+	#endif
+
+	#ifndef _AFX_NO_AFXCMN_SUPPORT
+		#include <afxcmn.h>
+	#endif
+
+	#ifndef _NO_RIBBONS_SUPPORT
+		#include <afxcontrolbars.h>
+	#endif
+
+#else
+
+	#include <Windows.h>
+	#include <WindowsX.h>
+	#include <commctrl.h>
+	#include <stdio.h>
+	#include <stdlib.h>
+	#include <malloc.h>
+	#include <memory.h>
+	#include <tchar.h>
+	#include <atlstr.h>
+	#include <atltime.h>
+
+	#ifndef ASSERT
+		#define ASSERT(f)	ATLASSERT(f)
+	#endif
+	#ifndef VERIFY
+		#define VERIFY(f)	ATLVERIFY(f)
+	#endif
+
+	#ifndef TRACE
+		#include <atltrace.h>
+
+		#define TRACE							AtlTrace
+		#define TRACE0(f)						TRACE(f)
+		#define TRACE1(f, p1)					TRACE(f, p1)
+		#define TRACE2(f, p1, p2)				TRACE(f, p1, p2)
+		#define TRACE3(f, p1, p2, p3)			TRACE(f, p1, p2, p3)
+		#define TRACE4(f, p1, p2, p3, p4)		TRACE(f, p1, p2, p3, p4)
+		#define TRACE5(f, p1, p2, p3, p4, p5)	TRACE(f, p1, p2, p3, p4, p5)
+	#endif
+
+#endif
+
+#ifdef _WINSOCK_SUPPORT
+	#include <winsock2.h>
+	#include <ws2tcpip.h>
+	#include <mswsock.h>
+#endif
+
+#include <atlbase.h>
+#include <atlconv.h>
+
+#include "Singleton.h"
+#include "Event.h"
+#include "Semaphore.h"
+#include "CriticalSection.h"
+#include "STLHelper.h"
+#include "Win32Helper.h"
+#include "PrivateHeap.h"
+#include "bufferptr.h"
+
+#if defined (_DEBUG) && defined (_DETECT_MEMORY_LEAK)
+	#include "debug/win32_crtdbg.h"
+#endif

+ 494 - 0
source/hook/hp-src/HPSocket.h

@@ -0,0 +1,494 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 3.6.1
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/******************************************************************************
+Module:  HPSocket
+
+Usage:
+		方法一:
+		--------------------------------------------------------------------------------------
+		0. 应用程序包含 HPTypeDef.h / SocketInterface.h / HPSocket.h 头文件
+		1. 调用 HP_Create_Xxx() 函数创建 HPSocket 对象
+		2. 使用完毕后调用 HP_Destroy_Xxx() 函数销毁 HPSocket 对象
+
+		方法二:
+		--------------------------------------------------------------------------------------
+		0. 应用程序包含 SocketInterface.h 和 HPSocket.h 头文件
+		1. 创建 CXxxPtr 智能指针,通过智能指针使用 HPSocket 对象
+
+Release:
+		<-- 动态链接库 -->
+		1. x86/HPSocket.dll				- (32位/MBCS/Release)
+		2. x86/HPSocket_D.dll			- (32位/MBCS/DeBug)
+		3. x86/HPSocket_U.dll			- (32位/UNICODE/Release)
+		4. x86/HPSocket_UD.dll			- (32位/UNICODE/DeBug)
+		5. x64/HPSocket.dll				- (64位/MBCS/Release)
+		6. x64/HPSocket_D.dll			- (64位/MBCS/DeBug)
+		7. x64/HPSocket_U.dll			- (64位/UNICODE/Release)
+		8. x64/HPSocket_UD.dll			- (64位/UNICODE/DeBug)
+
+		<-- 静态链接库 -->
+		!!注意!!:使用 HPSocket 静态库时,需要在工程属性中定义预处理宏 -> HPSOCKET_STATIC_LIB
+		1. x86/static/HPSocket.lib		- (32位/MBCS/Release)
+		2. x86/static/HPSocket_D.lib	- (32位/MBCS/DeBug)
+		3. x86/static/HPSocket_U.lib	- (32位/UNICODE/Release)
+		4. x86/static/HPSocket_UD.lib	- (32位/UNICODE/DeBug)
+		5. x64/static/HPSocket.lib		- (64位/MBCS/Release)
+		6. x64/static/HPSocket_D.lib	- (64位/MBCS/DeBug)
+		7. x64/static/HPSocket_U.lib	- (64位/UNICODE/Release)
+		8. x64/static/HPSocket_UD.lib	- (64位/UNICODE/DeBug)
+
+******************************************************************************/
+
+#pragma once
+
+/**************************************************/
+/*********** imports / exports HPSocket ***********/
+
+#ifdef HPSOCKET_STATIC_LIB
+	#define HPSOCKET_API EXTERN_C
+#else
+	#ifdef HPSOCKET_EXPORTS
+		#define HPSOCKET_API EXTERN_C __declspec(dllexport)
+	#else
+		#define HPSOCKET_API EXTERN_C __declspec(dllimport)
+	#endif
+#endif
+
+#include "SocketInterface.h"
+
+/*****************************************************************************************************************************************************/
+/****************************************************************** TCP/UDP Exports ******************************************************************/
+/*****************************************************************************************************************************************************/
+
+/**************************************************/
+/************** HPSocket 对象智能指针 **************/
+
+template<class T, class _Listener, class _Creator> class CHPSocketPtr
+{
+public:
+	CHPSocketPtr(_Listener* pListener = nullptr)
+	{
+		if(pListener)
+			m_pObj = _Creator::Create(pListener);
+		else
+			m_pObj = nullptr;
+	}
+
+	~CHPSocketPtr()
+	{
+		Reset();
+	}
+
+public:
+	CHPSocketPtr& Reset(T* pObj = nullptr)
+	{
+		if(pObj != m_pObj)
+		{
+			if(m_pObj)
+				_Creator::Destroy(m_pObj);
+
+			m_pObj = pObj;
+		}
+
+		return *this;
+	}
+
+	CHPSocketPtr& Attach(T* pObj)
+	{
+		return Reset(pObj);
+	}
+
+	T* Detach()
+	{
+		T* pObj	= m_pObj;
+		m_pObj	= nullptr;
+
+		return pObj;
+	}
+
+	BOOL IsValid	()	const	{return m_pObj != nullptr	;}
+	T* Get			()	const	{return m_pObj				;}
+	T* operator ->	()	const	{return m_pObj				;}
+	operator T*		()	const	{return m_pObj				;}
+
+	CHPSocketPtr& operator = (T* pObj)	{return Reset(pObj)	;}
+
+private:
+	CHPSocketPtr(const CHPSocketPtr&);
+	CHPSocketPtr& operator = (const CHPSocketPtr&);
+
+private:
+	T* m_pObj;
+};
+
+/**************************************************/
+/**************** HPSocket 导出函数 ****************/
+
+// 创建 ITcpServer 对象
+HPSOCKET_API ITcpServer* HP_Create_TcpServer(ITcpServerListener* pListener);
+// 创建 ITcpAgent 对象
+HPSOCKET_API ITcpAgent* HP_Create_TcpAgent(ITcpAgentListener* pListener);
+// 创建 ITcpClient 对象
+HPSOCKET_API ITcpClient* HP_Create_TcpClient(ITcpClientListener* pListener);
+// 创建 ITcpPullServer 对象
+HPSOCKET_API ITcpPullServer* HP_Create_TcpPullServer(ITcpServerListener* pListener);
+// 创建 ITcpPullAgent 对象
+HPSOCKET_API ITcpPullAgent* HP_Create_TcpPullAgent(ITcpAgentListener* pListener);
+// 创建 ITcpPullClient 对象
+HPSOCKET_API ITcpPullClient* HP_Create_TcpPullClient(ITcpClientListener* pListener);
+// 创建 ITcpPackServer 对象
+HPSOCKET_API ITcpPackServer* HP_Create_TcpPackServer(ITcpServerListener* pListener);
+// 创建 ITcpPackAgent 对象
+HPSOCKET_API ITcpPackAgent* HP_Create_TcpPackAgent(ITcpAgentListener* pListener);
+// 创建 ITcpPackClient 对象
+HPSOCKET_API ITcpPackClient* HP_Create_TcpPackClient(ITcpClientListener* pListener);
+// 创建 IUdpServer 对象
+HPSOCKET_API IUdpServer* HP_Create_UdpServer(IUdpServerListener* pListener);
+// 创建 IUdpClient 对象
+HPSOCKET_API IUdpClient* HP_Create_UdpClient(IUdpClientListener* pListener);
+// 创建 IUdpCast 对象
+HPSOCKET_API IUdpCast* HP_Create_UdpCast(IUdpCastListener* pListener);
+
+// 销毁 ITcpServer 对象
+HPSOCKET_API void HP_Destroy_TcpServer(ITcpServer* pServer);
+// 销毁 ITcpAgent 对象
+HPSOCKET_API void HP_Destroy_TcpAgent(ITcpAgent* pAgent);
+// 销毁 ITcpClient 对象
+HPSOCKET_API void HP_Destroy_TcpClient(ITcpClient* pClient);
+// 销毁 ITcpPullServer 对象
+HPSOCKET_API void HP_Destroy_TcpPullServer(ITcpPullServer* pServer);
+// 销毁 ITcpPullAgent 对象
+HPSOCKET_API void HP_Destroy_TcpPullAgent(ITcpPullAgent* pAgent);
+// 销毁 ITcpPullClient 对象
+HPSOCKET_API void HP_Destroy_TcpPullClient(ITcpPullClient* pClient);
+// 销毁 ITcpPackServer 对象
+HPSOCKET_API void HP_Destroy_TcpPackServer(ITcpPackServer* pServer);
+// 销毁 ITcpPackAgent 对象
+HPSOCKET_API void HP_Destroy_TcpPackAgent(ITcpPackAgent* pAgent);
+// 销毁 ITcpPackClient 对象
+HPSOCKET_API void HP_Destroy_TcpPackClient(ITcpPackClient* pClient);
+// 销毁 IUdpServer 对象
+HPSOCKET_API void HP_Destroy_UdpServer(IUdpServer* pServer);
+// 销毁 IUdpClient 对象
+HPSOCKET_API void HP_Destroy_UdpClient(IUdpClient* pClient);
+// 销毁 IUdpCast 对象
+HPSOCKET_API void HP_Destroy_UdpCast(IUdpCast* pCast);
+
+// ITcpServer 对象创建器
+struct TcpServer_Creator
+{
+	static ITcpServer* Create(ITcpServerListener* pListener)
+	{
+		return HP_Create_TcpServer(pListener);
+	}
+
+	static void Destroy(ITcpServer* pServer)
+	{
+		HP_Destroy_TcpServer(pServer);
+	}
+};
+
+// ITcpAgent 对象创建器
+struct TcpAgent_Creator
+{
+	static ITcpAgent* Create(ITcpAgentListener* pListener)
+	{
+		return HP_Create_TcpAgent(pListener);
+	}
+
+	static void Destroy(ITcpAgent* pAgent)
+	{
+		HP_Destroy_TcpAgent(pAgent);
+	}
+};
+
+// ITcpClient 对象创建器
+struct TcpClient_Creator
+{
+	static ITcpClient* Create(ITcpClientListener* pListener)
+	{
+		return HP_Create_TcpClient(pListener);
+	}
+
+	static void Destroy(ITcpClient* pClient)
+	{
+		HP_Destroy_TcpClient(pClient);
+	}
+};
+
+// ITcpPullServer 对象创建器
+struct TcpPullServer_Creator
+{
+	static ITcpPullServer* Create(ITcpServerListener* pListener)
+	{
+		return HP_Create_TcpPullServer(pListener);
+	}
+
+	static void Destroy(ITcpPullServer* pServer)
+	{
+		HP_Destroy_TcpPullServer(pServer);
+	}
+};
+
+// ITcpPullAgent 对象创建器
+struct TcpPullAgent_Creator
+{
+	static ITcpPullAgent* Create(ITcpAgentListener* pListener)
+	{
+		return HP_Create_TcpPullAgent(pListener);
+	}
+
+	static void Destroy(ITcpPullAgent* pAgent)
+	{
+		HP_Destroy_TcpPullAgent(pAgent);
+	}
+};
+
+// ITcpPullClient 对象创建器
+struct TcpPullClient_Creator
+{
+	static ITcpPullClient* Create(ITcpClientListener* pListener)
+	{
+		return HP_Create_TcpPullClient(pListener);
+	}
+
+	static void Destroy(ITcpPullClient* pClient)
+	{
+		HP_Destroy_TcpPullClient(pClient);
+	}
+};
+
+// ITcpPackServer 对象创建器
+struct TcpPackServer_Creator
+{
+	static ITcpPackServer* Create(ITcpServerListener* pListener)
+	{
+		return HP_Create_TcpPackServer(pListener);
+	}
+
+	static void Destroy(ITcpPackServer* pServer)
+	{
+		HP_Destroy_TcpPackServer(pServer);
+	}
+};
+
+// ITcpPackAgent 对象创建器
+struct TcpPackAgent_Creator
+{
+	static ITcpPackAgent* Create(ITcpAgentListener* pListener)
+	{
+		return HP_Create_TcpPackAgent(pListener);
+	}
+
+	static void Destroy(ITcpPackAgent* pAgent)
+	{
+		HP_Destroy_TcpPackAgent(pAgent);
+	}
+};
+
+// ITcpPackClient 对象创建器
+struct TcpPackClient_Creator
+{
+	static ITcpPackClient* Create(ITcpClientListener* pListener)
+	{
+		return HP_Create_TcpPackClient(pListener);
+	}
+
+	static void Destroy(ITcpPackClient* pClient)
+	{
+		HP_Destroy_TcpPackClient(pClient);
+	}
+};
+
+// IUdpServer 对象创建器
+struct UdpServer_Creator
+{
+	static IUdpServer* Create(IUdpServerListener* pListener)
+	{
+		return HP_Create_UdpServer(pListener);
+	}
+
+	static void Destroy(IUdpServer* pServer)
+	{
+		HP_Destroy_UdpServer(pServer);
+	}
+};
+
+// IUdpClient 对象创建器
+struct UdpClient_Creator
+{
+	static IUdpClient* Create(IUdpClientListener* pListener)
+	{
+		return HP_Create_UdpClient(pListener);
+	}
+
+	static void Destroy(IUdpClient* pClient)
+	{
+		HP_Destroy_UdpClient(pClient);
+	}
+};
+
+// IUdpClient 对象创建器
+struct UdpCast_Creator
+{
+	static IUdpCast* Create(IUdpCastListener* pListener)
+	{
+		return HP_Create_UdpCast(pListener);
+	}
+
+	static void Destroy(IUdpCast* pCast)
+	{
+		HP_Destroy_UdpCast(pCast);
+	}
+};
+
+// ITcpServer 对象智能指针
+typedef CHPSocketPtr<ITcpServer, ITcpServerListener, TcpServer_Creator>			CTcpServerPtr;
+// ITcpAgent 对象智能指针
+typedef CHPSocketPtr<ITcpAgent, ITcpAgentListener, TcpAgent_Creator>			CTcpAgentPtr;
+// ITcpClient 对象智能指针
+typedef CHPSocketPtr<ITcpClient, ITcpClientListener, TcpClient_Creator>			CTcpClientPtr;
+// ITcpPullServer 对象智能指针
+typedef CHPSocketPtr<ITcpPullServer, ITcpServerListener, TcpPullServer_Creator>	CTcpPullServerPtr;
+// ITcpPullAgent 对象智能指针
+typedef CHPSocketPtr<ITcpPullAgent, ITcpAgentListener, TcpPullAgent_Creator>	CTcpPullAgentPtr;
+// ITcpPullClient 对象智能指针
+typedef CHPSocketPtr<ITcpPullClient, ITcpClientListener, TcpPullClient_Creator>	CTcpPullClientPtr;
+// ITcpPackServer 对象智能指针
+typedef CHPSocketPtr<ITcpPackServer, ITcpServerListener, TcpPackServer_Creator>	CTcpPackServerPtr;
+// ITcpPackAgent 对象智能指针
+typedef CHPSocketPtr<ITcpPackAgent, ITcpAgentListener, TcpPackAgent_Creator>	CTcpPackAgentPtr;
+// ITcpPackClient 对象智能指针
+typedef CHPSocketPtr<ITcpPackClient, ITcpClientListener, TcpPackClient_Creator>	CTcpPackClientPtr;
+// IUdpServer 对象智能指针
+typedef CHPSocketPtr<IUdpServer, IUdpServerListener, UdpServer_Creator>			CUdpServerPtr;
+// IUdpClient 对象智能指针
+typedef CHPSocketPtr<IUdpClient, IUdpClientListener, UdpClient_Creator>			CUdpClientPtr;
+// IUdpCast 对象智能指针
+typedef CHPSocketPtr<IUdpCast, IUdpCastListener, UdpCast_Creator>				CUdpCastPtr;
+
+/*****************************************************************************************************************************************************/
+/******************************************************************** HTTP Exports *******************************************************************/
+/*****************************************************************************************************************************************************/
+
+// 创建 IHttpServer 对象
+HPSOCKET_API IHttpServer* HP_Create_HttpServer(IHttpServerListener* pListener);
+// 创建 IHttpAgent 对象
+HPSOCKET_API IHttpAgent* HP_Create_HttpAgent(IHttpAgentListener* pListener);
+// 创建 IHttpClient 对象
+HPSOCKET_API IHttpClient* HP_Create_HttpClient(IHttpClientListener* pListener);
+
+// 销毁 IHttpServer 对象
+HPSOCKET_API void HP_Destroy_HttpServer(IHttpServer* pServer);
+// 销毁 IHttpAgent 对象
+HPSOCKET_API void HP_Destroy_HttpAgent(IHttpAgent* pAgent);
+// 销毁 IHttpClient 对象
+HPSOCKET_API void HP_Destroy_HttpClient(IHttpClient* pClient);
+
+// IHttpServer 对象创建器
+struct HttpServer_Creator
+{
+	static IHttpServer* Create(IHttpServerListener* pListener)
+	{
+		return HP_Create_HttpServer(pListener);
+	}
+
+	static void Destroy(IHttpServer* pServer)
+	{
+		HP_Destroy_HttpServer(pServer);
+	}
+};
+
+// IHttpAgent 对象创建器
+struct HttpAgent_Creator
+{
+	static IHttpAgent* Create(IHttpAgentListener* pListener)
+	{
+		return HP_Create_HttpAgent(pListener);
+	}
+
+	static void Destroy(IHttpAgent* pAgent)
+	{
+		HP_Destroy_HttpAgent(pAgent);
+	}
+};
+
+// IHttpClient 对象创建器
+struct HttpClient_Creator
+{
+	static IHttpClient* Create(IHttpClientListener* pListener)
+	{
+		return HP_Create_HttpClient(pListener);
+	}
+
+	static void Destroy(IHttpClient* pClient)
+	{
+		HP_Destroy_HttpClient(pClient);
+	}
+};
+
+// IHttpServer 对象智能指针
+typedef CHPSocketPtr<IHttpServer, IHttpServerListener, HttpServer_Creator>		CHttpServerPtr;
+// IHttpAgent 对象智能指针
+typedef CHPSocketPtr<IHttpAgent, IHttpAgentListener, HttpAgent_Creator>			CHttpAgentPtr;
+// IHttpClient 对象智能指针
+typedef CHPSocketPtr<IHttpClient, IHttpClientListener, HttpClient_Creator>		CHttpClientPtr;
+
+/*****************************************************************************************************************************************************/
+/*************************************************************** Global Function Exports *************************************************************/
+/*****************************************************************************************************************************************************/
+
+// 获取错误描述文本
+HPSOCKET_API LPCTSTR HP_GetSocketErrorDesc(EnSocketError enCode);
+// 调用系统的 GetLastError() 方法获取系统错误代码
+HPSOCKET_API DWORD SYS_GetLastError	();
+// 调用系统的 WSAGetLastError() 方法获取系统错误代码
+HPSOCKET_API int SYS_WSAGetLastError();
+// 调用系统的 setsockopt()
+HPSOCKET_API int SYS_SetSocketOption(SOCKET sock, int level, int name, LPVOID val, int len);
+// 调用系统的 getsockopt()
+HPSOCKET_API int SYS_GetSocketOption(SOCKET sock, int level, int name, LPVOID val, int* len);
+// 调用系统的 ioctlsocket()
+HPSOCKET_API int SYS_IoctlSocket(SOCKET sock, long cmd, u_long* arg);
+// 调用系统的 WSAIoctl()
+HPSOCKET_API int SYS_WSAIoctl(SOCKET sock, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned);
+
+// 设置 socket 选项:IPPROTO_TCP -> TCP_NODELAY
+HPSOCKET_API int SYS_SSO_NoDelay(SOCKET sock, BOOL bNoDelay);
+// 设置 socket 选项:SOL_SOCKET -> SO_DONTLINGER
+HPSOCKET_API int SYS_SSO_DontLinger(SOCKET sock, BOOL bDont);
+// 设置 socket 选项:SOL_SOCKET -> SO_LINGER
+HPSOCKET_API int SYS_SSO_Linger(SOCKET sock, USHORT l_onoff, USHORT l_linger);
+// 设置 socket 选项:SOL_SOCKET -> SO_RCVBUF
+HPSOCKET_API int SYS_SSO_RecvBuffSize(SOCKET sock, int size);
+// 设置 socket 选项:SOL_SOCKET -> SO_SNDBUF
+HPSOCKET_API int SYS_SSO_SendBuffSize(SOCKET sock, int size);
+// 设置 socket 选项:SOL_SOCKET -> SO_REUSEADDR
+HPSOCKET_API int SYS_SSO_ReuseAddress(SOCKET sock, BOOL bReuse);
+
+// 获取 SOCKET 本地地址信息
+HPSOCKET_API BOOL SYS_GetSocketLocalAddress(SOCKET socket, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);
+// 获取 SOCKET 远程地址信息
+HPSOCKET_API BOOL SYS_GetSocketRemoteAddress(SOCKET socket, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);

+ 1556 - 0
source/hook/hp-src/HPSocket4C.h

@@ -0,0 +1,1556 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 3.6.1
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/******************************************************************************
+Module:  HPSocket for C
+
+Desc: 导出纯 C 函数,让其它语言(如:C / C# / Delphi 等)能方便地使用 HPSocket
+
+Usage:
+		方法一:
+		--------------------------------------------------------------------------------------
+		0. (C/C++ 程序)包含 HPTypeDef.h / HPSocket4C.h 头文件
+		1. 调用 ::Create_HP_XxxListener() 函数创建监听器对象
+		2. 调用 ::Create_HP_Xxx(pListener) 函数创建 HPSocket 对象
+		3. 调用 ::HP_Set_FN_Xxx_OnYyy(pListener, ...) 函数设置监听器的回调函数
+		4. 调用相关导出函数操作 HPSocket 对象
+		5. ...... ......
+		6. 调用 ::Destroy_HP_Xxx(pSocket) 函数销毁 HPSocket 对象
+		7. 调用 ::Destroy_HP_XxxListener(pListener) 函数销毁监听器对象
+
+		方法二:
+		--------------------------------------------------------------------------------------
+		1. 应用程序把需要用到的导出函数封装到特定语言的包装类中
+		2. 通过包装类封装后,以面向对象的方式使用 HPSocket
+
+Release:
+		<-- 动态链接库 -->
+		1. x86/HPSocket4C.dll			- (32位/MBCS/Release)
+		2. x86/HPSocket4C_D.dll			- (32位/MBCS/DeBug)
+		3. x86/HPSocket4C_U.dll			- (32位/UNICODE/Release)
+		4. x86/HPSocket4C_UD.dll		- (32位/UNICODE/DeBug)
+		5. x64/HPSocket4C.dll			- (64位/MBCS/Release)
+		6. x64/HPSocket4C_D.dll			- (64位/MBCS/DeBug)
+		7. x64/HPSocket4C_U.dll			- (64位/UNICODE/Release)
+		8. x64/HPSocket4C_UD.dll		- (64位/UNICODE/DeBug)
+
+		<-- 静态链接库 -->
+		!!注意!!:使用 HPSocket 静态库时,需要在工程属性中定义预处理宏 -> HPSOCKET_STATIC_LIB
+		1. x86/static/HPSocket4C.lib	- (32位/MBCS/Release)
+		2. x86/static/HPSocket4C_D.lib	- (32位/MBCS/DeBug)
+		3. x86/static/HPSocket4C_U.lib	- (32位/UNICODE/Release)
+		4. x86/static/HPSocket4C_UD.lib	- (32位/UNICODE/DeBug)
+		5. x64/static/HPSocket4C.lib	- (64位/MBCS/Release)
+		6. x64/static/HPSocket4C_D.lib	- (64位/MBCS/DeBug)
+		7. x64/static/HPSocket4C_U.lib	- (64位/UNICODE/Release)
+		8. x64/static/HPSocket4C_UD.lib	- (64位/UNICODE/DeBug)
+
+******************************************************************************/
+
+#pragma once
+
+#include <winsock2.h>
+
+#include "HPTypeDef.h"
+
+/**************************************************/
+/********** imports / exports HPSocket4C **********/
+
+#ifdef HPSOCKET_STATIC_LIB
+	#define HPSOCKET_API EXTERN_C
+#else
+	#ifdef HPSOCKET_EXPORTS
+		#define HPSOCKET_API EXTERN_C __declspec(dllexport)
+	#else
+		#define HPSOCKET_API EXTERN_C __declspec(dllimport)
+	#endif
+#endif
+
+/************************************************************************
+名称:定义 Socket 对象指针类型别名
+描述:把 Socket 对象指针定义为更直观的别名
+************************************************************************/
+
+typedef PVOID		HP_Object;
+
+typedef HP_Object	HP_Server;
+typedef HP_Object	HP_Agent;
+typedef HP_Object	HP_Client;
+typedef HP_Object	HP_TcpServer;
+typedef HP_Object	HP_TcpAgent;
+typedef HP_Object	HP_TcpClient;
+typedef HP_Object	HP_PullSocket;
+typedef HP_Object	HP_PullClient;
+typedef HP_Object	HP_TcpPullServer;
+typedef HP_Object	HP_TcpPullAgent;
+typedef HP_Object	HP_TcpPullClient;
+typedef HP_Object	HP_PackSocket;
+typedef HP_Object	HP_PackClient;
+typedef HP_Object	HP_TcpPackServer;
+typedef HP_Object	HP_TcpPackAgent;
+typedef HP_Object	HP_TcpPackClient;
+typedef HP_Object	HP_UdpServer;
+typedef HP_Object	HP_UdpClient;
+typedef HP_Object	HP_UdpCast;
+
+typedef HP_Object	HP_Listener;
+typedef HP_Object	HP_ServerListener;
+typedef HP_Object	HP_AgentListener;
+typedef HP_Object	HP_ClientListener;
+typedef HP_Object	HP_TcpServerListener;
+typedef HP_Object	HP_TcpAgentListener;
+typedef HP_Object	HP_TcpClientListener;
+typedef HP_Object	HP_PullSocketListener;
+typedef HP_Object	HP_PullClientListener;
+typedef HP_Object	HP_TcpPullServerListener;
+typedef HP_Object	HP_TcpPullAgentListener;
+typedef HP_Object	HP_TcpPullClientListener;
+typedef HP_Object	HP_UdpServerListener;
+typedef HP_Object	HP_UdpClientListener;
+typedef HP_Object	HP_UdpCastListener;
+
+typedef HP_Object	HP_HttpServer;
+typedef HP_Object	HP_HttpAgent;
+typedef HP_Object	HP_HttpClient;
+
+typedef HP_Object	HP_HttpServerListener;
+typedef HP_Object	HP_HttpAgentListener;
+typedef HP_Object	HP_HttpClientListener;
+
+/*****************************************************************************************************************************************************/
+/****************************************************************** TCP/UDP Exports ******************************************************************/
+/*****************************************************************************************************************************************************/
+
+/****************************************************/
+/***************** TCP/UDP 回调函数 ******************/
+
+/* Server 回调函数 */
+typedef En_HP_HandleResult (__stdcall *HP_FN_Server_OnPrepareListen)	(UINT_PTR soListen);
+// 如果为 TCP 连接,pClient为 SOCKET 句柄;如果为 UDP 连接,pClient为 SOCKADDR_IN 指针;
+typedef En_HP_HandleResult (__stdcall *HP_FN_Server_OnAccept)			(HP_CONNID dwConnID, UINT_PTR pClient);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Server_OnHandShake)		(HP_CONNID dwConnID);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Server_OnSend)				(HP_CONNID dwConnID, const BYTE* pData, int iLength);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Server_OnReceive)			(HP_CONNID dwConnID, const BYTE* pData, int iLength);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Server_OnPullReceive)		(HP_CONNID dwConnID, int iLength);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Server_OnClose)			(HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Server_OnShutdown)			();
+
+/* Agent 回调函数 */
+typedef En_HP_HandleResult (__stdcall *HP_FN_Agent_OnPrepareConnect)	(HP_CONNID dwConnID, UINT_PTR socket);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Agent_OnConnect)			(HP_CONNID dwConnID);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Agent_OnHandShake)			(HP_CONNID dwConnID);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Agent_OnSend)				(HP_CONNID dwConnID, const BYTE* pData, int iLength);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Agent_OnReceive)			(HP_CONNID dwConnID, const BYTE* pData, int iLength);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Agent_OnPullReceive)		(HP_CONNID dwConnID, int iLength);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Agent_OnClose)				(HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Agent_OnShutdown)			();
+
+/* Client 回调函数 */
+typedef En_HP_HandleResult (__stdcall *HP_FN_Client_OnPrepareConnect)	(HP_Client pClient, UINT_PTR socket);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Client_OnConnect)			(HP_Client pClient);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Client_OnHandShake)		(HP_Client pClient);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Client_OnSend)				(HP_Client pClient, const BYTE* pData, int iLength);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Client_OnReceive)			(HP_Client pClient, const BYTE* pData, int iLength);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Client_OnPullReceive)		(HP_Client pClient, int iLength);
+typedef En_HP_HandleResult (__stdcall *HP_FN_Client_OnClose)			(HP_Client pClient, En_HP_SocketOperation enOperation, int iErrorCode);
+
+/****************************************************/
+/*************** TCP/UDP 对象创建函数 ****************/
+
+// 创建 HP_TcpServer 对象
+HPSOCKET_API HP_TcpServer __stdcall Create_HP_TcpServer(HP_TcpServerListener pListener);
+// 创建 HP_TcpAgent 对象
+HPSOCKET_API HP_TcpAgent __stdcall Create_HP_TcpAgent(HP_TcpAgentListener pListener);
+// 创建 HP_TcpClient 对象
+HPSOCKET_API HP_TcpClient __stdcall Create_HP_TcpClient(HP_TcpClientListener pListener);
+// 创建 HP_TcpPullServer 对象
+HPSOCKET_API HP_TcpPullServer __stdcall Create_HP_TcpPullServer(HP_TcpPullServerListener pListener);
+// 创建 HP_TcpPullAgent 对象
+HPSOCKET_API HP_TcpPullAgent __stdcall Create_HP_TcpPullAgent(HP_TcpPullAgentListener pListener);
+// 创建 HP_TcpPullClient 对象
+HPSOCKET_API HP_TcpPullClient __stdcall Create_HP_TcpPullClient(HP_TcpPullClientListener pListener);
+// 创建 HP_TcpPackServer 对象
+HPSOCKET_API HP_TcpPackServer __stdcall Create_HP_TcpPackServer(HP_TcpServerListener pListener);
+// 创建 HP_TcpPackAgent 对象
+HPSOCKET_API HP_TcpPackAgent __stdcall Create_HP_TcpPackAgent(HP_TcpAgentListener pListener);
+// 创建 HP_TcpPackClient 对象
+HPSOCKET_API HP_TcpPackClient __stdcall Create_HP_TcpPackClient(HP_TcpClientListener pListener);
+// 创建 HP_UdpServer 对象
+HPSOCKET_API HP_UdpServer __stdcall Create_HP_UdpServer(HP_UdpServerListener pListener);
+// 创建 HP_UdpClient 对象
+HPSOCKET_API HP_UdpClient __stdcall Create_HP_UdpClient(HP_UdpClientListener pListener);
+// 创建 HP_UdpCast 对象
+HPSOCKET_API HP_UdpCast __stdcall Create_HP_UdpCast(HP_UdpCastListener pListener);
+
+// 销毁 HP_TcpServer 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpServer(HP_TcpServer pServer);
+// 销毁 HP_TcpAgent 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpAgent(HP_TcpAgent pAgent);
+// 销毁 HP_TcpClient 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpClient(HP_TcpClient pClient);
+// 销毁 HP_TcpPullServer 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpPullServer(HP_TcpPullServer pServer);
+// 销毁 HP_TcpPullAgent 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpPullAgent(HP_TcpPullAgent pAgent);
+// 销毁 HP_TcpPullClient 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpPullClient(HP_TcpPullClient pClient);
+// 销毁 HP_TcpPackServer 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpPackServer(HP_TcpPackServer pServer);
+// 销毁 HP_TcpPackAgent 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpPackAgent(HP_TcpPackAgent pAgent);
+// 销毁 HP_TcpPackClient 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpPackClient(HP_TcpPackClient pClient);
+// 销毁 HP_UdpServer 对象
+HPSOCKET_API void __stdcall Destroy_HP_UdpServer(HP_UdpServer pServer);
+// 销毁 HP_UdpClient 对象
+HPSOCKET_API void __stdcall Destroy_HP_UdpClient(HP_UdpClient pClient);
+// 销毁 HP_UdpCast 对象
+HPSOCKET_API void __stdcall Destroy_HP_UdpCast(HP_UdpCast pCast);
+
+// 创建 HP_TcpServerListener 对象
+HPSOCKET_API HP_TcpServerListener __stdcall Create_HP_TcpServerListener();
+// 创建 HP_TcpAgentListener 对象
+HPSOCKET_API HP_TcpAgentListener __stdcall Create_HP_TcpAgentListener();
+// 创建 HP_TcpClientListener 对象
+HPSOCKET_API HP_TcpClientListener __stdcall Create_HP_TcpClientListener();
+// 创建 HP_TcpPullServerListener 对象
+HPSOCKET_API HP_TcpPullServerListener __stdcall Create_HP_TcpPullServerListener();
+// 创建 HP_TcpPullAgentListener 对象
+HPSOCKET_API HP_TcpPullAgentListener __stdcall Create_HP_TcpPullAgentListener();
+// 创建 HP_TcpPullClientListener 对象
+HPSOCKET_API HP_TcpPullClientListener __stdcall Create_HP_TcpPullClientListener();
+// 创建 HP_UdpServerListener 对象
+HPSOCKET_API HP_UdpServerListener __stdcall Create_HP_UdpServerListener();
+// 创建 HP_UdpClientListener 对象
+HPSOCKET_API HP_UdpClientListener __stdcall Create_HP_UdpClientListener();
+// 创建 HP_UdpCastListener 对象
+HPSOCKET_API HP_UdpCastListener __stdcall Create_HP_UdpCastListener();
+
+// 销毁 HP_TcpServerListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpServerListener(HP_TcpServerListener pListener);
+// 销毁 HP_TcpAgentListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpAgentListener(HP_TcpAgentListener pListener);
+// 销毁 HP_TcpClientListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpClientListener(HP_TcpClientListener pListener);
+// 销毁 HP_TcpPullServerListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpPullServerListener(HP_TcpPullServerListener pListener);
+// 销毁 HP_TcpPullAgentListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpPullAgentListener(HP_TcpPullAgentListener pListener);
+// 销毁 HP_TcpPullClientListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_TcpPullClientListener(HP_TcpPullClientListener pListener);
+// 销毁 HP_UdpServerListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_UdpServerListener(HP_UdpServerListener pListener);
+// 销毁 HP_UdpClientListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_UdpClientListener(HP_UdpClientListener pListener);
+// 销毁 HP_UdpCastListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_UdpCastListener(HP_UdpCastListener pListener);
+
+/**********************************************************************************/
+/***************************** Server 回调函数设置方法 *****************************/
+
+HPSOCKET_API void __stdcall HP_Set_FN_Server_OnPrepareListen(HP_ServerListener pListener	, HP_FN_Server_OnPrepareListen fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Server_OnAccept(HP_ServerListener pListener			, HP_FN_Server_OnAccept fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Server_OnHandShake(HP_ServerListener pListener		, HP_FN_Server_OnHandShake fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Server_OnSend(HP_ServerListener pListener				, HP_FN_Server_OnSend fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Server_OnReceive(HP_ServerListener pListener			, HP_FN_Server_OnReceive fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Server_OnPullReceive(HP_ServerListener pListener		, HP_FN_Server_OnPullReceive fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Server_OnClose(HP_ServerListener pListener			, HP_FN_Server_OnClose fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Server_OnShutdown(HP_ServerListener pListener			, HP_FN_Server_OnShutdown fn);
+
+/**********************************************************************************/
+/****************************** Agent 回调函数设置方法 *****************************/
+
+HPSOCKET_API void __stdcall HP_Set_FN_Agent_OnPrepareConnect(HP_AgentListener pListener		, HP_FN_Agent_OnPrepareConnect fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Agent_OnConnect(HP_AgentListener pListener			, HP_FN_Agent_OnConnect fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Agent_OnHandShake(HP_AgentListener pListener			, HP_FN_Agent_OnHandShake fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Agent_OnSend(HP_AgentListener pListener				, HP_FN_Agent_OnSend fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Agent_OnReceive(HP_AgentListener pListener			, HP_FN_Agent_OnReceive fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Agent_OnPullReceive(HP_AgentListener pListener		, HP_FN_Agent_OnPullReceive fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Agent_OnClose(HP_AgentListener pListener				, HP_FN_Agent_OnClose fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Agent_OnShutdown(HP_AgentListener pListener			, HP_FN_Agent_OnShutdown fn);
+
+/**********************************************************************************/
+/***************************** Client 回调函数设置方法 *****************************/
+
+HPSOCKET_API void __stdcall HP_Set_FN_Client_OnPrepareConnect(HP_ClientListener pListener	, HP_FN_Client_OnPrepareConnect fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Client_OnConnect(HP_ClientListener pListener			, HP_FN_Client_OnConnect fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Client_OnHandShake(HP_ClientListener pListener		, HP_FN_Client_OnHandShake fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Client_OnSend(HP_ClientListener pListener				, HP_FN_Client_OnSend fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Client_OnReceive(HP_ClientListener pListener			, HP_FN_Client_OnReceive fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Client_OnPullReceive(HP_ClientListener pListener		, HP_FN_Client_OnPullReceive fn);
+HPSOCKET_API void __stdcall HP_Set_FN_Client_OnClose(HP_ClientListener pListener			, HP_FN_Client_OnClose fn);
+
+/**************************************************************************/
+/***************************** Server 操作方法 *****************************/
+
+/*
+* 名称:启动通信组件
+* 描述:启动服务端通信组件,启动完成后可开始接收客户端连接并收发数据
+*		
+* 参数:		lpszBindAddress	-- 监听地址
+*			usPort			-- 监听端口
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 HP_Server_GetLastError() 获取错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Server_Start(HP_Server pServer, LPCTSTR lpszBindAddress, USHORT usPort);
+
+/*
+* 名称:关闭通信组件
+* 描述:关闭服务端通信组件,关闭完成后断开所有客户端连接并释放所有资源
+*		
+* 参数:	
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 HP_Server_GetLastError() 获取错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Server_Stop(HP_Server pServer);
+
+/*
+* 名称:发送数据
+* 描述:向指定连接发送数据
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pBuffer		-- 发送缓冲区
+*			iLength		-- 发送缓冲区长度
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Server_Send(HP_Server pServer, HP_CONNID dwConnID, const BYTE* pBuffer, int iLength);
+
+/*
+* 名称:发送数据
+* 描述:向指定连接发送数据
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pBuffer		-- 发送缓冲区
+*			iLength		-- 发送缓冲区长度
+*			iOffset		-- 发送缓冲区指针偏移量
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Server_SendPart(HP_Server pServer, HP_CONNID dwConnID, const BYTE* pBuffer, int iLength, int iOffset);
+
+/*
+* 名称:发送多组数据
+* 描述:向指定连接发送多组数据
+*		TCP - 顺序发送所有数据包 
+*		UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) 
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pBuffers	-- 发送缓冲区数组
+*			iCount		-- 发送缓冲区数目
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Server_SendPackets(HP_Server pServer, HP_CONNID dwConnID, const WSABUF pBuffers[], int iCount);
+
+/*
+* 名称:断开连接
+* 描述:断开与某个客户端的连接
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			bForce		-- 是否强制断开连接
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败
+*/
+HPSOCKET_API BOOL __stdcall HP_Server_Disconnect(HP_Server pServer, HP_CONNID dwConnID, BOOL bForce);
+
+/*
+* 名称:断开超时连接
+* 描述:断开超过指定时长的连接
+*		
+* 参数:		dwPeriod	-- 时长(毫秒)
+*			bForce		-- 是否强制断开连接
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败
+*/
+HPSOCKET_API BOOL __stdcall HP_Server_DisconnectLongConnections(HP_Server pServer, DWORD dwPeriod, BOOL bForce);
+
+/*
+* 名称:断开静默连接
+* 描述:断开超过指定时长的静默连接
+*		
+* 参数:		dwPeriod	-- 时长(毫秒)
+*			bForce		-- 是否强制断开连接
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败
+*/
+HPSOCKET_API BOOL __stdcall HP_Server_DisconnectSilenceConnections(HP_Server pServer, DWORD dwPeriod, BOOL bForce);
+
+/******************************************************************************/
+/***************************** Server 属性访问方法 *****************************/
+
+/*
+* 名称:设置连接的附加数据
+* 描述:是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pv			-- 数据
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败(无效的连接 ID)
+*/
+HPSOCKET_API BOOL __stdcall HP_Server_SetConnectionExtra(HP_Server pServer, HP_CONNID dwConnID, PVOID pExtra);
+
+/*
+* 名称:获取连接的附加数据
+* 描述:是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			ppv			-- 数据指针
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败(无效的连接 ID)
+*/
+HPSOCKET_API BOOL __stdcall HP_Server_GetConnectionExtra(HP_Server pServer, HP_CONNID dwConnID, PVOID* ppExtra);
+
+/* 检查通信组件是否已启动 */
+HPSOCKET_API BOOL __stdcall HP_Server_HasStarted(HP_Server pServer);
+/* 查看通信组件当前状态 */
+HPSOCKET_API En_HP_ServiceState __stdcall HP_Server_GetState(HP_Server pServer);
+/* 获取最近一次失败操作的错误代码 */
+HPSOCKET_API En_HP_SocketError __stdcall HP_Server_GetLastError(HP_Server pServer);
+/* 获取最近一次失败操作的错误描述 */
+HPSOCKET_API LPCTSTR __stdcall HP_Server_GetLastErrorDesc(HP_Server pServer);
+/* 获取连接中未发出数据的长度 */
+HPSOCKET_API BOOL __stdcall HP_Server_GetPendingDataLength(HP_Server pServer, HP_CONNID dwConnID, int* piPending);
+/* 获取客户端连接数 */
+HPSOCKET_API DWORD __stdcall HP_Server_GetConnectionCount(HP_Server pServer);
+/* 获取所有连接的 HP_CONNID */
+HPSOCKET_API BOOL __stdcall HP_Server_GetAllConnectionIDs(HP_Server pServer, HP_CONNID pIDs[], DWORD* pdwCount);
+/* 获取某个客户端连接时长(毫秒) */
+HPSOCKET_API BOOL __stdcall HP_Server_GetConnectPeriod(HP_Server pServer, HP_CONNID dwConnID, DWORD* pdwPeriod);
+/* 获取某个连接静默时间(毫秒) */
+HPSOCKET_API BOOL __stdcall HP_Server_GetSilencePeriod(HP_Server pServer, HP_CONNID dwConnID, DWORD* pdwPeriod);
+/* 获取监听 Socket 的地址信息 */
+HPSOCKET_API BOOL __stdcall HP_Server_GetListenAddress(HP_Server pServer, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);
+/* 获取某个连接的本地地址信息 */
+HPSOCKET_API BOOL __stdcall HP_Server_GetLocalAddress(HP_Server pServer, HP_CONNID dwConnID, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);
+/* 获取某个连接的远程地址信息 */
+HPSOCKET_API BOOL __stdcall HP_Server_GetRemoteAddress(HP_Server pServer, HP_CONNID dwConnID, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);
+
+/* 设置数据发送策略 */
+HPSOCKET_API void __stdcall HP_Server_SetSendPolicy(HP_Server pServer, En_HP_SendPolicy enSendPolicy);
+/* 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) */
+HPSOCKET_API void __stdcall HP_Server_SetFreeSocketObjLockTime(HP_Server pServer, DWORD dwFreeSocketObjLockTime);
+/* 设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) */
+HPSOCKET_API void __stdcall HP_Server_SetFreeSocketObjPool(HP_Server pServer, DWORD dwFreeSocketObjPool);
+/* 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) */
+HPSOCKET_API void __stdcall HP_Server_SetFreeBufferObjPool(HP_Server pServer, DWORD dwFreeBufferObjPool);
+/* 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) */
+HPSOCKET_API void __stdcall HP_Server_SetFreeSocketObjHold(HP_Server pServer, DWORD dwFreeSocketObjHold);
+/* 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) */
+HPSOCKET_API void __stdcall HP_Server_SetFreeBufferObjHold(HP_Server pServer, DWORD dwFreeBufferObjHold);
+/* 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大)*/
+HPSOCKET_API void __stdcall HP_Server_SetMaxConnectionCount(HP_Server pServer, DWORD dwMaxConnectionCount);
+/* 设置工作线程数量(通常设置为 2 * CPU + 2) */
+HPSOCKET_API void __stdcall HP_Server_SetWorkerThreadCount(HP_Server pServer, DWORD dwWorkerThreadCount);
+/* 设置是否标记静默时间(设置为 TRUE 时 DisconnectSilenceConnections() 和 GetSilencePeriod() 才有效,默认:TRUE) */
+HPSOCKET_API void __stdcall HP_Server_SetMarkSilence(HP_Server pServer, BOOL bMarkSilence);
+
+/* 获取数据发送策略 */
+HPSOCKET_API En_HP_SendPolicy __stdcall HP_Server_GetSendPolicy(HP_Server pServer);
+/* 获取 Socket 缓存对象锁定时间 */
+HPSOCKET_API DWORD __stdcall HP_Server_GetFreeSocketObjLockTime(HP_Server pServer);
+/* 获取 Socket 缓存池大小 */
+HPSOCKET_API DWORD __stdcall HP_Server_GetFreeSocketObjPool(HP_Server pServer);
+/* 获取内存块缓存池大小 */
+HPSOCKET_API DWORD __stdcall HP_Server_GetFreeBufferObjPool(HP_Server pServer);
+/* 获取 Socket 缓存池回收阀值 */
+HPSOCKET_API DWORD __stdcall HP_Server_GetFreeSocketObjHold(HP_Server pServer);
+/* 获取内存块缓存池回收阀值 */
+HPSOCKET_API DWORD __stdcall HP_Server_GetFreeBufferObjHold(HP_Server pServer);
+/* 获取最大连接数 */
+HPSOCKET_API DWORD __stdcall HP_Server_GetMaxConnectionCount(HP_Server pServer);
+/* 获取工作线程数量 */
+HPSOCKET_API DWORD __stdcall HP_Server_GetWorkerThreadCount(HP_Server pServer);
+/* 检测是否标记静默时间 */
+HPSOCKET_API BOOL __stdcall HP_Server_IsMarkSilence(HP_Server pServer);
+
+/**********************************************************************************/
+/******************************* TCP Server 操作方法 *******************************/
+
+/*
+* 名称:发送小文件
+* 描述:向指定连接发送 4096 KB 以下的小文件
+*		
+* 参数:		dwConnID		-- 连接 ID
+*			lpszFileName	-- 文件路径
+*			pHead			-- 头部附加数据
+*			pTail			-- 尾部附加数据
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_TcpServer_SendSmallFile(HP_Server pServer, HP_CONNID dwConnID, LPCTSTR lpszFileName, const LPWSABUF pHead, const LPWSABUF pTail);
+
+/**********************************************************************************/
+/***************************** TCP Server 属性访问方法 *****************************/
+
+/* 设置监听 Socket 的等候队列大小(根据并发连接数量调整设置) */
+HPSOCKET_API void __stdcall HP_TcpServer_SetSocketListenQueue(HP_TcpServer pServer, DWORD dwSocketListenQueue);
+/* 设置 Accept 预投递数量(根据负载调整设置,Accept 预投递数量越大则支持的并发连接请求越多) */
+HPSOCKET_API void __stdcall HP_TcpServer_SetAcceptSocketCount(HP_TcpServer pServer, DWORD dwAcceptSocketCount);
+/* 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) */
+HPSOCKET_API void __stdcall HP_TcpServer_SetSocketBufferSize(HP_TcpServer pServer, DWORD dwSocketBufferSize);
+/* 设置正常心跳包间隔(毫秒,0 则不发送心跳包,默认:30 * 1000) */
+HPSOCKET_API void __stdcall HP_TcpServer_SetKeepAliveTime(HP_TcpServer pServer, DWORD dwKeepAliveTime);
+/* 设置异常心跳包间隔(毫秒,0 不发送心跳包,,默认:10 * 1000,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) */
+HPSOCKET_API void __stdcall HP_TcpServer_SetKeepAliveInterval(HP_TcpServer pServer, DWORD dwKeepAliveInterval);
+
+/* 获取 Accept 预投递数量 */
+HPSOCKET_API DWORD __stdcall HP_TcpServer_GetAcceptSocketCount(HP_TcpServer pServer);
+/* 获取通信数据缓冲区大小 */
+HPSOCKET_API DWORD __stdcall HP_TcpServer_GetSocketBufferSize(HP_TcpServer pServer);
+/* 获取监听 Socket 的等候队列大小 */
+HPSOCKET_API DWORD __stdcall HP_TcpServer_GetSocketListenQueue(HP_TcpServer pServer);
+/* 获取正常心跳包间隔 */
+HPSOCKET_API DWORD __stdcall HP_TcpServer_GetKeepAliveTime(HP_TcpServer pServer);
+/* 获取异常心跳包间隔 */
+HPSOCKET_API DWORD __stdcall HP_TcpServer_GetKeepAliveInterval(HP_TcpServer pServer);
+
+/**********************************************************************************/
+/***************************** UDP Server 属性访问方法 *****************************/
+
+/* 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) */
+HPSOCKET_API void __stdcall HP_UdpServer_SetMaxDatagramSize(HP_UdpServer pServer, DWORD dwMaxDatagramSize);
+/* 获取数据报文最大长度 */
+HPSOCKET_API DWORD __stdcall HP_UdpServer_GetMaxDatagramSize(HP_UdpServer pServer);
+
+/* 设置 Receive 预投递数量(根据负载调整设置,Receive 预投递数量越大则丢包概率越小) */
+HPSOCKET_API void __stdcall HP_UdpServer_SetPostReceiveCount(HP_UdpServer pServer, DWORD dwPostReceiveCount);
+/* 获取 Receive 预投递数量 */
+HPSOCKET_API DWORD __stdcall HP_UdpServer_GetPostReceiveCount(HP_UdpServer pServer);
+
+/* 设置监测包尝试次数(0 则不发送监测跳包,如果超过最大尝试次数则认为已断线) */
+HPSOCKET_API void __stdcall HP_UdpServer_SetDetectAttempts(HP_UdpServer pServer, DWORD dwDetectAttempts);
+/* 设置监测包发送间隔(秒,0 不发送监测包) */
+HPSOCKET_API void __stdcall HP_UdpServer_SetDetectInterval(HP_UdpServer pServer, DWORD dwDetectInterval);
+/* 获取心跳检查次数 */
+HPSOCKET_API DWORD __stdcall HP_UdpServer_GetDetectAttempts(HP_UdpServer pServer);
+/* 获取心跳检查间隔 */
+HPSOCKET_API DWORD __stdcall HP_UdpServer_GetDetectInterval(HP_UdpServer pServer);
+
+/**************************************************************************/
+/***************************** Agent 操作方法 *****************************/
+
+/*
+* 名称:启动通信组件
+* 描述:启动通信代理组件,启动完成后可开始连接远程服务器
+*		
+* 参数:		lpszBindAddress	-- 绑定地址(默认:nullptr,绑定 0.0.0.0)
+*			bAsyncConnect	-- 是否采用异步 Connect
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 HP_Agent_GetLastError() 获取错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_Start(HP_Agent pAgent, LPCTSTR lpszBindAddress, BOOL bAsyncConnect);
+
+/*
+* 名称:关闭通信组件
+* 描述:关闭通信组件,关闭完成后断开所有连接并释放所有资源
+*		
+* 参数:	
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 HP_Agent_GetLastError() 获取错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_Stop(HP_Agent pAgent);
+
+/*
+* 名称:连接服务器
+* 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件
+*		
+* 参数:		lpszRemoteAddress	-- 服务端地址
+*			usPort				-- 服务端端口
+*			pdwConnID			-- 连接 ID(默认:nullptr,不获取连接 ID)
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过函数 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_Connect(HP_Agent pAgent, LPCTSTR lpszRemoteAddress, USHORT usPort, HP_CONNID* pdwConnID);
+
+/*
+* 名称:发送数据
+* 描述:向指定连接发送数据
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pBuffer		-- 发送缓冲区
+*			iLength		-- 发送缓冲区长度
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_Send(HP_Agent pAgent, HP_CONNID dwConnID, const BYTE* pBuffer, int iLength);
+
+/*
+* 名称:发送数据
+* 描述:向指定连接发送数据
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pBuffer		-- 发送缓冲区
+*			iLength		-- 发送缓冲区长度
+*			iOffset		-- 发送缓冲区指针偏移量
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_SendPart(HP_Agent pAgent, HP_CONNID dwConnID, const BYTE* pBuffer, int iLength, int iOffset);
+
+/*
+* 名称:发送多组数据
+* 描述:向指定连接发送多组数据
+*		TCP - 顺序发送所有数据包 
+*		UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) 
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pBuffers	-- 发送缓冲区数组
+*			iCount		-- 发送缓冲区数目
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_SendPackets(HP_Agent pAgent, HP_CONNID dwConnID, const WSABUF pBuffers[], int iCount);
+
+/*
+* 名称:断开连接
+* 描述:断开某个连接
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			bForce		-- 是否强制断开连接
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_Disconnect(HP_Agent pAgent, HP_CONNID dwConnID, BOOL bForce);
+
+/*
+* 名称:断开超时连接
+* 描述:断开超过指定时长的连接
+*		
+* 参数:		dwPeriod	-- 时长(毫秒)
+*			bForce		-- 是否强制断开连接
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_DisconnectLongConnections(HP_Agent pAgent, DWORD dwPeriod, BOOL bForce);
+
+/*
+* 名称:断开静默连接
+* 描述:断开超过指定时长的静默连接
+*		
+* 参数:		dwPeriod	-- 时长(毫秒)
+*			bForce		-- 是否强制断开连接
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_DisconnectSilenceConnections(HP_Agent pAgent, DWORD dwPeriod, BOOL bForce);
+
+/******************************************************************************/
+/***************************** Agent 属性访问方法 *****************************/
+
+/*
+* 名称:设置连接的附加数据
+* 描述:是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pv			-- 数据
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败(无效的连接 ID)
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_SetConnectionExtra(HP_Agent pAgent, HP_CONNID dwConnID, PVOID pExtra);
+
+/*
+* 名称:获取连接的附加数据
+* 描述:是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			ppv			-- 数据指针
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败(无效的连接 ID)
+*/
+HPSOCKET_API BOOL __stdcall HP_Agent_GetConnectionExtra(HP_Agent pAgent, HP_CONNID dwConnID, PVOID* ppExtra);
+
+/* 检查通信组件是否已启动 */
+HPSOCKET_API BOOL __stdcall HP_Agent_HasStarted(HP_Agent pAgent);
+/* 查看通信组件当前状态 */
+HPSOCKET_API En_HP_ServiceState __stdcall HP_Agent_GetState(HP_Agent pAgent);
+/* 获取连接数 */
+HPSOCKET_API DWORD __stdcall HP_Agent_GetConnectionCount(HP_Agent pAgent);
+/* 获取所有连接的 HP_CONNID */
+HPSOCKET_API BOOL __stdcall HP_Agent_GetAllConnectionIDs(HP_Agent pAgent, HP_CONNID pIDs[], DWORD* pdwCount);
+/* 获取某个连接时长(毫秒) */
+HPSOCKET_API BOOL __stdcall HP_Agent_GetConnectPeriod(HP_Agent pAgent, HP_CONNID dwConnID, DWORD* pdwPeriod);
+/* 获取某个连接静默时间(毫秒) */
+HPSOCKET_API BOOL __stdcall HP_Agent_GetSilencePeriod(HP_Agent pAgent, HP_CONNID dwConnID, DWORD* pdwPeriod);
+/* 获取某个连接的本地地址信息 */
+HPSOCKET_API BOOL __stdcall HP_Agent_GetLocalAddress(HP_Agent pAgent, HP_CONNID dwConnID, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);
+/* 获取某个连接的远程地址信息 */
+HPSOCKET_API BOOL __stdcall HP_Agent_GetRemoteAddress(HP_Agent pAgent, HP_CONNID dwConnID, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);
+/* 获取最近一次失败操作的错误代码 */
+HPSOCKET_API En_HP_SocketError __stdcall HP_Agent_GetLastError(HP_Agent pAgent);
+/* 获取最近一次失败操作的错误描述 */
+HPSOCKET_API LPCTSTR __stdcall HP_Agent_GetLastErrorDesc(HP_Agent pAgent);
+/* 获取连接中未发出数据的长度 */
+HPSOCKET_API BOOL __stdcall HP_Agent_GetPendingDataLength(HP_Agent pAgent, HP_CONNID dwConnID, int* piPending);
+
+/* 设置数据发送策略 */
+HPSOCKET_API void __stdcall HP_Agent_SetSendPolicy(HP_Agent pAgent, En_HP_SendPolicy enSendPolicy);
+/* 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) */
+HPSOCKET_API void __stdcall HP_Agent_SetFreeSocketObjLockTime(HP_Agent pAgent, DWORD dwFreeSocketObjLockTime);
+/* 设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) */
+HPSOCKET_API void __stdcall HP_Agent_SetFreeSocketObjPool(HP_Agent pAgent, DWORD dwFreeSocketObjPool);
+/* 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) */
+HPSOCKET_API void __stdcall HP_Agent_SetFreeBufferObjPool(HP_Agent pAgent, DWORD dwFreeBufferObjPool);
+/* 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) */
+HPSOCKET_API void __stdcall HP_Agent_SetFreeSocketObjHold(HP_Agent pAgent, DWORD dwFreeSocketObjHold);
+/* 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) */
+HPSOCKET_API void __stdcall HP_Agent_SetFreeBufferObjHold(HP_Agent pAgent, DWORD dwFreeBufferObjHold);
+/* 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大)*/
+HPSOCKET_API void __stdcall HP_Agent_SetMaxConnectionCount(HP_Agent pAgent, DWORD dwMaxConnectionCount);
+/* 设置工作线程数量(通常设置为 2 * CPU + 2) */
+HPSOCKET_API void __stdcall HP_Agent_SetWorkerThreadCount(HP_Agent pAgent, DWORD dwWorkerThreadCount);
+/* 设置是否标记静默时间(设置为 TRUE 时 DisconnectSilenceConnections() 和 GetSilencePeriod() 才有效,默认:TRUE) */
+HPSOCKET_API void __stdcall HP_Agent_SetMarkSilence(HP_Agent pAgent, BOOL bMarkSilence);
+
+/* 获取数据发送策略 */
+HPSOCKET_API En_HP_SendPolicy __stdcall HP_Agent_GetSendPolicy(HP_Agent pAgent);
+/* 获取 Socket 缓存对象锁定时间 */
+HPSOCKET_API DWORD __stdcall HP_Agent_GetFreeSocketObjLockTime(HP_Agent pAgent);
+/* 获取 Socket 缓存池大小 */
+HPSOCKET_API DWORD __stdcall HP_Agent_GetFreeSocketObjPool(HP_Agent pAgent);
+/* 获取内存块缓存池大小 */
+HPSOCKET_API DWORD __stdcall HP_Agent_GetFreeBufferObjPool(HP_Agent pAgent);
+/* 获取 Socket 缓存池回收阀值 */
+HPSOCKET_API DWORD __stdcall HP_Agent_GetFreeSocketObjHold(HP_Agent pAgent);
+/* 获取内存块缓存池回收阀值 */
+HPSOCKET_API DWORD __stdcall HP_Agent_GetFreeBufferObjHold(HP_Agent pAgent);
+/* 获取最大连接数 */
+HPSOCKET_API DWORD __stdcall HP_Agent_GetMaxConnectionCount(HP_Agent pAgent);
+/* 获取工作线程数量 */
+HPSOCKET_API DWORD __stdcall HP_Agent_GetWorkerThreadCount(HP_Agent pAgent);
+/* 检测是否标记静默时间 */
+HPSOCKET_API BOOL __stdcall HP_Agent_IsMarkSilence(HP_Agent pAgent);
+
+/**********************************************************************************/
+/******************************* TCP Agent 操作方法 *******************************/
+
+/*
+* 名称:发送小文件
+* 描述:向指定连接发送 4096 KB 以下的小文件
+*		
+* 参数:		dwConnID		-- 连接 ID
+*			lpszFileName	-- 文件路径
+*			pHead			-- 头部附加数据
+*			pTail			-- 尾部附加数据
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_TcpAgent_SendSmallFile(HP_Agent pAgent, HP_CONNID dwConnID, LPCTSTR lpszFileName, const LPWSABUF pHead, const LPWSABUF pTail);
+
+/**********************************************************************************/
+/***************************** TCP Agent 属性访问方法 *****************************/
+
+/* 设置是否启用地址重用机制(默认:不启用) */
+HPSOCKET_API void __stdcall HP_TcpAgent_SetReuseAddress(HP_TcpAgent pAgent, BOOL bReuseAddress);
+/* 检测是否启用地址重用机制 */
+HPSOCKET_API BOOL __stdcall HP_TcpAgent_IsReuseAddress(HP_TcpAgent pAgent);
+
+/* 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) */
+HPSOCKET_API void __stdcall HP_TcpAgent_SetSocketBufferSize(HP_TcpAgent pAgent, DWORD dwSocketBufferSize);
+/* 设置正常心跳包间隔(毫秒,0 则不发送心跳包,默认:30 * 1000) */
+HPSOCKET_API void __stdcall HP_TcpAgent_SetKeepAliveTime(HP_TcpAgent pAgent, DWORD dwKeepAliveTime);
+/* 设置异常心跳包间隔(毫秒,0 不发送心跳包,,默认:10 * 1000,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) */
+HPSOCKET_API void __stdcall HP_TcpAgent_SetKeepAliveInterval(HP_TcpAgent pAgent, DWORD dwKeepAliveInterval);
+
+/* 获取通信数据缓冲区大小 */
+HPSOCKET_API DWORD __stdcall HP_TcpAgent_GetSocketBufferSize(HP_TcpAgent pAgent);
+/* 获取正常心跳包间隔 */
+HPSOCKET_API DWORD __stdcall HP_TcpAgent_GetKeepAliveTime(HP_TcpAgent pAgent);
+/* 获取异常心跳包间隔 */
+HPSOCKET_API DWORD __stdcall HP_TcpAgent_GetKeepAliveInterval(HP_TcpAgent pAgent);
+
+/******************************************************************************/
+/***************************** Client 组件操作方法 *****************************/
+
+/*
+* 名称:启动通信组件
+* 描述:启动客户端通信组件并连接服务端,启动完成后可开始收发数据
+*		
+* 参数:		lpszRemoteAddress	-- 服务端地址
+*			usPort				-- 服务端端口
+*			bAsyncConnect		-- 是否采用异步 Connect
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 HP_Client_GetLastError() 获取错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Client_Start(HP_Client pClient, LPCTSTR lpszRemoteAddress, USHORT usPort, BOOL bAsyncConnect);
+
+/*
+* 名称:启动通信组件(并指定绑定地址)
+* 描述:启动客户端通信组件并连接服务端,启动完成后可开始收发数据
+*		
+* 参数:		lpszRemoteAddress	-- 服务端地址
+*			usPort				-- 服务端端口
+*			bAsyncConnect		-- 是否采用异步 Connect
+*			lpszBindAddress		-- 绑定地址(默认:nullptr,TcpClient/UdpClient -> 不执行绑定操作,UdpCast 绑定 -> 0.0.0.0)
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 HP_Client_GetLastError() 获取错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Client_StartWithBindAddress(HP_Client pClient, LPCTSTR lpszRemoteAddress, USHORT usPort, BOOL bAsyncConnect, LPCTSTR lpszBindAddress);
+
+/*
+* 名称:关闭通信组件
+* 描述:关闭客户端通信组件,关闭完成后断开与服务端的连接并释放所有资源
+*		
+* 参数:	
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 HP_Client_GetLastError() 获取错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Client_Stop(HP_Client pClient);
+
+/*
+* 名称:发送数据
+* 描述:向服务端发送数据
+*		
+* 参数:		pBuffer		-- 发送缓冲区
+*			iLength		-- 发送缓冲区长度
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Client_Send(HP_Client pClient, const BYTE* pBuffer, int iLength);
+
+/*
+* 名称:发送数据
+* 描述:向服务端发送数据
+*		
+* 参数:		pBuffer		-- 发送缓冲区
+*			iLength		-- 发送缓冲区长度
+*			iOffset		-- 发送缓冲区指针偏移量
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Client_SendPart(HP_Client pClient, const BYTE* pBuffer, int iLength, int iOffset);
+
+/*
+* 名称:发送多组数据
+* 描述:向服务端发送多组数据
+*		TCP - 顺序发送所有数据包 
+*		UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) 
+*		
+* 参数:		pBuffers	-- 发送缓冲区数组
+*			iCount		-- 发送缓冲区数目
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_Client_SendPackets(HP_Client pClient, const WSABUF pBuffers[], int iCount);
+
+/******************************************************************************/
+/***************************** Client 属性访问方法 *****************************/
+
+/* 设置连接的附加数据 */
+HPSOCKET_API void __stdcall HP_Client_SetExtra(HP_Client pClient, PVOID pExtra);
+/* 获取连接的附加数据 */
+HPSOCKET_API PVOID __stdcall HP_Client_GetExtra(HP_Client pClient);
+
+/* 检查通信组件是否已启动 */
+HPSOCKET_API BOOL __stdcall HP_Client_HasStarted(HP_Client pClient);
+/* 查看通信组件当前状态 */
+HPSOCKET_API En_HP_ServiceState	__stdcall HP_Client_GetState(HP_Client pClient);
+/* 获取最近一次失败操作的错误代码 */
+HPSOCKET_API En_HP_SocketError	__stdcall HP_Client_GetLastError(HP_Client pClient);
+/* 获取最近一次失败操作的错误描述 */
+HPSOCKET_API LPCTSTR __stdcall HP_Client_GetLastErrorDesc(HP_Client pClient);
+/* 获取该组件对象的连接 ID */
+HPSOCKET_API HP_CONNID __stdcall HP_Client_GetConnectionID(HP_Client pClient);
+/* 获取 Client Socket 的地址信息 */
+HPSOCKET_API BOOL __stdcall HP_Client_GetLocalAddress(HP_Client pClient, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);
+/* 获取连接中未发出数据的长度 */
+HPSOCKET_API BOOL __stdcall HP_Client_GetPendingDataLength(HP_Client pClient, int* piPending);
+/* 设置内存块缓存池大小(通常设置为 -> PUSH 模型:5 - 10;PULL 模型:10 - 20 ) */
+HPSOCKET_API void __stdcall HP_Client_SetFreeBufferPoolSize(HP_Client pClient, DWORD dwFreeBufferPoolSize);
+/* 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) */
+HPSOCKET_API void __stdcall HP_Client_SetFreeBufferPoolHold(HP_Client pClient, DWORD dwFreeBufferPoolHold);
+/* 获取内存块缓存池大小 */
+HPSOCKET_API DWORD __stdcall HP_Client_GetFreeBufferPoolSize(HP_Client pClient);
+/* 获取内存块缓存池回收阀值 */
+HPSOCKET_API DWORD __stdcall HP_Client_GetFreeBufferPoolHold(HP_Client pClient);
+
+/**********************************************************************************/
+/******************************* TCP Client 操作方法 *******************************/
+
+/*
+* 名称:发送小文件
+* 描述:向服务端发送 4096 KB 以下的小文件
+*		
+* 参数:		lpszFileName	-- 文件路径
+*			pHead			-- 头部附加数据
+*			pTail			-- 尾部附加数据
+* 返回值:	TRUE	-- 成功
+*			FALSE	-- 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码
+*/
+HPSOCKET_API BOOL __stdcall HP_TcpClient_SendSmallFile(HP_Client pClient, LPCTSTR lpszFileName, const LPWSABUF pHead, const LPWSABUF pTail);
+
+/**********************************************************************************/
+/***************************** TCP Client 属性访问方法 *****************************/
+
+/* 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为:(N * 1024) - sizeof(TBufferObj)) */
+HPSOCKET_API void __stdcall HP_TcpClient_SetSocketBufferSize(HP_TcpClient pClient, DWORD dwSocketBufferSize);
+/* 设置正常心跳包间隔(毫秒,0 则不发送心跳包,默认:30 * 1000) */
+HPSOCKET_API void __stdcall HP_TcpClient_SetKeepAliveTime(HP_TcpClient pClient, DWORD dwKeepAliveTime);
+/* 设置异常心跳包间隔(毫秒,0 不发送心跳包,,默认:10 * 1000,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) */
+HPSOCKET_API void __stdcall HP_TcpClient_SetKeepAliveInterval(HP_TcpClient pClient, DWORD dwKeepAliveInterval);
+
+/* 获取通信数据缓冲区大小 */
+HPSOCKET_API DWORD __stdcall HP_TcpClient_GetSocketBufferSize(HP_TcpClient pClient);
+/* 获取正常心跳包间隔 */
+HPSOCKET_API DWORD __stdcall HP_TcpClient_GetKeepAliveTime(HP_TcpClient pClient);
+/* 获取异常心跳包间隔 */
+HPSOCKET_API DWORD __stdcall HP_TcpClient_GetKeepAliveInterval(HP_TcpClient pClient);
+
+/**********************************************************************************/
+/***************************** UDP Client 属性访问方法 *****************************/
+
+/* 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) */
+HPSOCKET_API void __stdcall HP_UdpClient_SetMaxDatagramSize(HP_UdpClient pClient, DWORD dwMaxDatagramSize);
+/* 获取数据报文最大长度 */
+HPSOCKET_API DWORD __stdcall HP_UdpClient_GetMaxDatagramSize(HP_UdpClient pClient);
+
+/* 设置监测包尝试次数(0 则不发送监测跳包,如果超过最大尝试次数则认为已断线) */
+HPSOCKET_API void __stdcall HP_UdpClient_SetDetectAttempts(HP_UdpClient pClient, DWORD dwDetectAttempts);
+/* 设置监测包发送间隔(秒,0 不发送监测包) */
+HPSOCKET_API void __stdcall HP_UdpClient_SetDetectInterval(HP_UdpClient pClient, DWORD dwDetectInterval);
+/* 获取心跳检查次数 */
+HPSOCKET_API DWORD __stdcall HP_UdpClient_GetDetectAttempts(HP_UdpClient pClient);
+/* 获取心跳检查间隔 */
+HPSOCKET_API DWORD __stdcall HP_UdpClient_GetDetectInterval(HP_UdpClient pClient);
+
+/**********************************************************************************/
+/****************************** UDP Cast 属性访问方法 ******************************/
+
+/* 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) */
+HPSOCKET_API void __stdcall HP_UdpCast_SetMaxDatagramSize(HP_UdpCast pCast, DWORD dwMaxDatagramSize);
+/* 获取数据报文最大长度 */
+HPSOCKET_API DWORD __stdcall HP_UdpCast_GetMaxDatagramSize(HP_UdpCast pCast);
+/* 获取当前数据报的远程地址信息(通常在 OnReceive 事件中调用) */
+HPSOCKET_API BOOL __stdcall HP_UdpCast_GetRemoteAddress(HP_UdpCast pCast, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);
+/* 设置是否启用地址重用机制(默认:不启用) */
+HPSOCKET_API void __stdcall HP_UdpCast_SetReuseAddress(HP_UdpCast pCast, BOOL bReuseAddress);
+/* 检测是否启用地址重用机制 */
+HPSOCKET_API BOOL __stdcall HP_UdpCast_IsReuseAddress(HP_UdpCast pCast);
+/* 设置传播模式(组播或广播) */
+HPSOCKET_API void __stdcall HP_UdpCast_SetCastMode(HP_UdpCast pCast, En_HP_CastMode enCastMode);
+/* 获取传播模式 */
+HPSOCKET_API En_HP_CastMode __stdcall HP_UdpCast_GetCastMode(HP_UdpCast pCast);
+/* 设置组播报文的 TTL(0 - 255) */
+HPSOCKET_API void __stdcall HP_UdpCast_SetMultiCastTtl(HP_UdpCast pCast, int iMCTtl);
+/* 获取组播报文的 TTL */
+HPSOCKET_API int __stdcall HP_UdpCast_GetMultiCastTtl(HP_UdpCast pCast);
+/* 设置是否启用组播环路(TRUE or FALSE) */
+HPSOCKET_API void __stdcall HP_UdpCast_SetMultiCastLoop(HP_UdpCast pCast, BOOL bMCLoop);
+/* 检测是否启用组播环路 */
+HPSOCKET_API BOOL __stdcall HP_UdpCast_IsMultiCastLoop(HP_UdpCast pCast);
+
+/***************************************************************************************/
+/***************************** TCP Pull Server 组件操作方法 *****************************/
+
+/*
+* 名称:抓取数据
+* 描述:用户通过该方法从 Socket 组件中抓取数据
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pData		-- 抓取缓冲区
+*			iLength		-- 抓取数据长度
+* 返回值:	En_HP_FetchResult
+*/
+HPSOCKET_API En_HP_FetchResult __stdcall HP_TcpPullServer_Fetch(HP_TcpPullServer pServer, HP_CONNID dwConnID, BYTE* pData, int iLength);
+
+/*
+* 名称:窥探数据(不会移除缓冲区数据)
+* 描述:用户通过该方法从 Socket 组件中窥探数据
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pData		-- 窥探缓冲区
+*			iLength		-- 窥探数据长度
+* 返回值:	En_HP_FetchResult
+*/
+HPSOCKET_API En_HP_FetchResult __stdcall HP_TcpPullServer_Peek(HP_TcpPullServer pServer, HP_CONNID dwConnID, BYTE* pData, int iLength);
+
+/***************************************************************************************/
+/***************************** TCP Pull Server 属性访问方法 *****************************/
+
+/***************************************************************************************/
+/***************************** TCP Pull Agent 组件操作方法 *****************************/
+
+/*
+* 名称:抓取数据
+* 描述:用户通过该方法从 Socket 组件中抓取数据
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pData		-- 抓取缓冲区
+*			iLength		-- 抓取数据长度
+* 返回值:	En_HP_FetchResult
+*/
+HPSOCKET_API En_HP_FetchResult __stdcall HP_TcpPullAgent_Fetch(HP_TcpPullAgent pAgent, HP_CONNID dwConnID, BYTE* pData, int iLength);
+
+/*
+* 名称:窥探数据(不会移除缓冲区数据)
+* 描述:用户通过该方法从 Socket 组件中窥探数据
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pData		-- 窥探缓冲区
+*			iLength		-- 窥探数据长度
+* 返回值:	En_HP_FetchResult
+*/
+HPSOCKET_API En_HP_FetchResult __stdcall HP_TcpPullAgent_Peek(HP_TcpPullAgent pAgent, HP_CONNID dwConnID, BYTE* pData, int iLength);
+
+/***************************************************************************************/
+/***************************** TCP Pull Agent 属性访问方法 *****************************/
+
+/***************************************************************************************/
+/***************************** TCP Pull Client 组件操作方法 *****************************/
+
+/*
+* 名称:抓取数据
+* 描述:用户通过该方法从 Socket 组件中抓取数据
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pData		-- 抓取缓冲区
+*			iLength		-- 抓取数据长度
+* 返回值:	En_HP_FetchResult
+*/
+HPSOCKET_API En_HP_FetchResult __stdcall HP_TcpPullClient_Fetch(HP_TcpPullClient pClient, BYTE* pData, int iLength);
+
+/*
+* 名称:窥探数据(不会移除缓冲区数据)
+* 描述:用户通过该方法从 Socket 组件中窥探数据
+*		
+* 参数:		dwConnID	-- 连接 ID
+*			pData		-- 窥探缓冲区
+*			iLength		-- 窥探数据长度
+* 返回值:	En_HP_FetchResult
+*/
+HPSOCKET_API En_HP_FetchResult __stdcall HP_TcpPullClient_Peek(HP_TcpPullClient pClient, BYTE* pData, int iLength);
+
+/***************************************************************************************/
+/***************************** TCP Pull Client 属性访问方法 *****************************/
+
+/***************************************************************************************/
+/***************************** TCP Pack Server 组件操作方法 *****************************/
+
+/***************************************************************************************/
+/***************************** TCP Pack Server 属性访问方法 *****************************/
+
+/* 设置数据包最大长度(有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000) */
+HPSOCKET_API void __stdcall HP_TcpPackServer_SetMaxPackSize(HP_TcpPackServer pServer, DWORD dwMaxPackSize);
+/* 设置包头标识(有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0) */
+HPSOCKET_API void __stdcall HP_TcpPackServer_SetPackHeaderFlag(HP_TcpPackServer pServer, USHORT usPackHeaderFlag);
+
+/* 获取数据包最大长度 */
+HPSOCKET_API DWORD __stdcall HP_TcpPackServer_GetMaxPackSize(HP_TcpPackServer pServer);
+/* 获取包头标识 */
+HPSOCKET_API USHORT __stdcall HP_TcpPackServer_GetPackHeaderFlag(HP_TcpPackServer pServer);
+
+/***************************************************************************************/
+/***************************** TCP Pack Agent 组件操作方法 *****************************/
+
+/***************************************************************************************/
+/***************************** TCP Pack Agent 属性访问方法 *****************************/
+
+/* 设置数据包最大长度(有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000) */
+HPSOCKET_API void __stdcall HP_TcpPackAgent_SetMaxPackSize(HP_TcpPackAgent pAgent, DWORD dwMaxPackSize);
+/* 设置包头标识(有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0) */
+HPSOCKET_API void __stdcall HP_TcpPackAgent_SetPackHeaderFlag(HP_TcpPackAgent pAgent, USHORT usPackHeaderFlag);
+
+/* 获取数据包最大长度 */
+HPSOCKET_API DWORD __stdcall HP_TcpPackAgent_GetMaxPackSize(HP_TcpPackAgent pAgent);
+/* 获取包头标识 */
+HPSOCKET_API USHORT __stdcall HP_TcpPackAgent_GetPackHeaderFlag(HP_TcpPackAgent pAgent);
+
+/***************************************************************************************/
+/***************************** TCP Pack Client 组件操作方法 *****************************/
+
+/***************************************************************************************/
+/***************************** TCP Pack Client 属性访问方法 *****************************/
+
+/* 设置数据包最大长度(有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000) */
+HPSOCKET_API void __stdcall HP_TcpPackClient_SetMaxPackSize(HP_TcpPackClient pClient, DWORD dwMaxPackSize);
+/* 设置包头标识(有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0) */
+HPSOCKET_API void __stdcall HP_TcpPackClient_SetPackHeaderFlag(HP_TcpPackClient pClient, USHORT usPackHeaderFlag);
+
+/* 获取数据包最大长度 */
+HPSOCKET_API DWORD __stdcall HP_TcpPackClient_GetMaxPackSize(HP_TcpPackClient pClient);
+/* 获取包头标识 */
+HPSOCKET_API USHORT __stdcall HP_TcpPackClient_GetPackHeaderFlag(HP_TcpPackClient pClient);
+
+/*****************************************************************************************************************************************************/
+/******************************************************************** HTTP Exports *******************************************************************/
+/*****************************************************************************************************************************************************/
+
+/****************************************************/
+/******************* HTTP 回调函数 *******************/
+
+/* Complex HTTP 回调函数 */
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnMessageBegin)		(HP_CONNID dwConnID);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnRequestLine)		(HP_CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnStatusLine)		(HP_CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnHeader)			(HP_CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnHeadersComplete)	(HP_CONNID dwConnID);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnBody)				(HP_CONNID dwConnID, const BYTE* pData, int iLength);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnChunkHeader)		(HP_CONNID dwConnID, int iLength);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnChunkComplete)	(HP_CONNID dwConnID);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnMessageComplete)	(HP_CONNID dwConnID);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnUpgrade)			(HP_CONNID dwConnID, En_HP_HttpUpgradeType enUpgradeType);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_ComplexHttp_OnParseError)		(HP_CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc);
+
+/* Single HTTP 回调函数 */
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnMessageBegin)		(HP_HttpClient pClient);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnRequestLine)		(HP_HttpClient pClient, LPCSTR lpszMethod, LPCSTR lpszUrl);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnStatusLine)		(HP_HttpClient pClient, USHORT usStatusCode, LPCSTR lpszDesc);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnHeader)			(HP_HttpClient pClient, LPCSTR lpszName, LPCSTR lpszValue);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnHeadersComplete)	(HP_HttpClient pClient);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnBody)				(HP_HttpClient pClient, const BYTE* pData, int iLength);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnChunkHeader)		(HP_HttpClient pClient, int iLength);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnChunkComplete)		(HP_HttpClient pClient);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnMessageComplete)	(HP_HttpClient pClient);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnUpgrade)			(HP_HttpClient pClient, En_HP_HttpUpgradeType enUpgradeType);
+typedef En_HP_HttpParseResult (__stdcall *HP_FN_SingleHttp_OnParseError)		(HP_HttpClient pClient, int iErrorCode, LPCSTR lpszErrorDesc);
+
+/* HTTP Server 回调函数 */
+typedef HP_FN_ComplexHttp_OnMessageBegin	HP_FN_HttpServer_OnMessageBegin;
+typedef HP_FN_ComplexHttp_OnRequestLine		HP_FN_HttpServer_OnRequestLine;
+typedef HP_FN_ComplexHttp_OnHeader			HP_FN_HttpServer_OnHeader;
+typedef HP_FN_ComplexHttp_OnHeadersComplete	HP_FN_HttpServer_OnHeadersComplete;
+typedef HP_FN_ComplexHttp_OnBody			HP_FN_HttpServer_OnBody;
+typedef HP_FN_ComplexHttp_OnChunkHeader		HP_FN_HttpServer_OnChunkHeader;
+typedef HP_FN_ComplexHttp_OnChunkComplete	HP_FN_HttpServer_OnChunkComplete;
+typedef HP_FN_ComplexHttp_OnMessageComplete	HP_FN_HttpServer_OnMessageComplete;
+typedef HP_FN_ComplexHttp_OnUpgrade			HP_FN_HttpServer_OnUpgrade;
+typedef HP_FN_ComplexHttp_OnParseError		HP_FN_HttpServer_OnParseError;
+
+typedef HP_FN_Server_OnPrepareListen		HP_FN_HttpServer_OnPrepareListen;
+typedef HP_FN_Server_OnAccept				HP_FN_HttpServer_OnAccept;
+typedef HP_FN_Server_OnHandShake			HP_FN_HttpServer_OnHandShake;
+typedef HP_FN_Server_OnSend					HP_FN_HttpServer_OnSend;
+typedef HP_FN_Server_OnClose				HP_FN_HttpServer_OnClose;
+typedef HP_FN_Server_OnShutdown				HP_FN_HttpServer_OnShutdown;
+
+/* HTTP Agent 回调函数 */
+typedef HP_FN_ComplexHttp_OnMessageBegin	HP_FN_HttpAgent_OnMessageBegin;
+typedef HP_FN_ComplexHttp_OnStatusLine		HP_FN_HttpAgent_OnStatusLine;
+typedef HP_FN_ComplexHttp_OnHeader			HP_FN_HttpAgent_OnHeader;
+typedef HP_FN_ComplexHttp_OnHeadersComplete	HP_FN_HttpAgent_OnHeadersComplete;
+typedef HP_FN_ComplexHttp_OnBody			HP_FN_HttpAgent_OnBody;
+typedef HP_FN_ComplexHttp_OnChunkHeader		HP_FN_HttpAgent_OnChunkHeader;
+typedef HP_FN_ComplexHttp_OnChunkComplete	HP_FN_HttpAgent_OnChunkComplete;
+typedef HP_FN_ComplexHttp_OnMessageComplete	HP_FN_HttpAgent_OnMessageComplete;
+typedef HP_FN_ComplexHttp_OnUpgrade			HP_FN_HttpAgent_OnUpgrade;
+typedef HP_FN_ComplexHttp_OnParseError		HP_FN_HttpAgent_OnParseError;
+
+typedef HP_FN_Agent_OnPrepareConnect		HP_FN_HttpAgent_OnPrepareConnect;
+typedef HP_FN_Agent_OnConnect				HP_FN_HttpAgent_OnConnect;
+typedef HP_FN_Agent_OnHandShake				HP_FN_HttpAgent_OnHandShake;
+typedef HP_FN_Agent_OnSend					HP_FN_HttpAgent_OnSend;
+typedef HP_FN_Agent_OnClose					HP_FN_HttpAgent_OnClose;
+typedef HP_FN_Agent_OnShutdown				HP_FN_HttpAgent_OnShutdown;
+
+/* HTTP Client 回调函数 */
+typedef HP_FN_SingleHttp_OnMessageBegin		HP_FN_HttpClient_OnMessageBegin;
+typedef HP_FN_SingleHttp_OnStatusLine		HP_FN_HttpClient_OnStatusLine;
+typedef HP_FN_SingleHttp_OnHeader			HP_FN_HttpClient_OnHeader;
+typedef HP_FN_SingleHttp_OnHeadersComplete	HP_FN_HttpClient_OnHeadersComplete;
+typedef HP_FN_SingleHttp_OnBody				HP_FN_HttpClient_OnBody;
+typedef HP_FN_SingleHttp_OnChunkHeader		HP_FN_HttpClient_OnChunkHeader;
+typedef HP_FN_SingleHttp_OnChunkComplete	HP_FN_HttpClient_OnChunkComplete;
+typedef HP_FN_SingleHttp_OnMessageComplete	HP_FN_HttpClient_OnMessageComplete;
+typedef HP_FN_SingleHttp_OnUpgrade			HP_FN_HttpClient_OnUpgrade;
+typedef HP_FN_SingleHttp_OnParseError		HP_FN_HttpClient_OnParseError;
+
+typedef HP_FN_Client_OnPrepareConnect		HP_FN_HttpClient_OnPrepareConnect;
+typedef HP_FN_Client_OnConnect				HP_FN_HttpClient_OnConnect;
+typedef HP_FN_Client_OnHandShake			HP_FN_HttpClient_OnHandShake;
+typedef HP_FN_Client_OnSend					HP_FN_HttpClient_OnSend;
+typedef HP_FN_Client_OnClose				HP_FN_HttpClient_OnClose;
+
+/****************************************************/
+/***************** HTTP 对象创建函数 *****************/
+
+// 创建 HP_HttpServer 对象
+HPSOCKET_API HP_HttpServer __stdcall Create_HP_HttpServer(HP_HttpServerListener pListener);
+// 创建 HP_HttpAgent 对象
+HPSOCKET_API HP_HttpAgent __stdcall Create_HP_HttpAgent(HP_HttpAgentListener pListener);
+// 创建 HP_HttpClient 对象
+HPSOCKET_API HP_HttpClient __stdcall Create_HP_HttpClient(HP_HttpClientListener pListener);
+
+// 销毁 HP_HttpServer 对象
+HPSOCKET_API void __stdcall Destroy_HP_HttpServer(HP_HttpServer pServer);
+// 销毁 HP_HttpAgent 对象
+HPSOCKET_API void __stdcall Destroy_HP_HttpAgent(HP_HttpAgent pAgent);
+// 销毁 HP_HttpClient 对象
+HPSOCKET_API void __stdcall Destroy_HP_HttpClient(HP_HttpClient pClient);
+
+// 创建 HP_HttpServerListener 对象
+HPSOCKET_API HP_HttpServerListener __stdcall Create_HP_HttpServerListener();
+// 创建 HP_HttpAgentListener 对象
+HPSOCKET_API HP_HttpAgentListener __stdcall Create_HP_HttpAgentListener();
+// 创建 HP_HttpClientListener 对象
+HPSOCKET_API HP_HttpClientListener __stdcall Create_HP_HttpClientListener();
+
+// 销毁 HP_HttpServerListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_HttpServerListener(HP_HttpServerListener pListener);
+// 销毁 HP_HttpAgentListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_HttpAgentListener(HP_HttpAgentListener pListener);
+// 销毁 HP_HttpClientListener 对象
+HPSOCKET_API void __stdcall Destroy_HP_HttpClientListener(HP_HttpClientListener pListener);
+
+/**********************************************************************************/
+/*************************** HTTP Server 回调函数设置方法 **************************/
+
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnMessageBegin(HP_HttpServerListener pListener		, HP_FN_HttpServer_OnMessageBegin fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnRequestLine(HP_HttpServerListener pListener		, HP_FN_HttpServer_OnRequestLine fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnHeader(HP_HttpServerListener pListener			, HP_FN_HttpServer_OnHeader fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnHeadersComplete(HP_HttpServerListener pListener	, HP_FN_HttpServer_OnHeadersComplete fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnBody(HP_HttpServerListener pListener				, HP_FN_HttpServer_OnBody fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnChunkHeader(HP_HttpServerListener pListener		, HP_FN_HttpServer_OnChunkHeader fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnChunkComplete(HP_HttpServerListener pListener	, HP_FN_HttpServer_OnChunkComplete fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnMessageComplete(HP_HttpServerListener pListener	, HP_FN_HttpServer_OnMessageComplete fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnUpgrade(HP_HttpServerListener pListener			, HP_FN_HttpServer_OnUpgrade fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnParseError(HP_HttpServerListener pListener		, HP_FN_HttpServer_OnParseError fn);
+
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnPrepareListen(HP_HttpServerListener pListener	, HP_FN_HttpServer_OnPrepareListen fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnAccept(HP_HttpServerListener pListener			, HP_FN_HttpServer_OnAccept fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnHandShake(HP_HttpServerListener pListener		, HP_FN_HttpServer_OnHandShake fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnSend(HP_HttpServerListener pListener				, HP_FN_HttpServer_OnSend fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnClose(HP_HttpServerListener pListener			, HP_FN_HttpServer_OnClose fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpServer_OnShutdown(HP_HttpServerListener pListener			, HP_FN_HttpServer_OnShutdown fn);
+
+/**********************************************************************************/
+/**************************** HTTP Agent 回调函数设置方法 **************************/
+
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnMessageBegin(HP_HttpAgentListener pListener		, HP_FN_HttpAgent_OnMessageBegin fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnStatusLine(HP_HttpAgentListener pListener			, HP_FN_HttpAgent_OnStatusLine fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnHeader(HP_HttpAgentListener pListener				, HP_FN_HttpAgent_OnHeader fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnHeadersComplete(HP_HttpAgentListener pListener	, HP_FN_HttpAgent_OnHeadersComplete fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnBody(HP_HttpAgentListener pListener				, HP_FN_HttpAgent_OnBody fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnChunkHeader(HP_HttpAgentListener pListener		, HP_FN_HttpAgent_OnChunkHeader fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnChunkComplete(HP_HttpAgentListener pListener		, HP_FN_HttpAgent_OnChunkComplete fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnMessageComplete(HP_HttpAgentListener pListener	, HP_FN_HttpAgent_OnMessageComplete fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnUpgrade(HP_HttpAgentListener pListener			, HP_FN_HttpAgent_OnUpgrade fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnParseError(HP_HttpAgentListener pListener			, HP_FN_HttpAgent_OnParseError fn);
+
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnPrepareConnect(HP_HttpAgentListener pListener		, HP_FN_HttpAgent_OnPrepareConnect fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnConnect(HP_HttpAgentListener pListener			, HP_FN_HttpAgent_OnConnect fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnHandShake(HP_HttpAgentListener pListener			, HP_FN_HttpAgent_OnHandShake fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnSend(HP_HttpAgentListener pListener				, HP_FN_HttpAgent_OnSend fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnClose(HP_HttpAgentListener pListener				, HP_FN_HttpAgent_OnClose fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpAgent_OnShutdown(HP_HttpAgentListener pListener			, HP_FN_HttpAgent_OnShutdown fn);
+
+/**********************************************************************************/
+/*************************** HTTP Client 回调函数设置方法 **************************/
+
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnMessageBegin(HP_HttpClientListener pListener		, HP_FN_HttpClient_OnMessageBegin fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnStatusLine(HP_HttpClientListener pListener		, HP_FN_HttpClient_OnStatusLine fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnHeader(HP_HttpClientListener pListener			, HP_FN_HttpClient_OnHeader fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnHeadersComplete(HP_HttpClientListener pListener	, HP_FN_HttpClient_OnHeadersComplete fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnBody(HP_HttpClientListener pListener				, HP_FN_HttpClient_OnBody fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnChunkHeader(HP_HttpClientListener pListener		, HP_FN_HttpClient_OnChunkHeader fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnChunkComplete(HP_HttpClientListener pListener	, HP_FN_HttpClient_OnChunkComplete fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnMessageComplete(HP_HttpClientListener pListener	, HP_FN_HttpClient_OnMessageComplete fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnUpgrade(HP_HttpClientListener pListener			, HP_FN_HttpClient_OnUpgrade fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnParseError(HP_HttpClientListener pListener		, HP_FN_HttpClient_OnParseError fn);
+
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnPrepareConnect(HP_HttpClientListener pListener	, HP_FN_HttpClient_OnPrepareConnect fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnConnect(HP_HttpClientListener pListener			, HP_FN_HttpClient_OnConnect fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnHandShake(HP_HttpClientListener pListener		, HP_FN_HttpClient_OnHandShake fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnSend(HP_HttpClientListener pListener				, HP_FN_HttpClient_OnSend fn);
+HPSOCKET_API void __stdcall HP_Set_FN_HttpClient_OnClose(HP_HttpClientListener pListener			, HP_FN_HttpClient_OnClose fn);
+
+/**************************************************************************/
+/***************************** Server 操作方法 *****************************/
+
+/*
+* 名称:回复请求
+* 描述:向客户端回复 HTTP 请求
+*		
+* 参数:		dwConnID		-- 连接 ID
+*			usStatusCode	-- HTTP 状态码
+*			lpszDesc		-- HTTP 状态描述
+*			lpHeaders		-- 回复请求头
+*			iHeaderCount	-- 回复请求头数量
+*			pData			-- 回复请求体
+*			iLength			-- 回复请求体长度
+* 返回值:	TRUE			-- 成功
+*			FALSE			-- 失败
+*/
+HPSOCKET_API BOOL __stdcall HP_HttpServer_SendResponse(HP_HttpServer pServer, HP_CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc, const HP_THeader lpHeaders[], int iHeaderCount, const BYTE* pData, int iLength);
+
+/*
+* 名称:释放连接
+* 描述:把连接放入释放队列,等待某个时间(通过 SetReleaseDelay() 设置)关闭连接
+*		
+* 参数:		dwConnID		-- 连接 ID
+* 返回值:	TRUE			-- 成功
+*			FALSE			-- 失败
+*/
+HPSOCKET_API BOOL __stdcall HP_HttpServer_Release(HP_HttpServer pServer, HP_CONNID dwConnID);
+
+/******************************************************************************/
+/***************************** Server 属性访问方法 *****************************/
+
+/* 设置连接释放延时(默认:3000 毫秒) */
+HPSOCKET_API void __stdcall HP_HttpServer_SetReleaseDelay(HP_HttpServer pServer, DWORD dwReleaseDelay);
+/* 获取连接释放延时 */
+HPSOCKET_API DWORD __stdcall HP_HttpServer_GetReleaseDelay(HP_HttpServer pServer);
+/* 获取请求行 URL 域掩码(URL 域参考:EnHttpUrlField) */
+HPSOCKET_API USHORT __stdcall HP_HttpServer_GetUrlFieldSet(HP_HttpServer pServer, HP_CONNID dwConnID);
+/* 获取某个 URL 域值 */
+HPSOCKET_API LPCSTR __stdcall HP_HttpServer_GetUrlField(HP_HttpServer pServer, HP_CONNID dwConnID, En_HP_HttpUrlField enField);
+/* 获取请求方法 */
+HPSOCKET_API LPCSTR __stdcall HP_HttpServer_GetMethod(HP_HttpServer pServer, HP_CONNID dwConnID);
+
+/* 设置本地协议版本 */
+HPSOCKET_API void __stdcall HP_HttpServer_SetLocalVersion(HP_HttpServer pServer, En_HP_HttpVersion usVersion);
+/* 获取本地协议版本 */
+HPSOCKET_API En_HP_HttpVersion __stdcall HP_HttpServer_GetLocalVersion(HP_HttpServer pServer);
+
+/* 检查是否升级协议 */
+HPSOCKET_API BOOL __stdcall HP_HttpServer_IsUpgrade(HP_HttpServer pServer, HP_CONNID dwConnID);
+/* 检查是否有 Keep-Alive 标识 */
+HPSOCKET_API BOOL __stdcall HP_HttpServer_IsKeepAlive(HP_HttpServer pServer, HP_CONNID dwConnID);
+/* 获取协议版本 */
+HPSOCKET_API USHORT __stdcall HP_HttpServer_GetVersion(HP_HttpServer pServer, HP_CONNID dwConnID);
+/* 获取内容长度 */
+HPSOCKET_API ULONGLONG __stdcall HP_HttpServer_GetContentLength(HP_HttpServer pServer, HP_CONNID dwConnID);
+/* 获取内容类型 */
+HPSOCKET_API LPCSTR __stdcall HP_HttpServer_GetContentType(HP_HttpServer pServer, HP_CONNID dwConnID);
+/* 获取协议升级类型 */
+HPSOCKET_API En_HP_HttpUpgradeType __stdcall HP_HttpServer_GetUpgradeType(HP_HttpServer pServer, HP_CONNID dwConnID);
+/* 获取解析错误代码 */
+HPSOCKET_API USHORT __stdcall HP_HttpServer_GetParseErrorCode(HP_HttpServer pServer, HP_CONNID dwConnID, LPCSTR* lpszErrorDesc);
+
+/* 获取某个请求头(单值) */
+HPSOCKET_API BOOL __stdcall HP_HttpServer_GetHeader(HP_HttpServer pServer, HP_CONNID dwConnID, LPCSTR lpszName, LPCSTR* lpszValue);
+/* 获取某个请求头(多值) */
+HPSOCKET_API BOOL __stdcall HP_HttpServer_GetHeaders(HP_HttpServer pServer, HP_CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue[], DWORD* pdwCount);
+/* 获取所有请求头 */
+HPSOCKET_API BOOL __stdcall HP_HttpServer_GetAllHeaders(HP_HttpServer pServer, HP_CONNID dwConnID, HP_THeader lpHeaders[], DWORD* pdwCount);
+/* 获取所有请求头名称 */
+HPSOCKET_API BOOL __stdcall HP_HttpServer_GetAllHeaderNames(HP_HttpServer pServer, HP_CONNID dwConnID, LPCSTR lpszName[], DWORD* pdwCount);
+
+/* 获取 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpServer_GetCookie(HP_HttpServer pServer, HP_CONNID dwConnID, LPCSTR lpszName, LPCSTR* lpszValue);
+/* 获取所有 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpServer_GetAllCookies(HP_HttpServer pServer, HP_CONNID dwConnID, HP_TCookie lpCookies[], DWORD* pdwCount);
+
+/**************************************************************************/
+/***************************** Agent 操作方法 ******************************/
+
+/*
+* 名称:发送请求
+* 描述:向服务端发送 HTTP 请求
+*		
+* 参数:		dwConnID		-- 连接 ID
+*			lpszMethod		-- 请求方法
+*			lpszPath		-- 请求路径
+*			lpHeaders		-- 请求头
+*			iHeaderCount	-- 请求头数量
+*			pBody			-- 请求体
+*			iLength			-- 请求体长度
+* 返回值:	TRUE			-- 成功
+*			FALSE			-- 失败
+*/
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_SendRequest(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount, const BYTE* pData, int iLength);
+
+/* 发送 POST 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_SendPost(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength);
+/* 发送 PUT 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_SendPut(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength);
+/* 发送 PATCH 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_SendPatch(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength);
+/* 发送 GET 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_SendGet(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount);
+/* 发送 DELETE 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_SendDelete(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount);
+/* 发送 HEAD 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_SendHead(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount);
+/* 发送 TRACE 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_SendTrace(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount);
+/* 发送 OPTIONS 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_SendOptions(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount);
+/* 发送 CONNECT 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_SendConnect(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszHost, const HP_THeader lpHeaders[], int iHeaderCount);
+
+/******************************************************************************/
+/***************************** Agent 属性访问方法 ******************************/
+
+/* 获取 HTTP 状态码 */
+HPSOCKET_API USHORT __stdcall HP_HttpAgent_GetStatusCode(HP_HttpAgent pAgent, HP_CONNID dwConnID);
+
+/* 设置本地协议版本 */
+HPSOCKET_API void __stdcall HP_HttpAgent_SetLocalVersion(HP_HttpAgent pAgent, En_HP_HttpVersion usVersion);
+/* 获取本地协议版本 */
+HPSOCKET_API En_HP_HttpVersion __stdcall HP_HttpAgent_GetLocalVersion(HP_HttpAgent pAgent);
+
+/* 检查是否升级协议 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_IsUpgrade(HP_HttpAgent pAgent, HP_CONNID dwConnID);
+/* 检查是否有 Keep-Alive 标识 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_IsKeepAlive(HP_HttpAgent pAgent, HP_CONNID dwConnID);
+/* 获取协议版本 */
+HPSOCKET_API USHORT __stdcall HP_HttpAgent_GetVersion(HP_HttpAgent pAgent, HP_CONNID dwConnID);
+/* 获取内容长度 */
+HPSOCKET_API ULONGLONG __stdcall HP_HttpAgent_GetContentLength(HP_HttpAgent pAgent, HP_CONNID dwConnID);
+/* 获取内容类型 */
+HPSOCKET_API LPCSTR __stdcall HP_HttpAgent_GetContentType(HP_HttpAgent pAgent, HP_CONNID dwConnID);
+/* 获取协议升级类型 */
+HPSOCKET_API En_HP_HttpUpgradeType __stdcall HP_HttpAgent_GetUpgradeType(HP_HttpAgent pAgent, HP_CONNID dwConnID);
+/* 获取解析错误代码 */
+HPSOCKET_API USHORT __stdcall HP_HttpAgent_GetParseErrorCode(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR* lpszErrorDesc);
+
+/* 获取某个请求头(单值) */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_GetHeader(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszName, LPCSTR* lpszValue);
+/* 获取某个请求头(多值) */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_GetHeaders(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue[], DWORD* pdwCount);
+/* 获取所有请求头 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_GetAllHeaders(HP_HttpAgent pAgent, HP_CONNID dwConnID, HP_THeader lpHeaders[], DWORD* pdwCount);
+/* 获取所有请求头名称 */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_GetAllHeaderNames(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszName[], DWORD* pdwCount);
+
+/* 获取 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_GetCookie(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszName, LPCSTR* lpszValue);
+/* 获取所有 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_GetAllCookies(HP_HttpAgent pAgent, HP_CONNID dwConnID, HP_TCookie lpCookies[], DWORD* pdwCount);
+/* 添加 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_AddCookie(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue, BOOL bRelpace);
+/* 删除 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_DeleteCookie(HP_HttpAgent pAgent, HP_CONNID dwConnID, LPCSTR lpszName);
+/* 删除所有 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpAgent_DeleteAllCookies(HP_HttpAgent pAgent, HP_CONNID dwConnID);
+
+/**************************************************************************/
+/***************************** Client 操作方法 *****************************/
+
+/*
+* 名称:发送请求
+* 描述:向服务端发送 HTTP 请求
+*		
+* 参数:		lpszMethod		-- 请求方法
+*			lpszPath		-- 请求路径
+*			lpHeaders		-- 请求头
+*			iHeaderCount	-- 请求头数量
+*			pBody			-- 请求体
+*			iLength			-- 请求体长度
+* 返回值:	TRUE			-- 成功
+*			FALSE			-- 失败
+*/
+HPSOCKET_API BOOL __stdcall HP_HttpClient_SendRequest(HP_HttpClient pClient, LPCSTR lpszMethod, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength);
+
+/* 发送 POST 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_SendPost(HP_HttpClient pClient, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength);
+/* 发送 PUT 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_SendPut(HP_HttpClient pClient, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength);
+/* 发送 PATCH 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_SendPatch(HP_HttpClient pClient, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength);
+/* 发送 GET 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_SendGet(HP_HttpClient pClient, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount);
+/* 发送 DELETE 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_SendDelete(HP_HttpClient pClient, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount);
+/* 发送 HEAD 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_SendHead(HP_HttpClient pClient, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount);
+/* 发送 TRACE 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_SendTrace(HP_HttpClient pClient, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount);
+/* 发送 OPTIONS 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_SendOptions(HP_HttpClient pClient, LPCSTR lpszPath, const HP_THeader lpHeaders[], int iHeaderCount);
+/* 发送 CONNECT 请求 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_SendConnect(HP_HttpClient pClient, LPCSTR lpszHost, const HP_THeader lpHeaders[], int iHeaderCount);
+
+/******************************************************************************/
+/***************************** Client 属性访问方法 *****************************/
+
+/* 获取 HTTP 状态码 */
+HPSOCKET_API USHORT __stdcall HP_HttpClient_GetStatusCode(HP_HttpClient pClient);
+
+/* 设置本地协议版本 */
+HPSOCKET_API void __stdcall HP_HttpClient_SetLocalVersion(HP_HttpClient pClient, En_HP_HttpVersion usVersion);
+/* 获取本地协议版本 */
+HPSOCKET_API En_HP_HttpVersion __stdcall HP_HttpClient_GetLocalVersion(HP_HttpClient pClient);
+
+/* 检查是否升级协议 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_IsUpgrade(HP_HttpClient pClient);
+/* 检查是否有 Keep-Alive 标识 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_IsKeepAlive(HP_HttpClient pClient);
+/* 获取协议版本 */
+HPSOCKET_API USHORT __stdcall HP_HttpClient_GetVersion(HP_HttpClient pClient);
+/* 获取内容长度 */
+HPSOCKET_API ULONGLONG __stdcall HP_HttpClient_GetContentLength(HP_HttpClient pClient);
+/* 获取内容类型 */
+HPSOCKET_API LPCSTR __stdcall HP_HttpClient_GetContentType(HP_HttpClient pClient);
+/* 获取协议升级类型 */
+HPSOCKET_API En_HP_HttpUpgradeType __stdcall HP_HttpClient_GetUpgradeType(HP_HttpClient pClient);
+/* 获取解析错误代码 */
+HPSOCKET_API USHORT __stdcall HP_HttpClient_GetParseErrorCode(HP_HttpClient pClient, LPCSTR* lpszErrorDesc);
+
+/* 获取某个请求头(单值) */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_GetHeader(HP_HttpClient pClient, LPCSTR lpszName, LPCSTR* lpszValue);
+/* 获取某个请求头(多值) */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_GetHeaders(HP_HttpClient pClient, LPCSTR lpszName, LPCSTR lpszValue[], DWORD* pdwCount);
+/* 获取所有请求头 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_GetAllHeaders(HP_HttpClient pClient, HP_THeader lpHeaders[], DWORD* pdwCount);
+/* 获取所有请求头名称 */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_GetAllHeaderNames(HP_HttpClient pClient, LPCSTR lpszName[], DWORD* pdwCount);
+
+/* 获取 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_GetCookie(HP_HttpClient pClient, LPCSTR lpszName, LPCSTR* lpszValue);
+/* 获取所有 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_GetAllCookies(HP_HttpClient pClient, HP_TCookie lpCookies[], DWORD* pdwCount);
+/* 添加 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_AddCookie(HP_HttpClient pClient, LPCSTR lpszName, LPCSTR lpszValue, BOOL bRelpace);
+/* 删除 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_DeleteCookie(HP_HttpClient pClient, LPCSTR lpszName);
+/* 删除所有 Cookie */
+HPSOCKET_API BOOL __stdcall HP_HttpClient_DeleteAllCookies(HP_HttpClient pClient);
+
+/*****************************************************************************************************************************************************/
+/*************************************************************** Global Function Exports *************************************************************/
+/*****************************************************************************************************************************************************/
+
+/* 获取错误描述文本 */
+HPSOCKET_API LPCTSTR __stdcall HP_GetSocketErrorDesc(En_HP_SocketError enCode);
+/* 调用系统的 GetLastError() 方法获取系统错误代码 */
+HPSOCKET_API DWORD __stdcall SYS_GetLastError();
+// 调用系统的 WSAGetLastError() 方法获取系统错误代码
+HPSOCKET_API int __stdcall SYS_WSAGetLastError();
+// 调用系统的 setsockopt()
+HPSOCKET_API int __stdcall SYS_SetSocketOption(SOCKET sock, int level, int name, LPVOID val, int len);
+// 调用系统的 getsockopt()
+HPSOCKET_API int __stdcall SYS_GetSocketOption(SOCKET sock, int level, int name, LPVOID val, int* len);
+// 调用系统的 ioctlsocket()
+HPSOCKET_API int __stdcall SYS_IoctlSocket(SOCKET sock, long cmd, u_long* arg);
+// 调用系统的 WSAIoctl()
+HPSOCKET_API int __stdcall SYS_WSAIoctl(SOCKET sock, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned);
+
+// 设置 socket 选项:IPPROTO_TCP -> TCP_NODELAY
+HPSOCKET_API int __stdcall SYS_SSO_NoDelay(SOCKET sock, BOOL bNoDelay);
+// 设置 socket 选项:SOL_SOCKET -> SO_DONTLINGER
+HPSOCKET_API int __stdcall SYS_SSO_DontLinger(SOCKET sock, BOOL bDont);
+// 设置 socket 选项:SOL_SOCKET -> SO_LINGER
+HPSOCKET_API int __stdcall SYS_SSO_Linger(SOCKET sock, USHORT l_onoff, USHORT l_linger);
+// 设置 socket 选项:SOL_SOCKET -> SO_RCVBUF
+HPSOCKET_API int __stdcall SYS_SSO_RecvBuffSize(SOCKET sock, int size);
+// 设置 socket 选项:SOL_SOCKET -> SO_SNDBUF
+HPSOCKET_API int __stdcall SYS_SSO_SendBuffSize(SOCKET sock, int size);
+// 设置 socket 选项:SOL_SOCKET -> SO_REUSEADDR
+HPSOCKET_API int __stdcall SYS_SSO_ReuseAddress(SOCKET sock, BOOL bReuse);
+
+// 获取 SOCKET 本地地址信息
+HPSOCKET_API BOOL __stdcall SYS_GetSocketLocalAddress(SOCKET socket, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);
+// 获取 SOCKET 远程地址信息
+HPSOCKET_API BOOL __stdcall SYS_GetSocketRemoteAddress(SOCKET socket, TCHAR lpszAddress[], int* piAddressLen, USHORT* pusPort);

+ 304 - 0
source/hook/hp-src/HPTypeDef.h

@@ -0,0 +1,304 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 3.6.1
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#pragma once
+
+
+/*****************************************************************************************************************************************************/
+/**************************************************************** Base Type Definitions **************************************************************/
+/*****************************************************************************************************************************************************/
+
+
+/************************************************************************
+名称:连接 ID 数据类型
+描述:应用程序可以把 CONNID 定义为自身需要的类型(如:ULONG / ULONGLONG)
+************************************************************************/
+typedef ULONG_PTR	CONNID;
+typedef CONNID		HP_CONNID;
+
+/************************************************************************
+名称:通信组件服务状态
+描述:应用程序可以通过通信组件的 GetState() 方法获取组件当前服务状态
+************************************************************************/
+typedef enum EnServiceState
+{
+	SS_STARTING	= 0,	// 正在启动
+	SS_STARTED	= 1,	// 已经启动
+	SS_STOPPING	= 2,	// 正在停止
+	SS_STOPPED	= 3,	// 已经停止
+} En_HP_ServiceState;
+
+/************************************************************************
+名称:Socket 操作类型
+描述:应用程序的 OnClose() 事件中通过该参数标识是哪种操作导致的错误
+************************************************************************/
+typedef enum EnSocketOperation
+{
+	SO_UNKNOWN	= 0,	// Unknown
+	SO_ACCEPT	= 1,	// Acccept
+	SO_CONNECT	= 2,	// Connect
+	SO_SEND		= 3,	// Send
+	SO_RECEIVE	= 4,	// Receive
+	SO_CLOSE	= 5,	// Close
+} En_HP_SocketOperation;
+
+/************************************************************************
+名称:事件处理结果
+描述:事件的返回值,不同的返回值会影响通信组件的后续行为
+************************************************************************/
+typedef enum EnHandleResult
+{
+	HR_OK		= 0,	// 成功
+	HR_IGNORE	= 1,	// 忽略
+	HR_ERROR	= 2,	// 错误
+} En_HP_HandleResult;
+
+/************************************************************************
+名称:数据抓取结果
+描述:数据抓取操作的返回值
+************************************************************************/
+typedef enum EnFetchResult
+{
+	FR_OK				= 0,	// 成功
+	FR_LENGTH_TOO_LONG	= 1,	// 抓取长度过大
+	FR_DATA_NOT_FOUND	= 2,	// 找不到 ConnID 对应的数据
+} En_HP_FetchResult;
+
+/************************************************************************
+名称:数据发送策略
+描述:Server 组件和 Agent 组件的数据发送策略
+
+* 打包模式(默认)	:尽量把多个发送操作的数据组合在一起发送,增加传输效率
+* 安全模式			:尽量把多个发送操作的数据组合在一起发送,并控制传输速度,避免缓冲区溢出
+* 直接模式			:对每一个发送操作都直接投递,适用于负载不高但要求实时性较高的场合
+
+************************************************************************/
+typedef enum EnSendPolicy
+{
+	SP_PACK				= 0,	// 打包模式(默认)
+	SP_SAFE				= 1,	// 安全模式
+	SP_DIRECT			= 2,	// 直接模式
+} En_HP_SendPolicy;
+
+/************************************************************************
+名称:操作结果代码
+描述:组件 Start() / Stop() 方法执行失败时,可通过 GetLastError() 获取错误代码
+************************************************************************/
+typedef enum EnSocketError
+{
+	SE_OK						= NO_ERROR,	// 成功
+	SE_ILLEGAL_STATE			= 1,		// 当前状态不允许操作
+	SE_INVALID_PARAM			= 2,		// 非法参数
+	SE_SOCKET_CREATE			= 3,		// 创建 SOCKET 失败
+	SE_SOCKET_BIND				= 4,		// 绑定 SOCKET 失败
+	SE_SOCKET_PREPARE			= 5,		// 设置 SOCKET 失败
+	SE_SOCKET_LISTEN			= 6,		// 监听 SOCKET 失败
+	SE_CP_CREATE				= 7,		// 创建完成端口失败
+	SE_WORKER_THREAD_CREATE		= 8,		// 创建工作线程失败
+	SE_DETECT_THREAD_CREATE		= 9,		// 创建监测线程失败
+	SE_SOCKE_ATTACH_TO_CP		= 10,		// 绑定完成端口失败
+	SE_CONNECT_SERVER			= 11,		// 连接服务器失败
+	SE_NETWORK					= 12,		// 网络错误
+	SE_DATA_PROC				= 13,		// 数据处理错误
+	SE_DATA_SEND				= 14,		// 数据发送失败
+
+	/***** SSL Socket 扩展操作结果代码 *****/
+	SE_SSL_ENV_NOT_READY		= 101,		// SSL 环境未就绪
+} En_HP_SocketError;
+
+/************************************************************************
+名称:播送模式
+描述:UDP 组件的播送模式(组播或广播)
+************************************************************************/
+typedef enum EnCastMode
+{
+	CM_MULTICAST	= 0,	// 组播
+	CM_BROADCAST	= 1,	// 广播
+} En_HP_CastMode;
+
+
+/*****************************************************************************************************************************************************/
+/**************************************************************** SSL Type Definitions ***************************************************************/
+/*****************************************************************************************************************************************************/
+
+#ifdef _SSL_SUPPORT
+
+/************************************************************************
+名称:SSL 工作模式
+描述:标识 SSL 的工作模式,客户端模式或服务端模式
+************************************************************************/
+typedef enum EnSSLSessionMode
+{
+	SSL_SM_CLIENT	= 0,	// 客户端模式
+	SSL_SM_SERVER	= 1,	// 服务端模式
+} En_HP_SSLSessionMode;
+
+/************************************************************************
+名称:SSL 验证模式
+描述:SSL 验证模式选项,SSL_VM_PEER 可以和后面两个选项组合一起
+************************************************************************/
+typedef enum EnSSLVerifyMode
+{
+	SSL_VM_NONE					= 0x00,	// SSL_VERIFY_NONE
+	SSL_VM_PEER					= 0x01,	// SSL_VERIFY_PEER
+	SSL_VM_FAIL_IF_NO_PEER_CERT	= 0x02,	// SSL_VERIFY_FAIL_IF_NO_PEER_CERT
+	SSL_VM_CLIENT_ONCE			= 0x04,	// SSL_VERIFY_CLIENT_ONCE
+} En_HP_SSLVerifyMode;
+
+#endif
+
+/*****************************************************************************************************************************************************/
+/**************************************************************** HTTP Type Definitions **************************************************************/
+/*****************************************************************************************************************************************************/
+
+/************************************************************************
+名称:HTTP 版本
+描述:低字节:主版本号,高字节:次版本号
+************************************************************************/
+
+typedef enum EnHttpVersion
+{
+	HV_1_0	= MAKEWORD(1, 0),	// HTTP/1.0
+	HV_1_1	= MAKEWORD(1, 1)	// HTTP/1.1
+} En_HP_HttpVersion;
+
+/************************************************************************
+名称:URL 域
+描述:HTTP 请求行中 URL 段位的域定义
+************************************************************************/
+typedef enum EnHttpUrlField
+{ 
+	HUF_SCHEMA		= 0,	// Schema
+	HUF_HOST		= 1,	// Host
+	HUF_PORT		= 2,	// Port
+	HUF_PATH		= 3,	// Path
+	HUF_QUERY		= 4,	// Query String
+	HUF_FRAGMENT	= 5,	// Fragment
+	HUF_USERINFO	= 6,	// User Info
+	HUF_MAX			= 7,	// (Field Count)
+} En_HP_HttpUrlField;
+
+/************************************************************************
+名称:HTTP 解析结果标识
+描述:指示 HTTP 解析器是否继续执行解析操作
+************************************************************************/
+typedef enum EnHttpParseResult
+{
+	HPR_OK	= 0,			// 继续解析
+	HPR_SKIP_BODY	= 1,	// 跳过当前请求 BODY(仅用于 OnHeadersComplete 事件)
+	HPR_UPGRADE		= 2,	// 升级协议(仅用于 OnHeadersComplete 事件)
+	HPR_ERROR		= -1,	// 终止解析,断开连接
+} En_HP_HttpParseResult;
+
+/************************************************************************
+名称:HTTP 协议升级类型
+描述:标识 HTTP 升级为哪种协议
+************************************************************************/
+typedef enum EnHttpUpgradeType
+{
+	HUT_NONE		= 0,	// 没有升级
+	HUT_WEB_SOCKET	= 1,	// WebSocket
+	HUT_HTTP_TUNNEL	= 2,	// HTTP 隧道
+	HUT_UNKNOWN		= -1,	// 未知类型
+} En_HP_HttpUpgradeType;
+
+/************************************************************************
+名称:HTTP 状态码
+描述:HTTP 标准状态码
+************************************************************************/
+typedef enum EnHttpStatusCode
+{ 
+	HSC_CONTINUE						= 100,
+	HSC_SWITCHING_PROTOCOLS				= 101,
+	HSC_PROCESSING						= 102,
+
+	HSC_OK								= 200,
+	HSC_CREATED							= 201,
+	HSC_ACCEPTED						= 202,
+	HSC_NON_AUTHORITATIVE_INFORMATION	= 203,
+	HSC_NO_CONTENT						= 204,
+	HSC_RESET_CONTENT					= 205,
+	HSC_PARTIAL_CONTENT					= 206,
+	HSC_MULTI_STATUS					= 207,
+
+	HSC_MULTIPLE_CHOICES				= 300,
+	HSC_MOVED_PERMANENTLY				= 301,
+	HSC_MOVED_TEMPORARILY				= 302,
+	HSC_SEE_OTHER						= 303,
+	HSC_NOT_MODIFIED					= 304,
+	HSC_USE_PROXY						= 305,
+	HSC_SWITCH_PROXY					= 306,
+	HSC_TEMPORARY_REDIRECT				= 307,
+
+	HSC_BAD_REQUEST						= 400,
+	HSC_UNAUTHORIZED					= 401,
+	HSC_PAYMENT_REQUIRED				= 402,
+	HSC_FORBIDDEN						= 403,
+	HSC_NOT_FOUND						= 404,
+	HSC_METHOD_NOT_ALLOWED				= 405,
+	HSC_NOT_ACCEPTABLE					= 406,
+	HSC_PROXY_AUTHENTICATION_REQUIRED	= 407,
+	HSC_REQUEST_TIMEOUT					= 408,
+	HSC_CONFLICT						= 409,
+	HSC_GONE							= 410,
+	HSC_LENGTH_REQUIRED					= 411,
+	HSC_PRECONDITION_FAILED				= 412,
+	HSC_REQUEST_ENTITY_TOO_LARGE		= 413,
+	HSC_REQUEST_URI_TOO_LONG			= 414,
+	HSC_UNSUPPORTED_MEDIA_TYPE			= 415,
+	HSC_REQUESTED_RANGE_NOT_SATISFIABLE	= 416,
+	HSC_EXPECTATION_FAILED				= 417,
+	HSC_UNPROCESSABLE_ENTITY			= 422,
+	HSC_LOCKED							= 423,
+	HSC_FAILED_DEPENDENCY				= 424,
+	HSC_UNORDERED_COLLECTION			= 425,
+	HSC_UPGRADE_REQUIRED				= 426,
+	HSC_RETRY_WITH						= 449,
+
+	HSC_INTERNAL_SERVER_ERROR			= 500,
+	HSC_NOT_IMPLEMENTED					= 501,
+	HSC_BAD_GATEWAY						= 502,
+	HSC_SERVICE_UNAVAILABLE				= 503,
+	HSC_GATEWAY_TIMEOUT					= 504,
+	HSC_HTTP_VERSION_NOT_SUPPORTED		= 505,
+	HSC_VARIANT_ALSO_NEGOTIATES			= 506,
+	HSC_INSUFFICIENT_STORAGE			= 507,
+	HSC_BANDWIDTH_LIMIT_EXCEEDED		= 509,
+	HSC_NOT_EXTENDED					= 510,
+
+	HSC_UNPARSEABLE_RESPONSE_HEADERS	= 600
+} En_HP_HttpStatusCode;
+
+/************************************************************************
+名称:Name/Value 结构体
+描述:字符串名值对结构体
+************************************************************************/
+typedef struct TNVPair
+{ 
+	LPCSTR name;
+	LPCSTR value;
+}	HP_TNVPair,
+	TParam, HP_TParam, *LPPARAM, *HP_LPPARAM,
+	THeader, HP_THeader, *LPHEADER, *HP_LPHEADER,
+	TCookie, HP_TCookie, *LPCOOKIE, *HP_LPCOOKIE;

+ 32 - 0
source/hook/hp-src/PrivateHeap.cpp

@@ -0,0 +1,32 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/******************************************************************************
+Module:  PrivateHeap.cpp
+Notices: Copyright (c) 2006 Bruce Liang
+Purpose: ¹ÜÀí½ø³Ì˽ÓжÑ.
+******************************************************************************/
+
+#include "StdAfx.h"
+#include "PrivateHeap.h"

+ 238 - 0
source/hook/hp-src/PrivateHeap.h

@@ -0,0 +1,238 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/******************************************************************************
+Module:  PrivateHeap.h
+Notices: Copyright (c) 2006 Bruce Liang
+Purpose: 管理进程私有堆.
+Desc:
+		 1. CPrivateHeap:		自动创建和销毁进程私有堆
+								每一个该类的对象都代表一个私有堆, 所以
+								该类对象的特点是: 一般声明周期都比较长
+								通常作为全局对象, 其他类的静态成员对象
+								或者一些长生命周期类对象的成员对象
+		 2. CPrivateHeapBuffer: 在私有堆中自动分配和释放指定大小的内存
+								一般用于在函数体内分配和释放局部作用域的堆内存
+								从而避免对 CPrivateHeap::Alloc() 和 
+								CPrivateHeap::Free() 的调用
+
+Examples:
+			CPrivateHeap g_hpPrivate;
+
+			int _tmain(int argc, _TCHAR* argv[])
+			{
+				CPrivateHeapStrBuffer buff(g_hpPrivate, 32);
+				lstrcpy(buff, _T("失败乃成功之母"));
+				SIZE_T size = buff.Size();
+				buff.ReAlloc(40);
+				size = buff.Size();
+				std::cout << (TCHAR*)buff << '\n';
+				// OR
+				// ASSERT(g_hpPrivate.IsValid());
+				// TCHAR* pch	= (TCHAR*)g_hpPrivate.Alloc(32 * sizeof(TCHAR));
+				// lstrcpy(pch, _T("失败乃成功之母"));
+				// SIZE_T size = g_hpPrivate.Size(pch);
+				// g_hpPrivate.ReAlloc(pch, 40 * sizeof(TCHAR));
+				// size = g_hpPrivate.Size(pch);
+				// std::cout << pch << '\n';
+				// g_hpPrivate.Free(pch);
+				// 
+				return 0;
+			}
+
+******************************************************************************/
+
+#pragma once
+
+class CPrivateHeapImpl
+{
+public:
+	PVOID Alloc(SIZE_T dwSize, DWORD dwFlags = 0)
+		{return ::HeapAlloc(m_hHeap, dwFlags, dwSize);}
+
+	PVOID ReAlloc(PVOID pvMemory, SIZE_T dwSize, DWORD dwFlags = 0)
+		{return ::HeapReAlloc(m_hHeap, dwFlags, pvMemory, dwSize);}
+
+	SIZE_T Size(PVOID pvMemory, DWORD dwFlags = 0)
+		{return ::HeapSize(m_hHeap, dwFlags, pvMemory);}
+
+	BOOL Free(PVOID pvMemory, DWORD dwFlags = 0)
+		{return ::HeapFree(m_hHeap, dwFlags, pvMemory);}
+
+	SIZE_T Compact(DWORD dwFlags = 0)
+		{return ::HeapCompact(m_hHeap, dwFlags);}
+
+	BOOL IsValid() {return m_hHeap != nullptr;}
+
+	BOOL Reset()
+	{
+		if(IsValid()) ::HeapDestroy(m_hHeap);
+		m_hHeap = ::HeapCreate(m_dwOptions, m_dwInitSize, m_dwMaxSize);
+
+		return IsValid();
+	}
+
+public:
+	CPrivateHeapImpl(DWORD dwOptions = 0, SIZE_T dwInitSize = 0, SIZE_T dwMaxSize = 0)
+	: m_dwOptions(dwOptions), m_dwInitSize(dwInitSize), m_dwMaxSize(dwMaxSize)
+		{m_hHeap = ::HeapCreate(m_dwOptions, m_dwInitSize, m_dwMaxSize);}
+
+	~CPrivateHeapImpl	()	{if(IsValid()) ::HeapDestroy(m_hHeap);}
+
+	operator HANDLE	()	{return m_hHeap;}
+
+private:
+	CPrivateHeapImpl(const CPrivateHeapImpl&);
+	CPrivateHeapImpl operator = (const CPrivateHeapImpl&);
+
+private:
+	HANDLE	m_hHeap;
+	DWORD	m_dwOptions;
+	SIZE_T	m_dwInitSize;
+	SIZE_T	m_dwMaxSize;
+};
+
+class CGlobalHeapImpl
+{
+public:
+	PVOID Alloc(SIZE_T dwSize, DWORD dwFlags = 0)
+	{
+		PVOID pv = malloc(dwSize);
+		
+		if(pv && (dwFlags | HEAP_ZERO_MEMORY))
+			ZeroMemory(pv, dwSize);
+		
+		return pv;
+	}
+
+	PVOID ReAlloc(PVOID pvMemory, SIZE_T dwSize, DWORD dwFlags = 0)
+	{
+		PVOID pv = realloc(pvMemory, dwSize);
+
+		if(pv && (dwFlags | HEAP_ZERO_MEMORY))
+			ZeroMemory(pv, dwSize);
+		else if(!pv)
+			free(pvMemory);
+
+		return pv;
+	}
+
+	BOOL Free(PVOID pvMemory, DWORD dwFlags = 0)
+	{
+		if(pvMemory)
+		{
+			free(pvMemory);
+			return TRUE;
+		}
+
+		return FALSE;
+	}
+
+	SIZE_T Compact	(DWORD dwFlags = 0)					{return -1;}
+	SIZE_T Size		(PVOID pvMemory, DWORD dwFlags = 0)	{return _msize(pvMemory);}
+
+	BOOL IsValid()	{return TRUE;}
+	BOOL Reset()	{return TRUE;}
+
+public:
+	CGlobalHeapImpl	(DWORD dwOptions = 0, SIZE_T dwInitSize = 0, SIZE_T dwMaxSize = 0) {}
+	~CGlobalHeapImpl()	{}
+
+	operator HANDLE	()	{return nullptr;}
+
+private:
+	CGlobalHeapImpl(const CGlobalHeapImpl&);
+	CGlobalHeapImpl operator = (const CGlobalHeapImpl&);
+};
+
+#ifndef _NOT_USE_PRIVATE_HEAP
+	typedef CPrivateHeapImpl	CPrivateHeap;
+#else
+	typedef CGlobalHeapImpl		CPrivateHeap;
+#endif
+
+template<class T>
+class CPrivateHeapBuffer
+{
+public:
+	CPrivateHeapBuffer(CPrivateHeap& hpPrivate,
+						SIZE_T dwSize		= 0,
+						DWORD dwAllocFlags	= 0,
+						DWORD dwFreeFlags	= 0)
+	: m_hpPrivate(hpPrivate)
+	, m_dwAllocFlags(dwAllocFlags)
+	, m_dwFreeFlags(dwFreeFlags)
+	, m_pvMemory(nullptr)
+	{
+		ASSERT(m_hpPrivate.IsValid());
+		Alloc(dwSize);
+	}
+
+	~CPrivateHeapBuffer() {Free();}
+
+public:
+
+	T* Alloc(SIZE_T dwSize)
+	{
+		if(IsValid())
+			Free();
+
+		return m_pvMemory = (T*)m_hpPrivate.Alloc(dwSize * sizeof(T), m_dwAllocFlags);
+	}
+
+	T* ReAlloc(SIZE_T dwSize, DWORD dwFlags = 0)
+		{return m_pvMemory = (T*)m_hpPrivate.ReAlloc(m_pvMemory, dwSize * sizeof(T), dwFlags);}
+
+	SIZE_T Size(DWORD dwFlags = 0)
+		{return m_hpPrivate.Size(m_pvMemory, dwFlags);}
+
+	BOOL Free()
+	{
+		BOOL isOK = TRUE;
+
+		if(IsValid())
+		{
+			isOK = m_hpPrivate.Free(m_pvMemory, m_dwFreeFlags);
+			m_pvMemory = nullptr;
+		}
+
+		return isOK;
+	}
+
+	BOOL IsValid()			{return m_pvMemory != nullptr;}
+	operator T* ()	const	{return m_pvMemory;}
+
+private:
+	CPrivateHeapBuffer(const CPrivateHeapBuffer&);
+	CPrivateHeapBuffer operator = (const CPrivateHeapBuffer&);
+
+private:
+	CPrivateHeap&	m_hpPrivate;
+	T*				m_pvMemory;
+	DWORD			m_dwAllocFlags;
+	DWORD			m_dwFreeFlags;
+};
+
+typedef CPrivateHeapBuffer<BYTE>	CPrivateHeapByteBuffer;
+typedef CPrivateHeapBuffer<TCHAR>	CPrivateHeapStrBuffer;

+ 26 - 0
source/hook/hp-src/RingBuffer.cpp

@@ -0,0 +1,26 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+#include "RingBuffer.h"

+ 1164 - 0
source/hook/hp-src/RingBuffer.h

@@ -0,0 +1,1164 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#pragma once
+
+#include "STLHelper.h"
+#include "RWLock.h"
+#include "CriticalSection.h"
+
+#define CACHE_LINE		64
+#define PACK_SIZE_OF(T)	(CACHE_LINE - sizeof(T) % CACHE_LINE)
+
+#if !defined (_WIN64)
+	#pragma pack(push, 4)
+#endif
+
+template <class T, class _PutGuard = CCriSec, class _GetGuard = CCriSec> class CRingBuffer
+{
+public:
+	static const UINT DEFAULT_EXPECT = 4096;
+
+public:
+	BOOL Put(T* pElement)
+	{
+		ASSERT(pElement != nullptr);
+
+		{
+			CLocalLock<_PutGuard> locallock(m_csPut);
+
+			ULONGLONG seqPut = m_seqPut;
+
+			WaitForPut(seqPut);
+			if(!IsValid()) return FALSE;
+
+			DoPut(pElement, seqPut);
+		}
+
+		return TRUE;
+	}
+
+	BOOL TryPut(T* pElement)
+	{
+		ASSERT(pElement != nullptr);
+
+		if(!IsValid() || !HasPutSpace(m_seqPut))
+			return FALSE;
+
+		{
+			CLocalLock<_PutGuard> locallock(m_csPut);
+
+			ULONGLONG seqPut = m_seqPut;
+
+			if(!IsValid() || !HasPutSpace(seqPut))
+				return FALSE;
+
+			DoPut(pElement, seqPut);
+		}
+
+		return TRUE;
+	}
+
+	BOOL PutBatch(T* pElements[], int& iCount)
+	{
+		ASSERT(pElements != nullptr && iCount > 0);
+
+		{
+			CLocalLock<_PutGuard> locallock(m_csPut);
+
+			ULONGLONG seqPut = m_seqPut;
+
+			for(int i = 0; i < iCount; ++i)
+			{
+				WaitForPut(seqPut);
+
+				if(!IsValid())
+				{
+					iCount = i;
+					return FALSE;
+				}
+
+				DoPut(*(pElements + i), seqPut);
+			}
+		}
+
+		return TRUE;
+	}
+
+	BOOL TryPutBatch(T* pElements[], int& iCount)
+	{
+		ASSERT(pElements != nullptr && iCount > 0);
+
+		if(!IsValid() || !HasPutSpace(m_seqPut))
+		{
+			iCount = 0;
+			return FALSE;
+		}
+
+		{
+			CLocalLock<_PutGuard> locallock(m_csPut);
+
+			ULONGLONG seqPut = m_seqPut;
+
+			for(int i = 0; i < iCount; ++i)
+			{
+				if(!IsValid() || !HasPutSpace(seqPut))
+				{
+					iCount = i;
+					return FALSE;
+				}
+
+				DoPut(*(pElements + i), seqPut);
+			}
+		}
+
+		return TRUE;
+	}
+
+	BOOL Get(T** pElement)
+	{
+		ASSERT(pElement != nullptr);
+
+		{
+			CLocalLock<_GetGuard> locallock(m_csGet);
+
+			ULONGLONG seqGet = m_seqGet;
+
+			WaitForGet(seqGet);
+			if(!IsValid()) return FALSE;
+
+			DoGet(pElement, seqGet);
+		}
+
+		return TRUE;
+	}
+
+	BOOL TryGet(T** pElement)
+	{
+		ASSERT(pElement != nullptr);
+
+		if(!IsValid() || !HasGetSpace(m_seqGet))
+			return FALSE;
+
+		{
+			CLocalLock<_GetGuard> locallock(m_csGet);
+
+			ULONGLONG seqGet = m_seqGet;
+
+			if(!IsValid() || !HasGetSpace(seqGet))
+				return FALSE;
+
+			DoGet(pElement, seqGet);
+		}
+
+		return TRUE;
+	}
+
+	BOOL GetBatch(T* pElements[], int& iCount)
+	{
+		ASSERT(pElements != nullptr && iCount > 0);
+
+		{
+			CLocalLock<_GetGuard> locallock(m_csGet);
+
+			ULONGLONG seqGet = m_seqGet;
+
+			for(int i = 0; i < iCount; ++i)
+			{
+				WaitForGet(seqGet);
+
+				if(!IsValid())
+				{
+					iCount = i;
+					return FALSE;
+				}
+
+				DoGet(pElements + i, seqGet);
+			}
+		}
+
+		return TRUE;
+	}
+
+	BOOL TryGetBatch(T* pElements[], int& iCount)
+	{
+		ASSERT(pElements != nullptr && iCount > 0);
+
+		if(!IsValid() || !HasGetSpace(m_seqGet))
+		{
+			iCount = 0;
+			return FALSE;
+		}
+
+		{
+			CLocalLock<_GetGuard> locallock(m_csGet);
+
+			ULONGLONG seqGet = m_seqGet;
+
+			for(int i = 0; i < iCount; ++i)
+			{
+				if(!IsValid() || !HasGetSpace(seqGet))
+				{
+					iCount = i;
+					return FALSE;
+				}
+
+				DoGet(pElements + i, seqGet);
+			}
+		}
+
+		return TRUE;
+	}
+
+	BOOL Peek(T** pElement)
+	{
+		ASSERT(pElement != nullptr);
+
+		{
+			//CLocalLock<_GetGuard> locallock(m_csGet);
+
+			ULONGLONG seqGet = m_seqGet;
+
+			if(!IsValid() || !HasGetSpace(seqGet))
+				return FALSE;
+
+			DoPeek(pElement, seqGet);
+		}
+
+		return TRUE;
+	}
+
+	BOOL Create(DWORD dwExpect = DEFAULT_EXPECT)
+	{
+		ASSERT(!IsValid() && dwExpect > 0);
+
+		if(IsValid()) return FALSE;
+
+		m_seqPut = 0;
+		m_seqGet = 0;
+		m_dwReal = Revise(dwExpect);
+		m_pv	 = (T**)malloc(m_dwReal * sizeof(T*));
+		m_bValid = (m_pv != nullptr);
+
+		return IsValid();
+	}
+
+	BOOL Destroy()
+	{
+		if(IsValid())
+		{
+			m_bValid = FALSE;
+
+			CLocalLock<_PutGuard> locallock1(m_csPut);
+			CLocalLock<_GetGuard> locallock2(m_csGet);
+
+			free((void*)m_pv);
+			m_pv	 = nullptr;
+			m_dwReal = 0;
+			m_seqPut = 0;
+			m_seqGet = 0;
+
+			return TRUE;
+		}
+
+		return FALSE;
+	}
+
+private:
+	void DoPut(T* pElement, ULONGLONG& seqPut)
+	{
+		DWORD index = seqPut & (m_dwReal - 1);
+		*(m_pv + index)	= pElement;
+
+		++seqPut;
+		m_seqPut = seqPut;
+	}
+
+	void DoGet(T** pElement, ULONGLONG& seqGet)
+	{
+		DWORD index = seqGet & (m_dwReal - 1);
+		*(pElement) = *(m_pv + index);
+
+		++seqGet;
+		m_seqGet = seqGet;
+	}
+
+	void DoPeek(T** pElement, ULONGLONG& seqGet)
+	{
+		DWORD index = seqGet & (m_dwReal - 1);
+		*(pElement) = *(m_pv + index);
+	}
+
+	BOOL HasPutSpace(ULONGLONG seqPut)
+	{
+		return (seqPut - m_seqGet < m_dwReal);
+	}
+
+	void WaitForPut(ULONGLONG seqPut)
+	{
+		for(DWORD w = 0; IsValid(); ++w)
+		{
+			if(HasPutSpace(seqPut))
+				break;
+
+			::YieldThread(w);
+		}
+	}
+
+	BOOL HasGetSpace(ULONGLONG seqGet)
+	{
+		return (m_seqPut - seqGet > 0);
+	}
+
+	void WaitForGet(ULONGLONG seqGet)
+	{
+		for(DWORD w = 0; IsValid(); ++w)
+		{
+			if(HasGetSpace(seqGet))
+				break;
+
+			::YieldThread(w);
+		}
+	}
+
+	DWORD Revise(DWORD dwExpect)
+	{
+		int index = 0;
+		int shift = sizeof(DWORD) * 8 - 1;
+
+		for(int i = shift; i >= 0; i--)
+		{
+			if(index == 0)
+			{
+				if(dwExpect & (1 << i))
+				{
+					index = i;
+
+					if(index == shift)
+						break;
+				}
+			}
+			else
+			{
+				if(dwExpect & (1 << i))
+					++index;
+
+				break;
+			}
+		}
+
+		return 1 << index;
+	}
+
+public:
+	CRingBuffer(BOOL bCreate = FALSE, DWORD uiExpect = DEFAULT_EXPECT)
+	: m_pv(nullptr)
+	, m_bValid(FALSE)
+	, m_dwReal(0)
+	, m_seqPut(0)
+	, m_seqGet(0)
+	{
+		ASSERT(uiExpect > 0);
+
+		if(bCreate)
+		{
+			Create(uiExpect);
+			ASSERT(IsValid());
+		}
+	}
+
+	~CRingBuffer()
+	{
+		Destroy();
+	}
+
+	BOOL IsValid() {return m_bValid;}
+
+private:
+	CRingBuffer(const CRingBuffer&);
+	CRingBuffer operator = (const CRingBuffer&);
+
+private:
+	BOOL				m_bValid;
+	DWORD				m_dwReal;
+	T**					m_pv;
+	char				pack1[PACK_SIZE_OF(T**)];
+	volatile ULONGLONG	m_seqPut;
+	char				pack4[PACK_SIZE_OF(ULONGLONG)];
+	volatile ULONGLONG	m_seqGet;
+	char				pack5[PACK_SIZE_OF(ULONGLONG)];
+	_PutGuard			m_csPut;
+	char				pack2[PACK_SIZE_OF(_PutGuard)];
+	_GetGuard			m_csGet;
+	char				pack3[PACK_SIZE_OF(_GetGuard)];
+};
+
+typedef CRingBuffer<void, CCriSec, CCriSec>				CCSRingBuffer;
+typedef CRingBuffer<void, CInterCriSec, CInterCriSec>	CICSRingBuffer;
+typedef CRingBuffer<void, CSpinGuard, CSpinGuard>		CSGRingBuffer;
+typedef CRingBuffer<void, CFakeGuard, CFakeGuard>		CFKRingBuffer;
+
+template <class T, class index_type = DWORD, bool adjust_index = false> class CRingCache
+{
+public:
+
+	typedef T*							TPTR;
+	typedef volatile T*					VTPTR;
+
+	typedef unordered_set<index_type>			IndexSet;
+	typedef typename IndexSet::const_iterator	IndexSetCI;
+	typedef typename IndexSet::iterator			IndexSetI;
+
+	static TPTR const E_EMPTY;
+	static TPTR const E_LOCKED;
+	static TPTR const E_MAX_STATUS;
+
+public:
+
+	static index_type&	INDEX_INC(index_type& dwIndex)	{if(adjust_index) ++dwIndex; return dwIndex;}
+	static index_type&	INDEX_DEC(index_type& dwIndex)	{if(adjust_index) --dwIndex; return dwIndex;}
+
+private:
+
+	VTPTR& INDEX_VAL(index_type dwIndex) {return *(m_pv + dwIndex);}
+
+public:
+
+	BOOL Put(TPTR pElement, index_type& dwIndex)
+	{
+		ASSERT(pElement != nullptr);
+
+		BOOL isOK = FALSE;
+
+		while(true)
+		{
+			if(!HasSpace())
+				break;
+
+			DWORD dwCurSeq			= m_dwCurSeq;
+			index_type dwCurIndex	= dwCurSeq % m_dwSize;
+			VTPTR& pValue			= INDEX_VAL(dwCurIndex);
+
+			if(pValue == E_EMPTY)
+			{
+				if(::InterlockedCompareExchangePointer((volatile PVOID*)&pValue, pElement, E_EMPTY) == E_EMPTY)
+				{
+					::InterlockedIncrement(&m_dwCount);
+					::InterlockedCompareExchange(&m_dwCurSeq, dwCurSeq + 1, dwCurSeq);
+
+					if(pElement != E_LOCKED)
+						EmplaceIndex(dwCurIndex);
+
+					dwIndex = INDEX_INC(dwCurIndex);
+					isOK	= TRUE;
+
+					break;
+				}
+			}
+
+			::InterlockedCompareExchange(&m_dwCurSeq, dwCurSeq + 1, dwCurSeq);
+		}
+
+		return isOK;
+	}
+
+	BOOL Get(index_type dwIndex, TPTR* ppElement)
+	{
+		INDEX_DEC(dwIndex);
+
+		ASSERT(dwIndex < m_dwSize);
+		ASSERT(ppElement != nullptr);
+
+		if(dwIndex >= m_dwSize)
+		{
+			*ppElement = nullptr;
+			return FALSE;
+		}
+
+		*ppElement = (TPTR)INDEX_VAL(dwIndex);
+
+		return IsValidElement(*ppElement);
+	}
+
+	BOOL Set(index_type dwIndex, TPTR pElement, TPTR* ppOldElement = nullptr)
+	{
+		TPTR pElement2 = nullptr;
+		Get(dwIndex, &pElement2);
+
+		if(ppOldElement != nullptr)
+			*ppOldElement = pElement2;
+
+		if(pElement == pElement2)
+			return FALSE;
+
+		int f1 = 0;
+		int f2 = 0;
+
+		if(pElement == E_EMPTY)
+		{
+			if(pElement2 == E_LOCKED)
+				f1 = -1;
+			else
+				f1 = f2 = -1;
+		}
+		else if(pElement == E_LOCKED)
+		{
+			if(pElement2 == E_EMPTY)
+				f1 = 1;
+			else
+				f2 = -1;
+		}
+		else
+		{
+			if(pElement2 == E_EMPTY)
+				f1 = f2 = 1;
+			else if(pElement2 == E_LOCKED)
+				f2 = 1;
+		}
+
+		INDEX_DEC(dwIndex);
+
+		BOOL bSetValueFirst = (f1 + f2 >= 0);
+
+		if(bSetValueFirst)	INDEX_VAL(dwIndex) = pElement;
+		if(f1 > 0)			::InterlockedIncrement(&m_dwCount);
+		if(f2 != 0)			(f2 > 0) ? EmplaceIndex(dwIndex) : EraseIndex(dwIndex);
+		if(f1 < 0)			::InterlockedDecrement(&m_dwCount);
+		if(!bSetValueFirst) INDEX_VAL(dwIndex) = pElement;
+
+		ASSERT(Spaces() <= Size());
+
+		return TRUE;
+	}
+
+	BOOL Remove(index_type dwIndex, TPTR* ppElement = nullptr)
+	{
+		return Set(dwIndex, E_EMPTY, ppElement);
+	}
+
+	BOOL AcquireLock(index_type& dwIndex)
+	{
+		return Put(E_LOCKED, dwIndex);
+	}
+
+	BOOL ReleaseLock(index_type dwIndex, TPTR pElement)
+	{
+		ASSERT(pElement == nullptr || IsValidElement(pElement));
+
+		TPTR pElement2 = nullptr;
+		Get(dwIndex, &pElement2);
+
+		if(pElement2 != E_LOCKED)
+			return FALSE;
+
+		Set(dwIndex, pElement);
+
+		return TRUE;
+	}
+
+public:
+
+	void Reset(DWORD dwSize = 0)
+	{
+		if(IsValid())
+			Destroy();
+		if(dwSize > 0)
+			Create(dwSize);
+	}
+	
+	BOOL GetAllElementIndexes(index_type ids[], DWORD& dwCount, BOOL bCopy = TRUE)
+	{
+		if(ids == nullptr || dwCount == 0)
+		{
+			dwCount = Elements();
+			return FALSE;
+		}
+
+		IndexSet* pIndexes = nullptr;
+		IndexSet indexes;
+
+		if(bCopy)
+			pIndexes = &CopyIndexes(indexes);
+		else
+			pIndexes = &m_indexes;
+
+		BOOL isOK	 = FALSE;
+		DWORD dwSize = (DWORD)pIndexes->size();
+
+		if(dwSize > 0 && dwSize <= dwCount)
+		{
+			IndexSetCI it  = pIndexes->begin();
+			IndexSetCI end = pIndexes->end();
+
+			for(int i = 0; it != end; ++it, ++i)
+			{
+				index_type index = *it;
+				ids[i]			 = INDEX_INC(index);
+			}
+
+			isOK = TRUE;
+		}
+
+		dwCount = dwSize;
+		return isOK;
+	}
+	
+	unique_ptr<index_type[]> GetAllElementIndexes(DWORD& dwCount, BOOL bCopy = TRUE)
+	{
+		IndexSet* pIndexes = nullptr;
+		IndexSet indexes;
+
+		if(bCopy)
+			pIndexes = &CopyIndexes(indexes);
+		else
+			pIndexes = &m_indexes;
+
+		unique_ptr<index_type[]> ids;
+		dwCount = (DWORD)pIndexes->size();
+
+		if(dwCount > 0)
+		{
+			ids.reset(new index_type[dwCount]);
+
+			IndexSetCI it  = pIndexes->begin();
+			IndexSetCI end = pIndexes->end();
+
+			for(int i = 0; it != end; ++it, ++i)
+			{
+				index_type index = *it;
+				ids[i]			 = INDEX_INC(index);
+			}
+		}
+
+		return ids;
+	}
+
+	static BOOL IsValidElement(TPTR pElement) {return pElement > E_MAX_STATUS;}
+
+	DWORD Size		()	{return m_dwSize;}
+	DWORD Elements	()	{return (DWORD)m_indexes.size();}
+	DWORD Spaces	()	{return m_dwSize - m_dwCount;}
+	BOOL HasSpace	()	{return m_dwCount < m_dwSize;}
+	BOOL IsEmpty	()	{return m_dwCount == 0;}
+	BOOL IsValid	()	{return m_pv != nullptr;}
+
+private:
+
+	void Create(DWORD dwSize)
+	{
+		ASSERT(!IsValid() && dwSize > 0);
+
+		m_dwCurSeq	= 0;
+		m_dwCount	= 0;
+		m_dwSize	= dwSize;
+		m_pv		= (VTPTR*)malloc(m_dwSize * sizeof(TPTR));
+
+		::ZeroMemory(m_pv, m_dwSize * sizeof(TPTR));
+	}
+
+	void Destroy()
+	{
+		ASSERT(IsValid());
+
+		m_indexes.clear();
+		free((void*)m_pv);
+
+		m_pv		= nullptr;
+		m_dwSize	= 0;
+		m_dwCount	= 0;
+		m_dwCurSeq	= 0;
+	}
+
+	IndexSet& CopyIndexes(IndexSet& indexes)
+	{
+		{
+			CReadLock locallock(m_cs);
+			indexes = m_indexes;
+		}
+
+		return indexes;
+	}
+
+	void EmplaceIndex(index_type dwIndex)
+	{
+		CWriteLock locallock(m_cs);
+		m_indexes.emplace(dwIndex);
+	}
+
+	void EraseIndex(index_type dwIndex)
+	{
+		CWriteLock locallock(m_cs);
+		m_indexes.erase(dwIndex);
+	}
+
+public:
+	CRingCache	(DWORD dwSize = 0)
+	: m_pv		(nullptr)
+	, m_dwSize	(0)
+	, m_dwCount	(0)
+	, m_dwCurSeq(0)
+	{
+		Reset(dwSize);
+	}
+
+	~CRingCache()
+	{
+		Reset(0);
+	}
+
+private:
+	CRingCache(const CRingCache&);
+	CRingCache operator = (const CRingCache&);
+
+private:
+	DWORD				m_dwSize;
+	VTPTR*				m_pv;
+	char				pack1[PACK_SIZE_OF(VTPTR*)];
+	volatile DWORD		m_dwCurSeq;
+	char				pack2[PACK_SIZE_OF(DWORD)];
+	volatile DWORD		m_dwCount;
+	char				pack3[PACK_SIZE_OF(DWORD)];
+
+	CSimpleRWLock		m_cs;
+	IndexSet			m_indexes;
+};
+
+template <class T, class index_type, bool adjust_index> T* const CRingCache<T, index_type, adjust_index>::E_EMPTY		= (T*)0x00;
+template <class T, class index_type, bool adjust_index> T* const CRingCache<T, index_type, adjust_index>::E_LOCKED		= (T*)0x01;
+template <class T, class index_type, bool adjust_index> T* const CRingCache<T, index_type, adjust_index>::E_MAX_STATUS	= (T*)0x0F;
+
+template <class T> class CRingPool
+{
+private:
+
+	typedef T*			TPTR;
+	typedef volatile T*	VTPTR;
+
+	static TPTR const E_EMPTY;
+	static TPTR const E_LOCKED;
+	static TPTR const E_RELEASED;
+	static TPTR const E_OCCUPIED;
+	static TPTR const E_MAX_STATUS;
+
+private:
+
+	VTPTR& INDEX_VAL(DWORD dwIndex) {return *(m_pv + dwIndex);}
+
+public:
+
+	BOOL TryPut(TPTR pElement)
+	{
+		ASSERT(pElement != nullptr);
+
+		BOOL isOK = FALSE;
+
+		while(true)
+		{
+			BOOL bOccupy = FALSE;
+			DWORD seqPut = m_seqPut;
+
+			if(!HasPutSpace(seqPut))
+				break;
+
+			DWORD dwIndex = seqPut % m_dwSize;
+			VTPTR& pValue = INDEX_VAL(dwIndex);
+
+			if(pValue == E_RELEASED)
+			{
+				if(::InterlockedCompareExchangePointer((volatile PVOID*)&pValue, E_OCCUPIED, E_RELEASED) == E_RELEASED)
+					bOccupy = TRUE;
+				else
+					continue;
+			}
+
+			if(pValue == E_EMPTY || bOccupy)
+			{
+				if(::InterlockedCompareExchange(&m_seqPut, seqPut + 1, seqPut) == seqPut)
+				{
+					pValue	= pElement;
+					isOK	= TRUE;
+
+					break;
+				}
+			}
+			else if(pValue == E_LOCKED)
+				break;
+		}
+
+		return isOK;
+	}
+
+	BOOL TryGet(TPTR* ppElement)
+	{
+		ASSERT(ppElement != nullptr);
+
+		BOOL isOK = FALSE;
+
+		while(true)
+		{
+			DWORD seqGet = m_seqGet;
+
+			if(!HasGetSpace(seqGet))
+				break;
+
+			DWORD dwIndex = seqGet % m_dwSize;
+			VTPTR& pValue = INDEX_VAL(dwIndex);
+
+			if(pValue == E_LOCKED)
+				break;
+			else if(pValue != E_EMPTY && pValue != E_RELEASED && pValue != E_OCCUPIED)
+			{
+				if(::InterlockedCompareExchange(&m_seqGet, seqGet + 1, seqGet) == seqGet)
+				{
+					ASSERT(pValue > E_MAX_STATUS);
+
+					*(ppElement)	= (TPTR)pValue;
+					pValue			= E_EMPTY;
+					isOK			= TRUE;
+
+					break;
+				}
+			}
+		}
+
+		return isOK;
+	}
+
+	BOOL TryLock(TPTR* ppElement, DWORD& dwIndex)
+	{
+		ASSERT(ppElement != nullptr);
+
+		BOOL isOK = FALSE;
+
+		while(true)
+		{
+			DWORD seqGet = m_seqGet;
+
+			if(!HasGetSpace(seqGet))
+				break;
+
+			dwIndex			= seqGet % m_dwSize;
+			VTPTR& pValue	= INDEX_VAL(dwIndex);
+
+			if(pValue == E_LOCKED)
+				break;
+			else if(pValue != E_EMPTY && pValue != E_RELEASED && pValue != E_OCCUPIED)
+			{
+				if(::InterlockedCompareExchange(&m_seqGet, seqGet + 1, seqGet) == seqGet)
+				{
+					ASSERT(pValue > E_MAX_STATUS);
+
+					*(ppElement)	= (TPTR)pValue;
+					pValue			= E_LOCKED;
+					isOK			= TRUE;
+
+					break;
+				}
+			}
+		}
+
+		return isOK;
+	}
+
+	void ReleaseLock(TPTR pElement, DWORD dwIndex)
+	{
+		ASSERT(dwIndex < m_dwSize);
+		ASSERT(pElement == nullptr || pElement > E_MAX_STATUS);
+
+		VTPTR& pValue = INDEX_VAL(dwIndex);
+		VERIFY(pValue == E_LOCKED);
+
+		if(pElement != nullptr)
+		{
+			for(DWORD i = 0; ; i++)
+			{
+				if(TryPut(pElement))
+					break;
+
+				DWORD dwPutIndex = m_seqPut % m_dwSize;
+
+				if(dwIndex == dwPutIndex)
+				{
+					pValue = pElement;
+					::InterlockedIncrement(&m_seqPut);
+
+					return;
+				}
+
+				::YieldThread(i);
+			}
+		}
+
+		pValue = E_RELEASED;
+	}
+
+public:
+
+	void Reset(DWORD dwSize = 0)
+	{
+		if(IsValid())
+			Destroy();
+		if(dwSize > 0)
+			Create(dwSize);
+	}
+
+	DWORD Size()		{return m_dwSize;}
+	DWORD Elements()	{return m_seqPut - m_seqGet;}
+	BOOL IsFull()		{return Elements() == Size();}
+	BOOL IsEmpty()		{return Elements() == 0;}
+	BOOL IsValid()		{return m_pv != nullptr;}
+
+private:
+
+	BOOL HasPutSpace(DWORD seqPut)
+	{
+		return (seqPut - m_seqGet < m_dwSize);
+	}
+
+	BOOL HasGetSpace(DWORD seqGet)
+	{
+		return (m_seqPut - seqGet > 0);
+	}
+
+	void Create(DWORD dwSize)
+	{
+		ASSERT(!IsValid() && dwSize > 0);
+
+		m_seqPut = 0;
+		m_seqGet = 0;
+		m_dwSize = dwSize;
+		m_pv	 = (VTPTR*)malloc(m_dwSize * sizeof(TPTR));
+
+		::ZeroMemory(m_pv, m_dwSize * sizeof(TPTR));
+	}
+
+	void Destroy()
+	{
+		ASSERT(IsValid());
+
+		free((void*)m_pv);
+		m_pv = nullptr;
+		m_dwSize = 0;
+		m_seqPut = 0;
+		m_seqGet = 0;
+	}
+
+public:
+	CRingPool(DWORD dwSize = 0)
+	: m_pv(nullptr)
+	, m_dwSize(0)
+	, m_seqPut(0)
+	, m_seqGet(0)
+	{
+		Reset(dwSize);
+	}
+
+	~CRingPool()
+	{
+		Reset(0);
+	}
+
+private:
+	CRingPool(const CRingPool&);
+	CRingPool operator = (const CRingPool&);
+
+private:
+	DWORD				m_dwSize;
+	VTPTR*				m_pv;
+	char				pack1[PACK_SIZE_OF(VTPTR*)];
+	volatile DWORD		m_seqPut;
+	char				pack2[PACK_SIZE_OF(DWORD)];
+	volatile DWORD		m_seqGet;
+	char				pack3[PACK_SIZE_OF(DWORD)];
+};
+
+template <class T> T* const CRingPool<T>::E_EMPTY		= (T*)0x00;
+template <class T> T* const CRingPool<T>::E_LOCKED		= (T*)0x01;
+template <class T> T* const CRingPool<T>::E_RELEASED	= (T*)0x02;
+template <class T> T* const CRingPool<T>::E_OCCUPIED	= (T*)0x03;
+template <class T> T* const CRingPool<T>::E_MAX_STATUS	= (T*)0x0F;
+
+template <class T> class CCASQueue
+{
+private:
+	struct Node;
+	typedef Node*			NPTR;
+	typedef volatile Node*	VNPTR;
+	typedef volatile ULONG	VLONG;
+
+	struct Node
+	{
+		T*		pValue;
+		VNPTR	pNext;
+
+		Node(T* val, NPTR next = nullptr)
+			: pValue(val), pNext(next)
+		{
+
+		}
+	};
+
+public:
+
+	void PushBack(T* pVal)
+	{
+		ASSERT(pVal != nullptr);
+
+		VNPTR pTail	= nullptr;
+		NPTR pNode	= new Node(pVal);
+
+		while(true)
+		{
+			pTail = m_pTail;
+
+			if(::InterlockedCompareExchangePointer((volatile PVOID*)&m_pTail, (PVOID)pNode, (PVOID)pTail) == pTail)
+			{
+				pTail->pNext = pNode;
+				break;
+			}
+		}
+
+		::InterlockedIncrement(&m_lSize);
+	}
+
+	void UnsafePushBack(T* pVal)
+	{
+		ASSERT(pVal != nullptr);
+
+		NPTR pNode		= new Node(pVal);
+		m_pTail->pNext	= pNode;
+		m_pTail			= pNode;
+		
+		::InterlockedIncrement(&m_lSize);
+	}
+
+	BOOL PopFront(T** ppVal)
+	{
+		ASSERT(ppVal != nullptr);
+
+		if(IsEmpty())
+			return FALSE;
+
+		BOOL isOK	= FALSE;
+		NPTR pHead	= nullptr;
+		NPTR pNext	= nullptr;
+		T* pVal		= nullptr;
+
+		while(true)
+		{
+			while(::InterlockedCompareExchange(&m_lLock, 1, 0) != 0)
+				::YieldProcessor();
+
+			pHead = (NPTR)m_pHead;
+			pNext = (NPTR)pHead->pNext;
+
+			if(pNext == nullptr)
+			{
+				m_lLock = 0;
+				break;
+			}
+
+			*ppVal	= pNext->pValue;
+			m_pHead	= pNext;
+
+			m_lLock = 0;
+			isOK	= TRUE;
+
+			::InterlockedDecrement(&m_lSize);
+
+			delete pHead;
+			break;
+		}
+
+		return isOK;
+	}
+
+	BOOL UnsafePopFront(T** ppVal)
+	{
+		if(!UnsafePeekFront(ppVal))
+			return FALSE;
+
+		NPTR pHead	= (NPTR)m_pHead;
+		NPTR pNext	= (NPTR)pHead->pNext;
+		m_pHead		= pNext;
+
+		::InterlockedDecrement(&m_lSize);
+
+		delete pHead;
+		return TRUE;
+	}
+
+	BOOL UnsafePeekFront(T** ppVal)
+	{
+		ASSERT(ppVal != nullptr);
+
+		NPTR pNext = (NPTR)m_pHead->pNext;
+
+		if(pNext == nullptr)
+			return FALSE;
+
+		*ppVal = pNext->pValue;
+
+		return TRUE;
+	}
+
+public:
+
+	ULONG Size()	{return m_lSize;}
+	BOOL IsEmpty()	{return m_lSize == 0;}
+
+public:
+
+	CCASQueue() : m_lLock(0), m_lSize(0)
+	{
+		NPTR pHead = new Node(nullptr);
+		m_pHead = m_pTail = pHead;
+	}
+
+	~CCASQueue()
+	{
+		ASSERT(m_lLock == 0);
+		ASSERT(m_lSize == 0);
+		ASSERT(m_pHead != nullptr);
+		ASSERT(m_pHead->pNext == nullptr);
+
+		while(m_pHead != nullptr)
+		{
+			VNPTR pNode = m_pHead->pNext;
+
+			delete m_pHead;
+			m_pHead = pNode;
+		}
+	}
+
+private:
+	VLONG	m_lLock;
+	VLONG	m_lSize;
+	VNPTR	m_pHead;
+	VNPTR	m_pTail;
+};
+
+#if !defined (_WIN64)
+	#pragma pack(pop)
+#endif

+ 1126 - 0
source/hook/hp-src/STLHelper.h

@@ -0,0 +1,1126 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#pragma once
+
+#include "GeneralHelper.h"
+
+#include <memory>
+#include <string>
+#include <functional>
+#include <algorithm>
+#include <vector>
+#include <deque>
+#include <queue>
+#include <stack>
+#include <list>
+#include <set>
+#include <map>
+#if _MSC_VER >= 1500
+	#include <unordered_set>
+	#include <unordered_map>
+
+	#define hash_set			unordered_set
+	#define hash_map			unordered_map
+	#define hash_multimap		unordered_multimap
+#else
+	#include <hash_set>
+	#include <hash_map>
+
+	#define unordered_set		hash_set
+	#define unordered_map		hash_map
+	#define unordered_multimap	hash_multimap
+#endif
+
+
+using namespace std;
+using namespace stdext;
+using namespace std::tr1;
+
+typedef	wstring		CStdStringW;
+typedef string		CStdStringA;
+
+#ifdef _UNICODE
+	typedef	CStdStringW		CStdString;
+#else
+	typedef CStdStringA		CStdString;
+#endif
+
+typedef list<short>						short_list;
+typedef list<int>						int_list;
+typedef list<long>						long_list;
+typedef list<__int64>					int64_list;
+typedef list<unsigned short>			ushort_list;
+typedef list<unsigned int>				uint_list;
+typedef list<unsigned long>				ulong_list;
+typedef list<unsigned __int64>			uint64_list;
+typedef list<float>						float_list;
+typedef list<double>					double_list;
+typedef stack<short>					short_stack;
+typedef stack<int>						int_stack;
+typedef stack<long>						long_stack;
+typedef stack<__int64>					int64_stack;
+typedef stack<unsigned short>			ushort_stack;
+typedef stack<unsigned int>				uint_stack;
+typedef stack<unsigned long>			ulong_stack;
+typedef stack<unsigned __int64>			uint64_stack;
+typedef stack<float>					float_stack;
+typedef stack<double>					double_stack;
+typedef queue<short>					short_queue;
+typedef queue<int>						int_queue;
+typedef queue<long>						long_queue;
+typedef queue<__int64>					int64_queue;
+typedef queue<unsigned short>			ushort_queue;
+typedef queue<unsigned int>				uint_queue;
+typedef queue<unsigned long>			ulong_queue;
+typedef queue<unsigned __int64>			uint64_queue;
+typedef queue<float>					float_queue;
+typedef queue<double>					double_queue;
+typedef deque<short>					short_deque;
+typedef deque<int>						int_deque;
+typedef deque<long>						long_deque;
+typedef deque<__int64>					int64_deque;
+typedef deque<unsigned short>			ushort_deque;
+typedef deque<unsigned int>				uint_deque;
+typedef deque<unsigned long>			ulong_deque;
+typedef deque<unsigned __int64>			uint64_deque;
+typedef deque<float>					float_deque;
+typedef deque<double>					double_deque;
+typedef vector<short>					short_vector;
+typedef vector<int>						int_vector;
+typedef vector<long>					long_vector;
+typedef vector<__int64>					int64_vector;
+typedef vector<unsigned short>			ushort_vector;
+typedef vector<unsigned int>			uint_vector;
+typedef vector<unsigned long>			ulong_vector;
+typedef vector<unsigned __int64>		uint64_vector;
+typedef vector<float>					float_vector;
+typedef vector<double>					double_vector;
+typedef set<short>						short_set;
+typedef set<int>						int_set;
+typedef set<long>						long_set;
+typedef set<__int64>					int64_set;
+typedef set<unsigned short>				ushort_set;
+typedef set<unsigned int>				uint_set;
+typedef set<unsigned long>				ulong_set;
+typedef set<unsigned __int64>			uint64_set;
+typedef set<float>						float_set;
+typedef set<double>						double_set;
+typedef hash_set<short>					short_hash_set;
+typedef hash_set<int>					int_hash_set;
+typedef hash_set<long>					long_hash_set;
+typedef hash_set<__int64>				int64_hash_set;
+typedef hash_set<unsigned short>		ushort_hash_set;
+typedef hash_set<unsigned int>			uint_hash_set;
+typedef hash_set<unsigned long>			ulong_hash_set;
+typedef hash_set<unsigned __int64>		uint64_hash_set;
+typedef hash_set<float>					float_hash_set;
+typedef hash_set<double>				double_hash_set;
+typedef unordered_set<short>			short_unordered_set;
+typedef unordered_set<int>				int_unordered_set;
+typedef unordered_set<long>				long_unordered_set;
+typedef unordered_set<__int64>			int64_unordered_set;
+typedef unordered_set<unsigned short>	ushort_unordered_set;
+typedef unordered_set<unsigned int>		uint_unordered_set;
+typedef unordered_set<unsigned long>	ulong_unordered_set;
+typedef unordered_set<unsigned __int64>	uint64_unordered_set;
+typedef unordered_set<float>			float_unordered_set;
+typedef unordered_set<double>			double_unordered_set;
+
+typedef list<INT_PTR>					int_ptr_list;
+typedef list<LONG_PTR>					long_ptr_list;
+typedef list<UINT_PTR>					uint_ptr_list;
+typedef list<ULONG_PTR>					ulong_ptr_list;
+typedef stack<INT_PTR>					int_ptr_stack;
+typedef stack<LONG_PTR>					long_ptr_stack;
+typedef stack<UINT_PTR>					uint_ptr_stack;
+typedef stack<ULONG_PTR>				ulong_ptr_stack;
+typedef queue<INT_PTR>					int_ptr_queue;
+typedef queue<LONG_PTR>					long_ptr_queue;
+typedef queue<UINT_PTR>					uint_ptr_queue;
+typedef queue<ULONG_PTR>				ulong_ptr_queue;
+typedef deque<INT_PTR>					int_ptr_deque;
+typedef deque<LONG_PTR>					long_ptr_deque;
+typedef deque<UINT_PTR>					uint_ptr_deque;
+typedef deque<ULONG_PTR>				ulong_ptr_deque;
+typedef vector<INT_PTR>					int_ptr_vector;
+typedef vector<LONG_PTR>				long_ptr_vector;
+typedef vector<UINT_PTR>				uint_ptr_vector;
+typedef vector<ULONG_PTR>				ulong_ptr_vector;
+typedef set<INT_PTR>					int_ptr_set;
+typedef set<LONG_PTR>					long_ptr_set;
+typedef set<UINT_PTR>					uint_ptr_set;
+typedef set<ULONG_PTR>					ulong_ptr_set;
+typedef hash_set<INT_PTR>				int_ptr_hash_set;
+typedef hash_set<LONG_PTR>				long_ptr_hash_set;
+typedef hash_set<UINT_PTR>				uint_ptr_hash_set;
+typedef hash_set<ULONG_PTR>				ulong_ptr_hash_set;
+typedef unordered_set<INT_PTR>			int_ptr_unordered_set;
+typedef unordered_set<LONG_PTR>			long_ptr_unordered_set;
+typedef unordered_set<UINT_PTR>			uint_ptr_unordered_set;
+typedef unordered_set<ULONG_PTR>		ulong_ptr_unordered_set;
+
+/*****************************************************************************/
+/******************************** 容器操作函数 *******************************/
+
+/**********************************
+描述: 清除普通集合 , 适用于 vector<Object> / list<Object>
+参数: 
+	v		: vector / list / set
+
+返回值: 		
+**********************************/
+template<class Set> void ClearSet(Set& v)
+{
+	v.clear();
+}
+
+template<class Set> struct Set_Cleaner
+{
+	static void Clear(Set& v) {ClearSet(v);}
+};
+
+/**********************************
+描述: 清除指针集合 (清除前先释放指针), 适用于 vector<Object*> / list<Object*>
+参数: 
+		v		: vector / list / set
+
+返回值: 		
+**********************************/
+template<class PtrSet> void ClearPtrSet(PtrSet& v)
+{
+	for(PtrSet::iterator	it	= v.begin(),
+							end	= v.end(); 
+							it != end;
+							++it)
+		delete (*it);
+
+	v.clear();
+}
+
+template<class PtrSet> struct PtrSet_Cleaner
+{
+	static void Clear(PtrSet& v) {ClearPtrSet(v);}
+};
+
+/**********************************
+描述: 清除指针集合 (指针同时又指向数组), 适用于 vector<Object*[]> / list<Object*[]>
+参数: 
+		v		: vector / list / set
+
+返回值: 		
+**********************************/
+template<class PtrArraySet> void ClearPtrArraySet(PtrArraySet& v)
+{
+	for(PtrArraySet::iterator	it	= v.begin(),
+								end	= v.end(); 
+								it != end;
+								++it)
+		delete[] (*it);
+
+	v.clear();
+}
+
+template<class PtrArraySet> struct PtrArraySet_Cleaner
+{
+	static void Clear(PtrArraySet& v) {ClearPtrArraySet(v);}
+};
+
+/**********************************
+描述: 清除普通影射 , 适用于 map<key, value>
+参数: 
+	v		: map
+
+返回值: 		
+**********************************/
+template<class Map> void ClearMap(Map& v)
+{
+	v.clear();
+}
+
+template<class Map> struct Map_Cleaner
+{
+	static void Clear(Map& v) {ClearMap(v);}
+};
+
+/**********************************
+描述: 清除指针影射 (清除前先释放指针), 适用于 map<key, Object*>
+参数: 
+		v		: map
+
+返回值: 		
+**********************************/
+template<class PtrMap> void ClearPtrMap(PtrMap& v)
+{
+	for(PtrMap::iterator	it	= v.begin(),
+							end	= v.end(); 
+							it != end;
+							++it)
+		delete it->second;
+
+	v.clear();
+}
+
+template<class PtrMap> struct PtrMap_Cleaner
+{
+	static void Clear(PtrMap& v) {ClearPtrMap(v);}
+};
+
+/**********************************
+描述: 清除指针影射 (指针同时又指向数组), 适用于 map<key, Object*[]>
+参数: 
+		v		: map
+
+返回值: 		
+**********************************/
+template<class PtrArrayMap> void ClearPtrArrayMap(PtrArrayMap& v)
+{
+	for(PtrArrayMap::iterator	it	= v.begin(),
+								end	= v.end(); 
+								it != end;
+								++it)
+		delete[] it->second;
+
+	v.clear();
+}
+
+template<class PtrArrayMap> struct PtrArrayMap_Cleaner
+{
+	static void Clear(PtrArrayMap& v) {ClearPtrArrayMap(v);}
+};
+
+/**********************************
+描述: 清除集合-集合 (清除前先清除内部集合), 适用于 set<vector<Object>*>
+参数: 
+		v		: vector / list / set
+
+返回值: 		
+**********************************/
+template<class SetSet> void ClearSetSet(SetSet& v)
+{
+	for(SetSet::iterator	it	= v.begin(),
+							end	= v.end(); 
+							it != end;
+							++it)
+	{
+		(*it)->clear();
+		delete (*it);
+	}
+
+	v.clear();
+}
+
+template<class SetSet> struct SetSet_Cleaner
+{
+	static void Clear(SetSet& v) {ClearSetSet(v);}
+};
+
+/**********************************
+描述: 清除指针集合-集合 (清除前先清除内部指针集合), 适用于 set<vector<Object*>*>
+参数: 
+		v		: vector / list / set
+
+返回值: 		
+**********************************/
+template<class PtrSetSet> void ClearPtrSetSet(PtrSetSet& v)
+{
+	for(PtrSetSet::iterator	it	= v.begin(),
+							end	= v.end(); 
+							it != end;
+							++it)
+	{
+		ClearPtrSet(**it);
+		delete (*it);
+	}
+
+	v.clear();
+}
+
+template<class PtrSetSet> struct PtrSetSet_Cleaner
+{
+	static void Clear(PtrSetSet& v) {ClearPtrSetSet(v);}
+};
+
+/**********************************
+描述: 清除指针数组集合影射 (清除前先清除指针数组集合), 适用于 map<vector<Object*[]>*>
+参数: 
+		v		: vector / list / set
+
+返回值: 		
+**********************************/
+template<class PtrArraySetSet> void ClearPtrArraySetSet(PtrArraySetSet& v)
+{
+	for(PtrArraySetSet::iterator	it	= v.begin(),
+									end	= v.end(); 
+									it != end;
+									++it)
+	{
+		ClearPtrArraySet(**it);
+		delete (*it);
+	}
+
+	v.clear();
+}
+
+template<class PtrArraySetSet> struct PtrArraySetSet_Cleaner
+{
+	static void Clear(PtrArraySetSet& v) {ClearPtrArraySetSet(v);}
+};
+
+/**********************************
+描述: 清除集合影射 (清除前先清除集合), 适用于 map<key, vector<Object>*>
+参数: 
+		v		: map
+
+返回值: 		
+**********************************/
+template<class SetMap> void ClearSetMap(SetMap& v)
+{
+	for(SetMap::iterator	it	= v.begin(),
+							end	= v.end(); 
+							it != end;
+							++it)
+	{
+		it->second->clear();
+		delete it->second;
+	}
+
+	v.clear();
+}
+
+template<class SetMap> struct SetMap_Cleaner
+{
+	static void Clear(SetMap& v) {ClearSetMap(v);}
+};
+
+/**********************************
+描述: 清除指针集合影射 (清除前先清除指针集合), 适用于 map<key, vector<Object*>*>
+参数: 
+		v		: map
+
+返回值: 		
+**********************************/
+template<class PtrSetMap> void ClearPtrSetMap(PtrSetMap& v)
+{
+	for(PtrSetMap::iterator	it	= v.begin(),
+							end	= v.end(); 
+							it != end;
+							++it)
+	{
+		ClearPtrSet(*(it->second));
+		delete it->second;
+	}
+
+	v.clear();
+}
+
+template<class PtrSetMap> struct PtrSetMap_Cleaner
+{
+	static void Clear(PtrSetMap& v) {ClearPtrSetMap(v);}
+};
+
+/**********************************
+描述: 清除指针数组集合影射 (清除前先清除指针数组集合), 适用于 map<key, vector<Object*[]>*>
+参数: 
+		v		: map
+
+返回值: 		
+**********************************/
+template<class PtrArraySetMap> void ClearPtrArraySetMap(PtrArraySetMap& v)
+{
+	for(PtrArraySetMap::iterator	it	= v.begin(),
+									end	= v.end(); 
+									it != end;
+									++it)
+	{
+		ClearPtrArraySet(*(it->second));
+		delete it->second;
+	}
+
+	v.clear();
+}
+
+template<class PtrArraySetMap> struct PtrArraySetMap_Cleaner
+{
+	static void Clear(PtrArraySetMap& v) {ClearPtrArraySetMap(v);}
+};
+
+/**********************************
+描述: 清除映射-影射 (清除前先清除内部映射), 适用于 map<key, map<key2, Object>*>
+参数: 
+v		: map
+
+返回值: 		
+**********************************/
+template<class MapMap> void ClearMapMap(MapMap& v)
+{
+	for(MapMap::iterator	it	= v.begin(),
+							end	= v.end(); 
+							it != end;
+							++it)
+	{
+		it->second->clear();
+		delete it->second;
+	}
+
+	v.clear();
+}
+
+template<class MapMap> struct MapMap_Cleaner
+{
+	static void Clear(MapMap& v) {ClearMapMap(v);}
+};
+
+/**********************************
+描述: 清除指针映射-影射 (清除前先清除指针内部映射), 适用于 map<key, map<key2, Object*>*>
+参数: 
+		v		: map
+
+返回值: 		
+**********************************/
+template<class PtrMapMap> void ClearPtrMapMap(PtrMapMap& v)
+{
+	for(PtrMapMap::iterator	it	= v.begin(),
+							end	= v.end(); 
+							it != end;
+							++it)
+	{
+		ClearPtrMap(*(it->second));
+		delete it->second;
+	}
+
+	v.clear();
+}
+
+template<class PtrMapMap> struct PtrMapMap_Cleaner
+{
+	static void Clear(PtrMapMap& v) {ClearPtrMapMap(v);}
+};
+
+/**********************************
+描述: 清除指针映射-影射 (清除前先清除指针数组内部映射), 适用于 map<key, map<key2, Object*[]>*>
+参数: 
+		v		: map
+
+返回值: 		
+**********************************/
+template<class PtrArrayMapMap> void ClearPtrArrayMapMap(PtrArrayMapMap& v)
+{
+	for(PtrArrayMapMap::iterator	it	= v.begin(),
+									end	= v.end(); 
+									it != end;
+									++it)
+	{
+		ClearPtrArrayMap(*(it->second));
+		delete it->second;
+	}
+
+	v.clear();
+}
+
+template<class PtrArrayMapMap> struct PtrArrayMapMap_Cleaner
+{
+	static void Clear(PtrArrayMapMap& v) {ClearPtrArrayMapMap(v);}
+};
+
+/************************************************************************/
+/*                           指针集合容器                               */
+/************************************************************************/
+template<class Set, class Cleaner> struct SetWrapper
+{
+	typedef typename Set::iterator			iterator;
+	typedef typename Set::const_iterator	const_iterator;
+	typedef typename Set::value_type		value_type;
+	typedef typename Set::reference			reference;
+	typedef typename Set::const_reference	const_reference;
+	typedef typename Set::pointer			pointer;
+	typedef typename Set::const_pointer		const_pointer;
+	typedef typename Set::size_type			size_type;
+	typedef typename Set::difference_type	difference_type;
+
+	SetWrapper()
+	{
+	}
+
+	virtual ~SetWrapper()
+	{
+		Clear();
+	}
+
+	void Clear()
+	{
+		if(!IsEmpty())
+		{
+			Cleaner::Clear(m_set);
+		}
+	}
+
+	Set& operator *			()			{return m_set;}
+	const Set& operator *	()	const	{return m_set;}
+	Set* operator ->		()			{return &m_set;}
+	const Set* operator ->	()	const	{return &m_set;}
+	Set& Get				()			{return m_set;}
+	operator Set&			()			{return m_set;}
+	bool IsEmpty			()	const	{return m_set.empty();}
+	size_t Size				()	const	{return m_set.size();}
+
+protected:
+	Set m_set;
+
+	DECLARE_NO_COPY_CLASS(SetWrapper)
+};
+
+template<class Set, class Cleaner> struct VectorWrapper : public SetWrapper<Set, Cleaner>
+{
+	VectorWrapper()
+	{
+	}
+
+	reference		operator []	(size_type i)			{return m_set[i];}
+	const_reference operator []	(size_type i)	const	{return m_set[i];}
+
+	DECLARE_NO_COPY_CLASS(VectorWrapper)
+};
+
+/************************************************************************/
+/*                         指针数组集合容器                             */
+/************************************************************************/
+
+
+/************************************************************************/
+/*                           指针映射容器                               */
+/************************************************************************/
+template<class Map, class Cleaner> struct MapWrapper
+{
+	typedef typename Map::iterator			iterator;
+	typedef typename Map::const_iterator	const_iterator;
+	typedef typename Map::key_type			key_type;
+	typedef typename Map::mapped_type		mapped_type;
+	typedef typename Map::value_type		value_type;
+	typedef typename Map::reference			reference;
+	typedef typename Map::const_reference	const_reference;
+	typedef typename Map::pointer			pointer;
+	typedef typename Map::size_type			size_type;
+	typedef typename Map::difference_type	difference_type;
+
+	MapWrapper()
+	{
+	}
+
+	~MapWrapper()
+	{
+		Clear();
+	}
+
+	void Clear()
+	{
+		if(!IsEmpty())
+		{
+			Cleaner::Clear(m_map);
+		}
+	}
+
+	Map&				operator *	()								{return m_map;}
+	const Map&			operator *	()						const	{return m_map;}
+	Map*				operator ->	()								{return &m_map;}
+	const Map*			operator ->	()						const	{return &m_map;}
+	mapped_type&		operator []	(const key_type& key)			{return m_map[key];}
+	const mapped_type&	operator []	(const key_type& key)	const	{return m_map[key];}
+	Map& Get			()			{return m_map;}
+	operator Map&		()			{return m_map;}
+	bool IsEmpty		()	const	{return m_map.empty();}
+	size_t Size			()	const	{return m_map.size();}
+
+private:
+	Map m_map;
+
+	DECLARE_NO_COPY_CLASS(MapWrapper)
+};
+
+/************************************************************************/
+/*                            比较仿函数                                */
+/************************************************************************/
+struct bool_comp_func
+{
+	bool operator() (bool v1, bool v2) const
+	{
+		if(!v1)
+			return false;
+		if(v1 == v2)
+			return false;
+
+		return true;
+	}
+};
+
+template<class T>
+// T -> (signed / unsigned) short / int / long / __int64
+struct integer_comp_func
+{
+	bool operator() (T v1, T v2) const
+	{
+		return v1 < v2;
+	}
+};
+
+typedef integer_comp_func<short>				short_comp_func;
+typedef integer_comp_func<int>					int_comp_func;
+typedef integer_comp_func<long>					long_comp_func;
+typedef integer_comp_func<__int64>				int64_comp_func;
+typedef integer_comp_func<unsigned short>		ushort_comp_func;
+typedef integer_comp_func<unsigned int>			uint_comp_func;
+typedef integer_comp_func<unsigned long>		ulong_comp_func;
+typedef integer_comp_func<unsigned __int64>		uint64_comp_func;
+
+struct float_comp_func
+{
+	bool operator() (float v1, float v2) const
+	{
+		float disc	= v1 - v2;
+		if(fabsf(disc) < 1E-5)
+			return false;
+
+		return disc < 0;
+	}
+};
+
+struct double_comp_func
+{
+	bool operator() (double v1, double v2) const
+	{
+		double disc	= v1 - v2;
+		if(fabs(disc) < 1E-8)
+			return false;
+
+		return disc < 0;
+	}
+};
+
+template<class T, bool CASE = false>
+// T -> (unsigned) char / wchar_t
+struct character_comp_func
+{
+	bool operator() (T v1, T v2) const
+	{
+		if(!CASE)
+		{
+			if(v1 >= 'A' && v1 <= 'Z')	v1 += 32;
+			if(v2 >= 'A' && v2 <= 'Z')	v2 += 32;
+		}
+
+		return v1 < v2;
+	}
+};
+
+typedef character_comp_func<char, true>				char_case_comp_func;
+typedef character_comp_func<unsigned char, true>	uchar_case_comp_func;
+typedef character_comp_func<wchar_t, true>			wchar_case_comp_func;
+typedef character_comp_func<char, false>			char_ucase_comp_func;
+typedef character_comp_func<unsigned char, false>	uchar_ucase_comp_func;
+typedef character_comp_func<wchar_t, false>			wchar_ucase_comp_func;
+
+template<class T, bool CASE = false>
+// T -> TCHAR* / CString
+struct str_comp_func
+{
+	//比较函数。
+	bool operator() (const T &A, const T &B) const
+	{
+		if(!CASE)
+			return lstrcmpi((LPCTSTR)A, (LPCTSTR)B) < 0;
+		else
+			return lstrcmp((LPCTSTR)A, (LPCTSTR)B) < 0;
+	}
+};
+
+typedef str_comp_func<LPCTSTR, true>		case_tchar_comp_func;
+typedef str_comp_func<LPCTSTR, false>		uncase_tchar_comp_func;
+typedef str_comp_func<CString, true>		case_string_comp_func;
+typedef str_comp_func<CString, false>		uncase_string_comp_func;
+typedef case_tchar_comp_func				tchar_ptr_case_comp_func;
+typedef uncase_tchar_comp_func				tchar_ptr_ucase_comp_func;
+typedef case_string_comp_func				string_case_comp_func;
+typedef uncase_string_comp_func				string_ucase_comp_func;
+/************************************************************************/
+/*                            排序仿函数                                */
+/************************************************************************/
+template<bool ASC = true>
+struct bool_sort_func
+{
+	bool operator() (bool v1, bool v2) const
+	{
+		if(v1 == v2)
+			return false;
+
+		bool result = !v1;
+		return ASC ? result : !result;
+	}
+};
+
+typedef bool_sort_func<true>	bool_asc_sort_func;
+typedef bool_sort_func<false>	bool_desc_sort_func;
+
+template<class T, bool ASC = true>
+// T -> (signed / unsigned) short / int / long / __int64
+struct integer_sort_func
+{
+	bool operator() (T v1, T v2) const
+	{
+		if(v1 == v2)
+			return false;
+
+		bool result = v1 < v2;
+		return ASC ? result : !result;
+	}
+};
+
+typedef integer_sort_func<short,			true>		short_asc_sort_func;
+typedef integer_sort_func<unsigned short,	true>		ushort_asc_sort_func;
+typedef integer_sort_func<int,				true>		int_asc_sort_func;
+typedef integer_sort_func<unsigned int,		true>		uint_asc_sort_func;
+typedef integer_sort_func<long,				true>		long_asc_sort_func;
+typedef integer_sort_func<unsigned long,	true>		ulong_asc_sort_func;
+typedef integer_sort_func<__int64,			true>		int64_asc_sort_func;
+typedef integer_sort_func<unsigned __int64,	true>		uint64_asc_sort_func;
+typedef integer_sort_func<short,			false>		short_desc_sort_func;
+typedef integer_sort_func<unsigned short,	false>		ushort_desc_sort_func;
+typedef integer_sort_func<int,				false>		int_desc_sort_func;
+typedef integer_sort_func<unsigned int,		false>		uint_desc_sort_func;
+typedef integer_sort_func<long,				false>		long_desc_sort_func;
+typedef integer_sort_func<unsigned long,	false>		ulong_desc_sort_func;
+typedef integer_sort_func<__int64,			false>		int64_desc_sort_func;
+typedef integer_sort_func<unsigned __int64,	false>		uint64_desc_sort_func;
+
+template<bool ASC = true>
+struct float_sort_func
+{
+	bool operator() (float v1, float v2) const
+	{
+		float disc	= v1 - v2;
+		if(fabsf(disc) < 1E-5)
+			return false;
+
+		bool result = disc < 0;
+		return ASC ? result : !result;
+	}
+};
+
+typedef float_sort_func<true>		float_asc_sort_func;
+typedef float_sort_func<false>		float_desc_sort_func;
+
+template<bool ASC = true>
+struct double_sort_func
+{
+	bool operator() (double v1, double v2) const
+	{
+		double disc	= v1 - v2;
+		if(fabs(disc) < 1E-8)
+			return false;
+
+		bool result = disc < 0;
+		return ASC ? result : !result;
+	}
+};
+
+typedef double_sort_func<true>		double_asc_sort_func;
+typedef double_sort_func<false>		double_desc_sort_func;
+
+template<class T, bool ASC = true, bool CASE = false>
+// T -> (unsigned) char / wchar_t
+struct character_sort_func
+{
+	bool operator() (T v1, T v2) const
+	{
+		if(!CASE)
+		{
+			if(v1 >= 'A' && v1 <= 'Z')	v1 += 32;
+			if(v2 >= 'A' && v2 <= 'Z')	v2 += 32;
+		}
+
+		if(v1 == v2)
+			return false;
+
+		bool result = v1 < v2;
+		return ASC ? result : !result;
+	}
+};
+
+typedef character_sort_func<char, true, true>				char_asc_case_sort_func;
+typedef character_sort_func<unsigned char, true, true>		uchar_asc_case_sort_func;
+typedef character_sort_func<wchar_t, true, true>			wchar_asc_case_sort_func;
+typedef character_sort_func<char, true, false>				char_asc_ucase_sort_func;
+typedef character_sort_func<unsigned char, true, false>		uchar_asc_ucase_sort_func;
+typedef character_sort_func<wchar_t, true, false>			wchar_asc_ucase_sort_func;
+typedef character_sort_func<char, false, true>				char_desc_case_sort_func;
+typedef character_sort_func<unsigned char, false, true>		uchar_desc_case_sort_func;
+typedef character_sort_func<wchar_t, false, true>			wchar_desc_case_sort_func;
+typedef character_sort_func<char, false, false>				char_desc_ucase_sort_func;
+typedef character_sort_func<unsigned char, false, false>	uchar_desc_ucase_sort_func;
+typedef character_sort_func<wchar_t, false, false>			wchar_desc_ucase_sort_func;
+
+template<class T, bool ASC = true, bool CASE = false>
+// T -> TCHAR* / CString
+struct str_sort_func
+{
+	bool operator() (const T& v1, const T& v2) const
+	{
+		bool result;
+
+		if(CASE)
+		{
+			int v = lstrcmp((LPCTSTR)v1, (LPCTSTR)v2);
+			if(v == 0)
+				result = false;
+			else
+				result = v < 0;
+		}
+		else
+		{
+			int v = lstrcmpi((LPCTSTR)v1, (LPCTSTR)v2);
+			if(v == 0)
+				result = false;
+			else
+				result = v < 0;
+		}
+
+		return ASC ? result : !result;
+	}
+};
+
+typedef str_sort_func<TCHAR*, true, true>		tchar_ptr_asc_case_sort_func;
+typedef str_sort_func<CString, true, true>		string_asc_case_sort_func;
+typedef str_sort_func<TCHAR*, true, false>		tchar_ptr_asc_ucase_sort_func;
+typedef str_sort_func<CString, true, false>		string_asc_ucase_sort_func;
+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;
+
+/************************************************************************/
+/*					   smart_ptr 单实体或数组智能指针                    */
+/************************************************************************/
+
+template<class _Ty>
+struct simple_deleter
+{
+	static void delete_ptr(_Ty* pv) {delete pv;}
+};
+
+template<class _Ty>
+struct global_simple_deleter
+{
+	static void delete_ptr(_Ty* pv) {::delete pv;}
+};
+
+template<class _Ty>
+struct array_deleter
+{
+	static void delete_ptr(_Ty* pv) {delete[] pv;}
+};
+
+template<class _Ty>
+struct global_array_deleter
+{
+	static void delete_ptr(_Ty* pv) {::delete[] pv;}
+};
+
+template<class _Ty, class _Deleter>
+class smart_ptr
+{
+public:
+	smart_ptr(_Ty* _Ptr = 0)					: _Myptr(_Ptr)				{}
+	smart_ptr(smart_ptr<_Ty, _Deleter>& _Right)	: _Myptr(_Right.release())	{}
+
+	~smart_ptr()
+	{
+		reset();
+	}
+
+	smart_ptr<_Ty, _Deleter>& reset(_Ty* _Ptr = 0)
+	{
+		if (_Ptr != _Myptr)
+		{
+			if(_Myptr)
+				_Deleter::delete_ptr(_Myptr);
+
+			_Myptr = _Ptr;
+		}
+
+		return *this;
+	}
+
+	smart_ptr<_Ty, _Deleter>& reset(smart_ptr<_Ty, _Deleter>& _Right)
+	{
+		if (this != &_Right)
+			reset(_Right.release());
+
+		return *this;
+	}
+
+	_Ty* release()
+	{
+		_Ty* _Ptr	= _Myptr;
+		_Myptr		= 0;
+
+		return _Ptr;
+	}
+
+	smart_ptr<_Ty, _Deleter>& operator = (_Ty* _Ptr)						{return reset(_Ptr);}
+	smart_ptr<_Ty, _Deleter>& operator = (smart_ptr<_Ty, _Deleter>& _Right)	{return reset(_Right);}
+
+	bool is_valid		()	const	{return _Myptr != 0;}
+	_Ty& operator *		()	const	{return *_Myptr;}
+	_Ty* get			()	const	{return _Myptr;}
+	_Ty* operator ->	()	const	{return _Myptr;}
+	operator _Ty*		()	const	{return _Myptr;}
+
+private:
+	template<class _Other> smart_ptr<_Ty, _Deleter>					(const smart_ptr<_Ty, _Other>&);
+	template<class _Other> smart_ptr<_Ty, _Deleter>&	reset		(const smart_ptr<_Ty, _Other>&);
+	template<class _Other> smart_ptr<_Ty, _Deleter>&	operator =	(const smart_ptr<_Ty, _Other>&);
+
+	template<class _Other> smart_ptr<_Ty, _Deleter>					(const smart_ptr<_Other, _Deleter>&);
+	template<class _Other> smart_ptr<_Ty, _Deleter>&	reset		(const smart_ptr<_Other, _Deleter>&);
+	template<class _Other> smart_ptr<_Ty, _Deleter>&	operator =	(const smart_ptr<_Other, _Deleter>&);
+
+protected:
+	_Ty* _Myptr;
+};
+
+
+/************************************************************************/
+/*				    smart_simple_ptr 单实体智能指针                      */
+/************************************************************************/
+
+template<class _Ty>
+class smart_simple_ptr : public smart_ptr<_Ty, simple_deleter<_Ty>>
+{
+public:
+	smart_simple_ptr(_Ty* _Ptr = 0)									: smart_ptr(_Ptr)	{}
+	smart_simple_ptr(smart_simple_ptr<_Ty>& _Right)					: smart_ptr(_Right)	{}
+	smart_simple_ptr(smart_ptr<_Ty, simple_deleter<_Ty>>& _Right)	: smart_ptr(_Right)	{}
+
+	smart_simple_ptr<_Ty>& operator = (smart_ptr<_Ty, simple_deleter<_Ty>>& _Right)
+	{return (smart_simple_ptr<_Ty>&)__super::operator = (_Right);}
+
+	smart_simple_ptr<_Ty>& operator = (smart_simple_ptr<_Ty>& _Right)
+	{return (smart_simple_ptr<_Ty>&)__super::operator = (_Right);}
+
+	smart_simple_ptr<_Ty>& operator = (_Ty* _Ptr)
+	{return (smart_simple_ptr<_Ty>&)__super::operator = (_Ptr);}
+
+private:
+	template<class _Other> smart_simple_ptr<_Ty>				(const smart_ptr<_Ty, _Other>&);
+	template<class _Other> smart_simple_ptr<_Ty>&	operator =	(const smart_ptr<_Ty, _Other>&);
+
+	template<class _Other> smart_simple_ptr<_Ty>				(const smart_simple_ptr<_Other>&);
+	template<class _Other> smart_simple_ptr<_Ty>&	operator =	(const smart_simple_ptr<_Other>&);
+};
+
+/************************************************************************/
+/*		   smart_gd_simple_ptr 单实体智能指针 (使用全局 delete)          */
+/************************************************************************/
+
+template<class _Ty>
+class smart_gd_simple_ptr : public smart_ptr<_Ty, global_simple_deleter<_Ty>>
+{
+public:
+	smart_gd_simple_ptr(_Ty* _Ptr = 0)										: smart_ptr(_Ptr)	{}
+	smart_gd_simple_ptr(smart_gd_simple_ptr<_Ty>& _Right)					: smart_ptr(_Right)	{}
+	smart_gd_simple_ptr(smart_ptr<_Ty, global_simple_deleter<_Ty>>& _Right)	: smart_ptr(_Right)	{}
+
+	smart_gd_simple_ptr<_Ty>& operator = (smart_ptr<_Ty, global_simple_deleter<_Ty>>& _Right)
+	{return (smart_gd_simple_ptr<_Ty>&)__super::operator = (_Right);}
+
+	smart_gd_simple_ptr<_Ty>& operator = (smart_gd_simple_ptr<_Ty>& _Right)
+	{return (smart_gd_simple_ptr<_Ty>&)__super::operator = (_Right);}
+
+	smart_gd_simple_ptr<_Ty>& operator = (_Ty* _Ptr)
+	{return (smart_gd_simple_ptr<_Ty>&)__super::operator = (_Ptr);}
+
+private:
+	template<class _Other> smart_gd_simple_ptr<_Ty>					(const smart_ptr<_Ty, _Other>&);
+	template<class _Other> smart_gd_simple_ptr<_Ty>&	operator =	(const smart_ptr<_Ty, _Other>&);
+
+	template<class _Other> smart_gd_simple_ptr<_Ty>					(const smart_gd_simple_ptr<_Other>&);
+	template<class _Other> smart_gd_simple_ptr<_Ty>&	operator =	(const smart_gd_simple_ptr<_Other>&);
+};
+
+/************************************************************************/
+/*                   smart_array_ptr 数组智能指针                        */
+/************************************************************************/
+
+template<class _Ty>
+class smart_array_ptr : public smart_ptr<_Ty, array_deleter<_Ty>>
+{
+public:
+	smart_array_ptr(_Ty* _Ptr = 0)								: smart_ptr(_Ptr)	{}
+	smart_array_ptr(smart_simple_ptr<_Ty>& _Right)				: smart_ptr(_Right)	{}
+	smart_array_ptr(smart_ptr<_Ty, array_deleter<_Ty>>& _Right)	: smart_ptr(_Right)	{}
+
+	smart_array_ptr<_Ty>& operator = (smart_ptr<_Ty, array_deleter<_Ty>>& _Right)
+	{return (smart_array_ptr<_Ty>&)__super::operator = (_Right);}
+
+	smart_array_ptr<_Ty>& operator = (smart_array_ptr<_Ty>& _Right)
+	{return (smart_array_ptr<_Ty>&)__super::operator = (_Right);}
+
+	smart_array_ptr<_Ty>& operator = (_Ty* _Ptr)
+	{return (smart_array_ptr<_Ty>&)__super::operator = (_Ptr);}
+
+private:
+	template<class _Other> smart_array_ptr<_Ty>					(const smart_ptr<_Ty, _Other>&);
+	template<class _Other> smart_array_ptr<_Ty>&	operator =	(const smart_ptr<_Ty, _Other>&);
+
+	template<class _Other> smart_array_ptr<_Ty>					(const smart_array_ptr<_Other>&);
+	template<class _Other> smart_array_ptr<_Ty>&	operator =	(const smart_array_ptr<_Other>&);
+};
+
+/************************************************************************/
+/*          smart_gd_array_ptr 单实体智能指针 (使用全局 delete)          */
+/************************************************************************/
+
+template<class _Ty>
+class smart_gd_array_ptr : public smart_ptr<_Ty, global_array_deleter<_Ty>>
+{
+public:
+	smart_gd_array_ptr(_Ty* _Ptr = 0)										: smart_ptr(_Ptr)	{}
+	smart_gd_array_ptr(smart_gd_array_ptr<_Ty>& _Right)						: smart_ptr(_Right)	{}
+	smart_gd_array_ptr(smart_ptr<_Ty, global_array_deleter<_Ty>>& _Right)	: smart_ptr(_Right)	{}
+
+	smart_gd_array_ptr<_Ty>& operator = (smart_ptr<_Ty, global_array_deleter<_Ty>>& _Right)
+	{return (smart_gd_array_ptr<_Ty>&)__super::operator = (_Right);}
+
+	smart_gd_array_ptr<_Ty>& operator = (smart_gd_array_ptr<_Ty>& _Right)
+	{return (smart_gd_array_ptr<_Ty>&)__super::operator = (_Right);}
+
+	smart_gd_array_ptr<_Ty>& operator = (_Ty* _Ptr)
+	{return (smart_gd_array_ptr<_Ty>&)__super::operator = (_Ptr);}
+
+private:
+	template<class _Other> smart_gd_array_ptr<_Ty>				(const smart_ptr<_Ty, _Other>&);
+	template<class _Other> smart_gd_array_ptr<_Ty>&	operator =	(const smart_ptr<_Ty, _Other>&);
+
+	template<class _Other> smart_gd_array_ptr<_Ty>				(const smart_gd_array_ptr<_Other>&);
+	template<class _Other> smart_gd_array_ptr<_Ty>&	operator =	(const smart_gd_array_ptr<_Other>&);
+};

+ 26 - 0
source/hook/hp-src/Semaphore.cpp

@@ -0,0 +1,26 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "stdafx.h"
+#include "Semaphore.h"

+ 70 - 0
source/hook/hp-src/Semaphore.h

@@ -0,0 +1,70 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#pragma once
+
+class CSEM
+{
+public:
+	CSEM(LONG lMaximumCount, LONG lInitialCount = 0, LPCTSTR lpName = nullptr, LPSECURITY_ATTRIBUTES pSecurity = nullptr)
+	{
+		m_hsem = ::CreateSemaphore(pSecurity, lInitialCount, lMaximumCount, lpName);
+		ASSERT(IsValid());
+	}
+
+	~CSEM()
+	{
+		if(IsValid())
+			VERIFY(::CloseHandle(m_hsem));
+	}
+
+	BOOL Open(DWORD dwAccess, BOOL bInheritHandle, LPCTSTR pszName)
+	{
+		if(IsValid())
+			VERIFY(::CloseHandle(m_hsem));
+
+		m_hsem = ::OpenSemaphore(dwAccess, bInheritHandle, pszName);
+		return(IsValid());
+	}
+
+	void Wait(DWORD dwMilliseconds = INFINITE)
+	{
+		::WaitForSingleObject(m_hsem, dwMilliseconds);
+	}
+
+	BOOL Release(LONG lReleaseCount = 1, LPLONG lpPreviousCount = nullptr)
+	{
+		return ::ReleaseSemaphore(m_hsem, lReleaseCount, lpPreviousCount);
+	}
+
+	HANDLE& GetHandle	() 	{return m_hsem;}
+	operator HANDLE		()	{return m_hsem;}
+	BOOL IsValid		()	{return m_hsem != nullptr;}
+
+private:
+	CSEM(const CSEM& sem);
+	CSEM operator = (const CSEM& sem);
+private:
+	HANDLE m_hsem;
+};

+ 50 - 0
source/hook/hp-src/SendPackage.cpp

@@ -0,0 +1,50 @@
+#include "StdAfx.h"
+#include "SendPackage.h"
+
+
+SendPackage::SendPackage(void)
+{
+}
+
+
+SendPackage::~SendPackage(void)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+IMPLEMENT_SERIAL(CAddDepartment, CObject, 0)
+
+CAddDepartment::CAddDepartment()
+{
+	m_strDepartmentName = _T("");
+	m_strDepartmentNote = _T("");
+}
+
+CAddDepartment::~CAddDepartment()
+{
+
+}
+
+CAddDepartment& CAddDepartment::operator=(const CAddDepartment& member)
+{
+	m_strDepartmentName = member.m_strDepartmentName;
+	m_strDepartmentNote = member.m_strDepartmentNote;
+
+	return *this;
+}
+
+void CAddDepartment::Serialize(CArchive& ar)
+{
+	CObject::Serialize(ar);
+
+	if ( ar.IsStoring() )
+	{
+		ar << m_strDepartmentName;
+		ar << m_strDepartmentNote;
+	}
+	else
+	{
+		ar >> m_strDepartmentName;
+		ar >> m_strDepartmentNote;
+	}
+}

+ 47 - 0
source/hook/hp-src/SendPackage.h

@@ -0,0 +1,47 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[IT];
+/*  日    期:[9/25/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __SEND_PACKAGE__
+#define __SEND_PACKAGE__
+
+#pragma once
+
+class SendPackage
+{
+public:
+	SendPackage(void);
+	~SendPackage(void);
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+class CAddDepartment:public CObject
+{
+	DECLARE_SERIAL(CAddDepartment);
+public:
+	CAddDepartment();
+	~CAddDepartment();
+
+	CString		m_strDepartmentName;
+	CString		m_strDepartmentNote;
+
+public:
+	virtual void Serialize(CArchive& ar);
+	CAddDepartment& operator=(const CAddDepartment& member);
+};
+
+#endif

+ 111 - 0
source/hook/hp-src/Singleton.h

@@ -0,0 +1,111 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#define SINGLETON_THIS(ClassName)		ClassName::GetThis()
+#define SINGLETON_INSTANCE(ClassName)	ClassName::GetInstance()
+#define SINGLETON_OBJECT(ObjName)		SINGLETON_INSTANCE(C##ObjName)
+
+#define DEFINE_SINGLETON(ClassName)											\
+	ClassName* ClassName::m_pThis = nullptr;
+
+#define DEFINE_P_THIS(ClassName)											\
+		DEFINE_SINGLETON(ClassName)
+
+#define DECLARE_SINGLETON_INTERFACE(ClassName)								\
+public:																		\
+	static ClassName* GetThis()		{return m_pThis;}						\
+	static ClassName& GetInstance() {return *m_pThis;}						\
+protected:																	\
+	static ClassName* m_pThis;
+
+#define DECLARE_SINGLETON_CREATE_INSTANCE(ClassName)						\
+public:																		\
+	static BOOL CreateInstance()											\
+	{																		\
+		if(!m_pThis)														\
+			m_pThis = new ClassName;										\
+																			\
+		return m_pThis != nullptr;											\
+	}																		\
+																			\
+	static BOOL DeleteInstance()											\
+	{																		\
+		if(m_pThis)															\
+		{																	\
+			delete m_pThis;													\
+			m_pThis = nullptr;												\
+		}																	\
+																			\
+		return m_pThis == nullptr;											\
+	}
+
+#define DECLARE_PRIVATE_DEFAULT_CONSTRUCTOR(ClassName)						\
+private:																	\
+	ClassName(){}
+
+#define DECLARE_PRIVATE_COPY_CONSTRUCTOR(ClassName)							\
+private:																	\
+	ClassName(const ClassName&);											\
+	ClassName& operator = (const ClassName&);
+
+#define DECLARE_NO_COPY_CLASS(className)									\
+		DECLARE_PRIVATE_COPY_CONSTRUCTOR(className)
+
+
+#define DECLARE_SINGLETON_IMPLEMENT_NO_CREATE_INSTANCE(ClassName)			\
+	DECLARE_SINGLETON_INTERFACE(ClassName)									\
+	DECLARE_PRIVATE_DEFAULT_CONSTRUCTOR(ClassName)							\
+	DECLARE_PRIVATE_COPY_CONSTRUCTOR(ClassName)								
+
+#define DECLARE_SINGLETON_IMPLEMENT_NO_DEFAULT_CONSTRUCTOR(ClassName)		\
+	DECLARE_SINGLETON_CREATE_INSTANCE(ClassName)							\
+	DECLARE_PRIVATE_COPY_CONSTRUCTOR(ClassName)
+
+#define DECLARE_SINGLETON_IMPLEMENT(ClassName)								\
+	DECLARE_SINGLETON_IMPLEMENT_NO_DEFAULT_CONSTRUCTOR(ClassName)			\
+	DECLARE_PRIVATE_DEFAULT_CONSTRUCTOR(ClassName)
+
+#define DECLARE_SINGLETON_NO_DEFAULT_CONSTRUCTOR(ClassName)					\
+	DECLARE_SINGLETON_INTERFACE(ClassName)									\
+	DECLARE_SINGLETON_IMPLEMENT_NO_DEFAULT_CONSTRUCTOR(ClassName)
+
+#define DECLARE_SINGLETON(ClassName)										\
+	DECLARE_SINGLETON_NO_DEFAULT_CONSTRUCTOR(ClassName)						\
+	DECLARE_PRIVATE_DEFAULT_CONSTRUCTOR(ClassName)
+
+
+template<class T>
+class CSingleObject
+{
+public:
+	CSingleObject	()	{T::CreateInstance();}
+	~CSingleObject	()	{T::DeleteInstance();}
+	T* GetPointer	()	{return T::GetThis();}
+	T& GetObject	()	{return T::GetInstance();}
+	BOOL IsValid	()	{return GetPointer() != nullptr;}
+};
+
+#define DECLARE_SINGLE_OBJECT(ClassName) CSingleObject<ClassName> _##ClassName##_Single_Object_;

+ 2040 - 0
source/hook/hp-src/SocketInterface.h

@@ -0,0 +1,2040 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 3.6.1
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#pragma once
+
+#include <winsock2.h>
+
+#include "HPTypeDef.h"
+
+/*****************************************************************************************************************************************************/
+/***************************************************************** TCP/UDP Interfaces ****************************************************************/
+/*****************************************************************************************************************************************************/
+
+/************************************************************************
+名称:Complex Socket 监听器基接口
+描述:定义 IServer 和 IAgent 组件监听器的公共方法
+************************************************************************/
+class IComplexSocketListener
+{
+public:
+
+	/*
+	* 名称:握手完成通知
+	* 描述:连接完成握手时,Socket 监听器将收到该通知,监听器接收到该通知后才能开始
+	*		数据收发操作
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
+	*/
+	virtual EnHandleResult OnHandShake(CONNID dwConnID)												= 0;
+
+	/*
+	* 名称:已发送数据通知
+	* 描述:成功发送数据后,Socket 监听器将收到该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			pData		-- 已发送数据缓冲区
+	*			iLength		-- 已发送数据长度
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 该通知不允许返回 HR_ERROR(调试模式下引发断言错误)
+	*/
+	virtual EnHandleResult OnSend(CONNID dwConnID, const BYTE* pData, int iLength)					= 0;
+
+	/*
+	* 名称:数据到达通知(PUSH 模型)
+	* 描述:对于 PUSH 模型的 Socket 通信组件,成功接收数据后将向 Socket 监听器发送该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			pData		-- 已接收数据缓冲区
+	*			iLength		-- 已接收数据长度
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
+	*/
+	virtual EnHandleResult OnReceive(CONNID dwConnID, const BYTE* pData, int iLength)				= 0;
+
+	/*
+	* 名称:数据到达通知(PULL 模型)
+	* 描述:对于 PULL 模型的 Socket 通信组件,成功接收数据后将向 Socket 监听器发送该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			iLength		-- 已接收数据长度
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
+	*/
+	virtual EnHandleResult OnReceive(CONNID dwConnID, int iLength)									= 0;
+
+	/*
+	* 名称:通信错误通知
+	* 描述:通信发生错误后,Socket 监听器将收到该通知,并关闭连接
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			enOperation	-- Socket 操作类型
+	*			iErrorCode	-- 错误代码
+	* 返回值:	忽略返回值
+	*/
+	virtual EnHandleResult OnClose(CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)	= 0;
+
+	/*
+	* 名称:关闭通信组件通知
+	* 描述:通信组件关闭时,Socket 监听器将收到该通知
+	*		
+	* 参数:	
+	* 返回值:忽略返回值
+	*/
+	virtual EnHandleResult OnShutdown()																= 0;
+
+public:
+	virtual ~IComplexSocketListener() {}
+};
+
+/************************************************************************
+名称:服务端 Socket 监听器接口
+描述:定义服务端 Socket 监听器的所有事件
+************************************************************************/
+class IServerListener : public IComplexSocketListener
+{
+public:
+
+	/*
+	* 名称:准备监听通知
+	* 描述:通信服务端组件启动时,在监听 Socket 创建完成并开始执行监听前,Socket 监听
+	*		器将收到该通知,监听器可以在通知处理方法中执行 Socket 选项设置等额外工作
+	*		
+	* 参数:		soListen	-- 监听 Socket
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 终止启动通信服务组件
+	*/
+	virtual EnHandleResult OnPrepareListen(SOCKET soListen)				= 0;
+};
+
+/************************************************************************
+名称:TCP 服务端 Socket 监听器接口
+描述:定义 TCP 服务端 Socket 监听器的所有事件
+************************************************************************/
+class ITcpServerListener : public IServerListener
+{
+public:
+
+	/*
+	* 名称:接收连接通知
+	* 描述:接收到客户端连接请求时,Socket 监听器将收到该通知,监听器可以在通知处理方
+	*		法中执行 Socket 选项设置或拒绝客户端连接等额外工作
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			soClient	-- 客户端 Socket
+	* 返回值:	HR_OK / HR_IGNORE	-- 接受连接
+	*			HR_ERROR			-- 拒绝连接
+	*/
+	virtual EnHandleResult OnAccept(CONNID dwConnID, SOCKET soClient)	= 0;
+};
+
+/************************************************************************
+名称:PUSH 模型服务端 Socket 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CTcpServerListener : public ITcpServerListener
+{
+public:
+	virtual EnHandleResult OnPrepareListen(SOCKET soListen)							{return HR_IGNORE;}
+	virtual EnHandleResult OnAccept(CONNID dwConnID, SOCKET soClient)				{return HR_IGNORE;}
+	virtual EnHandleResult OnHandShake(CONNID dwConnID)								{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(CONNID dwConnID, int iLength)					{return HR_IGNORE;}
+	virtual EnHandleResult OnSend(CONNID dwConnID, const BYTE* pData, int iLength)	{return HR_IGNORE;}
+	virtual EnHandleResult OnShutdown()												{return HR_IGNORE;}
+};
+
+/************************************************************************
+名称:PULL 模型服务端 Socket 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CTcpPullServerListener : public CTcpServerListener
+{
+public:
+	virtual EnHandleResult OnReceive(CONNID dwConnID, int iLength)						= 0;
+	virtual EnHandleResult OnReceive(CONNID dwConnID, const BYTE* pData, int iLength)	{return HR_IGNORE;}
+};
+
+/************************************************************************
+名称:UDP 服务端 Socket 监听器接口
+描述:定义 UDP 服务端 Socket 监听器的所有事件
+************************************************************************/
+class IUdpServerListener : public IServerListener
+{
+public:
+
+	/*
+	* 名称:接收连接通知
+	* 描述:接收到客户端连接请求时,Socket 监听器将收到该通知,监听器可以在通知处理方
+	*		法中执行 Socket 选项设置或拒绝客户端连接等额外工作
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			soClient	-- 客户端 Socket
+	* 返回值:	HR_OK / HR_IGNORE	-- 接受连接
+	*			HR_ERROR			-- 拒绝连接
+	*/
+	virtual EnHandleResult OnAccept(CONNID dwConnID, const SOCKADDR_IN* pSockAddr)	= 0;
+};
+
+/************************************************************************
+名称:UDP 服务端 Socket 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CUdpServerListener : public IUdpServerListener
+{
+public:
+	virtual EnHandleResult OnPrepareListen(SOCKET soListen)							{return HR_IGNORE;}
+	virtual EnHandleResult OnAccept(CONNID dwConnID, const SOCKADDR_IN* pSockAddr)	{return HR_IGNORE;}
+	virtual EnHandleResult OnHandShake(CONNID dwConnID)								{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(CONNID dwConnID, int iLength)					{return HR_IGNORE;}
+	virtual EnHandleResult OnSend(CONNID dwConnID, const BYTE* pData, int iLength)	{return HR_IGNORE;}
+	virtual EnHandleResult OnShutdown()												{return HR_IGNORE;}
+};
+
+/************************************************************************
+名称:通信代理 Socket 监听器接口
+描述:定义 通信代理 Socket 监听器的所有事件
+************************************************************************/
+class IAgentListener : public IComplexSocketListener
+{
+public:
+
+	/*
+	* 名称:准备连接通知
+	* 描述:通信客户端组件启动时,在客户端 Socket 创建完成并开始执行连接前,Socket 监听
+	*		器将收到该通知,监听器可以在通知处理方法中执行 Socket 选项设置等额外工作
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			socket		-- 客户端 Socket
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 终止启动通信客户端组件
+	*/
+	virtual EnHandleResult OnPrepareConnect(CONNID dwConnID, SOCKET socket)		= 0;
+
+	/*
+	* 名称:连接完成通知
+	* 描述:与服务端成功建立连接时,Socket 监听器将收到该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 同步连接:终止启动通信客户端组件
+	*								   异步连接:关闭连接
+	*/
+	virtual EnHandleResult OnConnect(CONNID dwConnID)							= 0;
+};
+
+/************************************************************************
+名称:TCP 通信代理 Socket 监听器接口
+描述:定义 TCP 通信代理 Socket 监听器的所有事件
+************************************************************************/
+class ITcpAgentListener : public IAgentListener
+{
+public:
+
+};
+
+/************************************************************************
+名称:PUSH 模型通信代理 Socket 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CTcpAgentListener : public ITcpAgentListener
+{
+public:
+	virtual EnHandleResult OnPrepareConnect(CONNID dwConnID, SOCKET socket)				{return HR_IGNORE;}
+	virtual EnHandleResult OnConnect(CONNID dwConnID)									{return HR_IGNORE;}
+	virtual EnHandleResult OnHandShake(CONNID dwConnID)									{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(CONNID dwConnID, int iLength)						{return HR_IGNORE;}
+	virtual EnHandleResult OnSend(CONNID dwConnID, const BYTE* pData, int iLength)		{return HR_IGNORE;}
+	virtual EnHandleResult OnShutdown()													{return HR_IGNORE;}
+};
+
+/************************************************************************
+名称:PULL 通信代理 Socket 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CTcpPullAgentListener : public CTcpAgentListener
+{
+public:
+	virtual EnHandleResult OnReceive(CONNID dwConnID, int iLength)						= 0;
+	virtual EnHandleResult OnReceive(CONNID dwConnID, const BYTE* pData, int iLength)	{return HR_IGNORE;}
+};
+
+/************************************************************************
+名称:客户端 Socket 监听器接口
+描述:定义客户端 Socket 监听器的所有事件
+************************************************************************/
+
+class IClient;
+
+class IClientListener
+{
+public:
+	
+	/*
+	* 名称:握手完成通知
+	* 描述:连接完成握手时,Socket 监听器将收到该通知,监听器接收到该通知后才能开始
+	*		数据收发操作
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
+	*/
+	virtual EnHandleResult OnHandShake(IClient* pClient)											= 0;
+
+	/*
+	* 名称:准备连接通知
+	* 描述:通信客户端组件启动时,在客户端 Socket 创建完成并开始执行连接前,Socket 监听
+	*		器将收到该通知,监听器可以在通知处理方法中执行 Socket 选项设置等额外工作
+	*		
+	* 参数:		pClient		-- 连接对象
+	*			socket		-- 客户端 Socket
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 终止启动通信客户端组件
+	*/
+	virtual EnHandleResult OnPrepareConnect(IClient* pClient, SOCKET socket)						= 0;
+
+	/*
+	* 名称:连接完成通知
+	* 描述:与服务端成功建立连接时,Socket 监听器将收到该通知
+	*		
+	* 参数:		pClient		-- 连接对象
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 同步连接:终止启动通信客户端组件
+	*								   异步连接:关闭连接
+	*/
+	virtual EnHandleResult OnConnect(IClient* pClient)												= 0;
+
+	/*
+	* 名称:已发送数据通知
+	* 描述:成功发送数据后,Socket 监听器将收到该通知
+	*		
+	* 参数:		pClient		-- 连接对象
+	*			pData		-- 已发送数据缓冲区
+	*			iLength		-- 已发送数据长度
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 该通知不允许返回 HR_ERROR(调试模式下引发断言错误)
+	*/
+	virtual EnHandleResult OnSend(IClient* pClient, const BYTE* pData, int iLength)					= 0;
+
+	/*
+	* 名称:数据到达通知(PUSH 模型)
+	* 描述:对于 PUSH 模型的 Socket 通信组件,成功接收数据后将向 Socket 监听器发送该通知
+	*		
+	* 参数:		pClient		-- 连接对象
+	*			pData		-- 已接收数据缓冲区
+	*			iLength		-- 已接收数据长度
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
+	*/
+	virtual EnHandleResult OnReceive(IClient* pClient, const BYTE* pData, int iLength)				= 0;
+
+	/*
+	* 名称:数据到达通知(PULL 模型)
+	* 描述:对于 PULL 模型的 Socket 通信组件,成功接收数据后将向 Socket 监听器发送该通知
+	*		
+	* 参数:		pClient		-- 连接对象
+	*			iLength		-- 已接收数据长度
+	* 返回值:	HR_OK / HR_IGNORE	-- 继续执行
+	*			HR_ERROR			-- 引发 OnClose() 事件并关闭连接
+	*/
+	virtual EnHandleResult OnReceive(IClient* pClient, int iLength)									= 0;
+
+	/*
+	* 名称:通信错误通知
+	* 描述:通信发生错误后,Socket 监听器将收到该通知,并关闭连接
+	*		
+	* 参数:		pClient		-- 连接对象
+	*			enOperation	-- Socket 操作类型
+	*			iErrorCode	-- 错误代码
+	* 返回值:	忽略返回值
+	*/
+	virtual EnHandleResult OnClose(IClient* pClient, EnSocketOperation enOperation, int iErrorCode)	= 0;
+
+public:
+	virtual ~IClientListener() {}
+};
+
+/************************************************************************
+名称:TCP 客户端 Socket 监听器接口
+描述:定义 TCP 客户端 Socket 监听器的所有事件
+************************************************************************/
+class ITcpClientListener : public IClientListener
+{
+public:
+
+};
+
+/************************************************************************
+名称:PUSH 模型客户端 Socket 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CTcpClientListener : public ITcpClientListener
+{
+public:
+	virtual EnHandleResult OnPrepareConnect(IClient* pClient, SOCKET socket)			{return HR_IGNORE;}
+	virtual EnHandleResult OnConnect(IClient* pClient)									{return HR_IGNORE;}
+	virtual EnHandleResult OnHandShake(IClient* pClient)								{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(IClient* pClient, int iLength)						{return HR_IGNORE;}
+	virtual EnHandleResult OnSend(IClient* pClient, const BYTE* pData, int iLength)		{return HR_IGNORE;}
+};
+
+/************************************************************************
+名称:PULL 客户端 Socket 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CTcpPullClientListener : public CTcpClientListener
+{
+public:
+	virtual EnHandleResult OnReceive(IClient* pClient, int iLength)						= 0;
+	virtual EnHandleResult OnReceive(IClient* pClient, const BYTE* pData, int iLength)	{return HR_IGNORE;}
+};
+
+/************************************************************************
+名称:UDP 客户端 Socket 监听器接口
+描述:定义 UDP 客户端 Socket 监听器的所有事件
+************************************************************************/
+class IUdpClientListener : public IClientListener
+{
+};
+
+/************************************************************************
+名称:UDP 户端 Socket 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CUdpClientListener : public IUdpClientListener
+{
+public:
+	virtual EnHandleResult OnPrepareConnect(IClient* pClient, SOCKET socket)			{return HR_IGNORE;}
+	virtual EnHandleResult OnConnect(IClient* pClient)									{return HR_IGNORE;}
+	virtual EnHandleResult OnHandShake(IClient* pClient)								{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(IClient* pClient, int iLength)						{return HR_IGNORE;}
+	virtual EnHandleResult OnSend(IClient* pClient, const BYTE* pData, int iLength)		{return HR_IGNORE;}
+};
+
+/************************************************************************
+名称:UDP 传播 Socket 监听器接口
+描述:定义 UDP 传播 Socket 监听器的所有事件
+************************************************************************/
+class IUdpCastListener : public IClientListener
+{
+};
+
+/************************************************************************
+名称:UDP 传播 Socket 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CUdpCastListener : public IUdpCastListener
+{
+public:
+	virtual EnHandleResult OnPrepareConnect(IClient* pClient, SOCKET socket)			{return HR_IGNORE;}
+	virtual EnHandleResult OnConnect(IClient* pClient)									{return HR_IGNORE;}
+	virtual EnHandleResult OnHandShake(IClient* pClient)								{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(IClient* pClient, int iLength)						{return HR_IGNORE;}
+	virtual EnHandleResult OnSend(IClient* pClient, const BYTE* pData, int iLength)		{return HR_IGNORE;}
+};
+
+/************************************************************************
+名称:复合 Socket 组件接口
+描述:定义复合 Socket 组件的所有操作方法和属性访问方法,复合 Socket 组件同时管理多个 Socket 连接
+************************************************************************/
+class IComplexSocket
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+	/*
+	* 名称:关闭通信组件
+	* 描述:关闭通信组件,关闭完成后断开所有连接并释放所有资源
+	*		
+	* 参数:	
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 GetLastError() 获取错误代码
+	*/
+	virtual BOOL Stop	()																		= 0;
+
+	/*
+	* 名称:发送数据
+	* 描述:向指定连接发送数据
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			pBuffer		-- 发送缓冲区
+	*			iLength		-- 发送缓冲区长度
+	*			iOffset		-- 发送缓冲区指针偏移量
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码
+	*/
+	virtual BOOL Send	(CONNID dwConnID, const BYTE* pBuffer, int iLength, int iOffset = 0)	= 0;
+
+	/*
+	* 名称:发送多组数据
+	* 描述:向指定连接发送多组数据
+	*		TCP - 顺序发送所有数据包 
+	*		UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) 
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			pBuffers	-- 发送缓冲区数组
+	*			iCount		-- 发送缓冲区数目
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码
+	*/
+	virtual BOOL SendPackets(CONNID dwConnID, const WSABUF pBuffers[], int iCount)	= 0;
+
+	/*
+	* 名称:断开连接
+	* 描述:断开某个连接
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			bForce		-- 是否强制断开连接
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败
+	*/
+	virtual BOOL Disconnect(CONNID dwConnID, BOOL bForce = TRUE)					= 0;
+
+	/*
+	* 名称:断开超时连接
+	* 描述:断开超过指定时长的连接
+	*		
+	* 参数:		dwPeriod	-- 时长(毫秒)
+	*			bForce		-- 是否强制断开连接
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败
+	*/
+	virtual BOOL DisconnectLongConnections(DWORD dwPeriod, BOOL bForce = TRUE)		= 0;
+
+	/*
+	* 名称:断开静默连接
+	* 描述:断开超过指定时长的静默连接
+	*		
+	* 参数:		dwPeriod	-- 时长(毫秒)
+	*			bForce		-- 是否强制断开连接
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败
+	*/
+	virtual BOOL DisconnectSilenceConnections(DWORD dwPeriod, BOOL bForce = TRUE)	= 0;
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/*
+	* 名称:设置连接的附加数据
+	* 描述:是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序自身决定
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			pv			-- 数据
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败(无效的连接 ID)
+	*/
+	virtual BOOL SetConnectionExtra		(CONNID dwConnID, PVOID pExtra)			= 0;
+
+	/*
+	* 名称:获取连接的附加数据
+	* 描述:是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序自身决定
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			ppv			-- 数据指针
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败(无效的连接 ID)
+	*/
+	virtual BOOL GetConnectionExtra			(CONNID dwConnID, PVOID* ppExtra)	= 0;
+
+	/* 检查通信组件是否已启动 */
+	virtual BOOL HasStarted				()									= 0;
+	/* 查看通信组件当前状态 */
+	virtual EnServiceState GetState		()									= 0;
+	/* 获取连接数 */
+	virtual DWORD GetConnectionCount	()									= 0;
+	/* 获取所有连接的 CONNID */
+	virtual BOOL GetAllConnectionIDs	(CONNID pIDs[], DWORD& dwCount)		= 0;
+	/* 获取某个连接时长(毫秒) */
+	virtual BOOL GetConnectPeriod		(CONNID dwConnID, DWORD& dwPeriod)	= 0;
+	/* 获取某个连接静默时间(毫秒) */
+	virtual BOOL GetSilencePeriod		(CONNID dwConnID, DWORD& dwPeriod)	= 0;
+	/* 获取某个连接的本地地址信息 */
+	virtual BOOL GetLocalAddress		(CONNID dwConnID, TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort)	= 0;
+	/* 获取某个连接的远程地址信息 */
+	virtual BOOL GetRemoteAddress		(CONNID dwConnID, TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort)	= 0;
+	/* 获取最近一次失败操作的错误代码 */
+	virtual EnSocketError GetLastError	()									= 0;
+	/* 获取最近一次失败操作的错误描述 */
+	virtual LPCTSTR GetLastErrorDesc	()									= 0;
+	/* 获取连接中未发出数据的长度 */
+	virtual BOOL GetPendingDataLength	(CONNID dwConnID, int& iPending)	= 0;
+
+	/* 设置数据发送策略 */
+	virtual void SetSendPolicy				(EnSendPolicy enSendPolicy)		= 0;
+	/* 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大)*/
+	virtual void SetMaxConnectionCount		(DWORD MaxConnectionCount)		= 0;
+	/* 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) */
+	virtual void SetFreeSocketObjLockTime	(DWORD dwFreeSocketObjLockTime)	= 0;
+	/* 设置 Socket 缓存池大小(通常设置为平均并发连接数的 1/3 - 1/2) */
+	virtual void SetFreeSocketObjPool		(DWORD dwFreeSocketObjPool)		= 0;
+	/* 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) */
+	virtual void SetFreeBufferObjPool		(DWORD dwFreeBufferObjPool)		= 0;
+	/* 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) */
+	virtual void SetFreeSocketObjHold		(DWORD dwFreeSocketObjHold)		= 0;
+	/* 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) */
+	virtual void SetFreeBufferObjHold		(DWORD dwFreeBufferObjHold)		= 0;
+	/* 设置工作线程数量(通常设置为 2 * CPU + 2) */
+	virtual void SetWorkerThreadCount		(DWORD dwWorkerThreadCount)		= 0;
+	/* 设置是否标记静默时间(设置为 TRUE 时 DisconnectSilenceConnections() 和 GetSilencePeriod() 才有效,默认:TRUE) */
+	virtual void SetMarkSilence				(BOOL bMarkSilence)				= 0;
+
+	/* 获取数据发送策略 */
+	virtual EnSendPolicy GetSendPolicy		()	= 0;
+	/* 获取最大连接数 */
+	virtual DWORD GetMaxConnectionCount		()	= 0;
+	/* 获取 Socket 缓存对象锁定时间 */
+	virtual DWORD GetFreeSocketObjLockTime	()	= 0;
+	/* 获取 Socket 缓存池大小 */
+	virtual DWORD GetFreeSocketObjPool		()	= 0;
+	/* 获取内存块缓存池大小 */
+	virtual DWORD GetFreeBufferObjPool		()	= 0;
+	/* 获取 Socket 缓存池回收阀值 */
+	virtual DWORD GetFreeSocketObjHold		()	= 0;
+	/* 获取内存块缓存池回收阀值 */
+	virtual DWORD GetFreeBufferObjHold		()	= 0;
+	/* 获取工作线程数量 */
+	virtual DWORD GetWorkerThreadCount		()	= 0;
+	/* 检测是否标记静默时间 */
+	virtual BOOL IsMarkSilence				()	= 0;
+
+public:
+	virtual ~IComplexSocket() {}
+};
+
+/************************************************************************
+名称:通信服务端组件接口
+描述:定义通信服务端组件的所有操作方法和属性访问方法
+************************************************************************/
+class IServer : public IComplexSocket
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+	/*
+	* 名称:启动通信组件
+	* 描述:启动服务端通信组件,启动完成后可开始接收客户端连接并收发数据
+	*		
+	* 参数:		lpszBindAddress	-- 监听地址
+	*			usPort			-- 监听端口
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 GetLastError() 获取错误代码
+	*/
+	virtual BOOL Start	(LPCTSTR lpszBindAddress, USHORT usPort)							= 0;
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 获取监听 Socket 的地址信息 */
+	virtual BOOL GetListenAddress(TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort)	= 0;
+};
+
+/************************************************************************
+名称:TCP 通信服务端组件接口
+描述:定义 TCP 通信服务端组件的所有操作方法和属性访问方法
+************************************************************************/
+class ITcpServer : public IServer
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+	/*
+	* 名称:发送小文件
+	* 描述:向指定连接发送 4096 KB 以下的小文件
+	*		
+	* 参数:		dwConnID		-- 连接 ID
+	*			lpszFileName	-- 文件路径
+	*			pHead			-- 头部附加数据
+	*			pTail			-- 尾部附加数据
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码
+	*/
+	virtual BOOL SendSmallFile	(CONNID dwConnID, LPCTSTR lpszFileName, const LPWSABUF pHead = nullptr, const LPWSABUF pTail = nullptr)	= 0;
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置 Accept 预投递数量(根据负载调整设置,Accept 预投递数量越大则支持的并发连接请求越多) */
+	virtual void SetAcceptSocketCount	(DWORD dwAcceptSocketCount)		= 0;
+	/* 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) */
+	virtual void SetSocketBufferSize	(DWORD dwSocketBufferSize)		= 0;
+	/* 设置监听 Socket 的等候队列大小(根据并发连接数量调整设置) */
+	virtual void SetSocketListenQueue	(DWORD dwSocketListenQueue)		= 0;
+	/* 设置正常心跳包间隔(毫秒,0 则不发送心跳包,默认:30 * 1000) */
+	virtual void SetKeepAliveTime		(DWORD dwKeepAliveTime)			= 0;
+	/* 设置异常心跳包间隔(毫秒,0 不发送心跳包,,默认:10 * 1000,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) */
+	virtual void SetKeepAliveInterval	(DWORD dwKeepAliveInterval)		= 0;
+
+	/* 获取 Accept 预投递数量 */
+	virtual DWORD GetAcceptSocketCount	()	= 0;
+	/* 获取通信数据缓冲区大小 */
+	virtual DWORD GetSocketBufferSize	()	= 0;
+	/* 获取监听 Socket 的等候队列大小 */
+	virtual DWORD GetSocketListenQueue	()	= 0;
+	/* 获取正常心跳包间隔 */
+	virtual DWORD GetKeepAliveTime		()	= 0;
+	/* 获取异常心跳包间隔 */
+	virtual DWORD GetKeepAliveInterval	()	= 0;
+};
+
+/************************************************************************
+名称:UDP 通信服务端组件接口
+描述:定义 UDP 通信服务端组件的所有操作方法和属性访问方法
+************************************************************************/
+class IUdpServer : public IServer
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) */
+	virtual void SetMaxDatagramSize		(DWORD dwMaxDatagramSize)	= 0;
+	/* 获取数据报文最大长度 */
+	virtual DWORD GetMaxDatagramSize	()							= 0;
+
+	/* 设置 Receive 预投递数量(根据负载调整设置,Receive 预投递数量越大则丢包概率越小) */
+	virtual void SetPostReceiveCount	(DWORD dwPostReceiveCount)	= 0;
+	/* 获取 Receive 预投递数量 */
+	virtual DWORD GetPostReceiveCount	()							= 0;
+
+	/* 设置监测包尝试次数(0 则不发送监测跳包,如果超过最大尝试次数则认为已断线) */
+	virtual void SetDetectAttempts		(DWORD dwDetectAttempts)	= 0;
+	/* 设置监测包发送间隔(秒,0 不发送监测包) */
+	virtual void SetDetectInterval		(DWORD dwDetectInterval)	= 0;
+	/* 获取心跳检查次数 */
+	virtual DWORD GetDetectAttempts		()							= 0;
+	/* 获取心跳检查间隔 */
+	virtual DWORD GetDetectInterval		()							= 0;
+};
+
+/************************************************************************
+名称:通信代理组件接口
+描述:定义通信代理组件的所有操作方法和属性访问方法,代理组件本质是一个同时连接多个服务器的客户端组件
+************************************************************************/
+class IAgent : public IComplexSocket
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+	/*
+	* 名称:启动通信组件
+	* 描述:启动通信代理组件,启动完成后可开始连接远程服务器
+	*		
+	* 参数:		lpszBindAddress	-- 绑定地址(默认:nullptr,绑定 0.0.0.0)
+	*			bAsyncConnect	-- 是否采用异步 Connect
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 GetLastError() 获取错误代码
+	*/
+	virtual BOOL Start	(LPCTSTR lpszBindAddress = nullptr, BOOL bAsyncConnect = TRUE)						= 0;
+
+	/*
+	* 名称:连接服务器
+	* 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件
+	*		
+	* 参数:		lpszRemoteAddress	-- 服务端地址
+	*			usPort				-- 服务端端口
+	*			pdwConnID			-- 连接 ID(默认:nullptr,不获取连接 ID)
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码
+	*/
+	virtual BOOL Connect(LPCTSTR lpszRemoteAddress, USHORT usPort, CONNID* pdwConnID = nullptr)				= 0;
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+};
+
+/************************************************************************
+名称:TCP 通信代理组件接口
+描述:定义 TCP 通信代理组件的所有操作方法和属性访问方法
+************************************************************************/
+class ITcpAgent : public IAgent
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+	/*
+	* 名称:发送小文件
+	* 描述:向指定连接发送 4096 KB 以下的小文件
+	*		
+	* 参数:		dwConnID		-- 连接 ID
+	*			lpszFileName	-- 文件路径
+	*			pHead			-- 头部附加数据
+	*			pTail			-- 尾部附加数据
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码
+	*/
+	virtual BOOL SendSmallFile	(CONNID dwConnID, LPCTSTR lpszFileName, const LPWSABUF pHead = nullptr, const LPWSABUF pTail = nullptr)	= 0;
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置是否启用地址重用机制(默认:不启用) */
+	virtual void SetReuseAddress		(BOOL bReuseAddress)			= 0;
+	/* 检测是否启用地址重用机制 */
+	virtual BOOL IsReuseAddress			()								= 0;
+
+	/* 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) */
+	virtual void SetSocketBufferSize	(DWORD dwSocketBufferSize)		= 0;
+	/* 设置正常心跳包间隔(毫秒,0 则不发送心跳包,默认:30 * 1000) */
+	virtual void SetKeepAliveTime		(DWORD dwKeepAliveTime)			= 0;
+	/* 设置异常心跳包间隔(毫秒,0 不发送心跳包,,默认:10 * 1000,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) */
+	virtual void SetKeepAliveInterval	(DWORD dwKeepAliveInterval)		= 0;
+
+	/* 获取通信数据缓冲区大小 */
+	virtual DWORD GetSocketBufferSize	()	= 0;
+	/* 获取正常心跳包间隔 */
+	virtual DWORD GetKeepAliveTime		()	= 0;
+	/* 获取异常心跳包间隔 */
+	virtual DWORD GetKeepAliveInterval	()	= 0;
+};
+
+/************************************************************************
+名称:通信客户端组件接口
+描述:定义通信客户端组件的所有操作方法和属性访问方法
+************************************************************************/
+class IClient
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+	/*
+	* 名称:启动通信组件
+	* 描述:启动客户端通信组件并连接服务端,启动完成后可开始收发数据
+	*		
+	* 参数:		lpszRemoteAddress	-- 服务端地址
+	*			usPort				-- 服务端端口
+	*			bAsyncConnect		-- 是否采用异步 Connect
+	*			lpszBindAddress		-- 绑定地址(默认:nullptr,TcpClient/UdpClient -> 不执行绑定操作,UdpCast 绑定 -> 0.0.0.0)
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 GetLastError() 获取错误代码
+	*/
+	virtual BOOL Start	(LPCTSTR lpszRemoteAddress, USHORT usPort, BOOL bAsyncConnect = TRUE, LPCTSTR lpszBindAddress = nullptr)	= 0;
+
+	/*
+	* 名称:关闭通信组件
+	* 描述:关闭客户端通信组件,关闭完成后断开与服务端的连接并释放所有资源
+	*		
+	* 参数:	
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 GetLastError() 获取错误代码
+	*/
+	virtual BOOL Stop	()																		= 0;
+
+	/*
+	* 名称:发送数据
+	* 描述:向服务端发送数据
+	*		
+	* 参数:		pBuffer		-- 发送缓冲区
+	*			iLength		-- 发送缓冲区长度
+	*			iOffset		-- 发送缓冲区指针偏移量
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码
+	*/
+	virtual BOOL Send	(const BYTE* pBuffer, int iLength, int iOffset = 0)						= 0;
+
+	/*
+	* 名称:发送多组数据
+	* 描述:向服务端发送多组数据
+	*		TCP - 顺序发送所有数据包 
+	*		UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) 
+	*		
+	* 参数:		pBuffers	-- 发送缓冲区数组
+	*			iCount		-- 发送缓冲区数目
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码
+	*/
+	virtual BOOL SendPackets(const WSABUF pBuffers[], int iCount)								= 0;
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置连接的附加数据 */
+	virtual void SetExtra					(PVOID pExtra)										= 0;
+
+	/* 获取连接的附加数据 */
+	virtual PVOID GetExtra					()													= 0;
+
+	/* 检查通信组件是否已启动 */
+	virtual BOOL HasStarted					()													= 0;
+	/* 查看通信组件当前状态 */
+	virtual EnServiceState	GetState		()													= 0;
+	/* 获取最近一次失败操作的错误代码 */
+	virtual EnSocketError	GetLastError	()													= 0;
+	/* 获取最近一次失败操作的错误描述 */
+	virtual LPCTSTR			GetLastErrorDesc()													= 0;
+	/* 获取该组件对象的连接 ID */
+	virtual CONNID			GetConnectionID	()													= 0;
+	/* 获取 Client Socket 的地址信息 */
+	virtual BOOL		GetLocalAddress	(TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort)	= 0;
+	/* 获取连接中未发出数据的长度 */
+	virtual BOOL GetPendingDataLength	(int& iPending)											= 0;
+
+	/* 设置内存块缓存池大小(通常设置为 -> PUSH 模型:5 - 10;PULL 模型:10 - 20 ) */
+	virtual void SetFreeBufferPoolSize		(DWORD dwFreeBufferPoolSize)						= 0;
+	/* 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) */
+	virtual void SetFreeBufferPoolHold		(DWORD dwFreeBufferPoolHold)						= 0;
+
+	/* 获取内存块缓存池大小 */
+	virtual DWORD GetFreeBufferPoolSize		()													= 0;
+	/* 获取内存块缓存池回收阀值 */
+	virtual DWORD GetFreeBufferPoolHold		()													= 0;
+
+public:
+	virtual ~IClient() {}
+};
+
+/************************************************************************
+名称:TCP 通信客户端组件接口
+描述:定义 TCP 通信客户端组件的所有操作方法和属性访问方法
+************************************************************************/
+class ITcpClient : public IClient
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+	/*
+	* 名称:发送小文件
+	* 描述:向服务端发送 4096 KB 以下的小文件
+	*		
+	* 参数:		lpszFileName	-- 文件路径
+	*			pHead			-- 头部附加数据
+	*			pTail			-- 尾部附加数据
+	* 返回值:	TRUE	-- 成功
+	*			FALSE	-- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码
+	*/
+	virtual BOOL SendSmallFile	(LPCTSTR lpszFileName, const LPWSABUF pHead = nullptr, const LPWSABUF pTail = nullptr)	= 0;
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+	
+	/* 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为:(N * 1024) - sizeof(TBufferObj)) */
+	virtual void SetSocketBufferSize	(DWORD dwSocketBufferSize)	= 0;
+	/* 设置正常心跳包间隔(毫秒,0 则不发送心跳包,默认:30 * 1000) */
+	virtual void SetKeepAliveTime		(DWORD dwKeepAliveTime)		= 0;
+	/* 设置异常心跳包间隔(毫秒,0 不发送心跳包,,默认:10 * 1000,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) */
+	virtual void SetKeepAliveInterval	(DWORD dwKeepAliveInterval)	= 0;
+
+	/* 获取通信数据缓冲区大小 */
+	virtual DWORD GetSocketBufferSize	()	= 0;
+	/* 获取正常心跳包间隔 */
+	virtual DWORD GetKeepAliveTime		()	= 0;
+	/* 获取异常心跳包间隔 */
+	virtual DWORD GetKeepAliveInterval	()	= 0;
+};
+
+/************************************************************************
+名称:UDP 通信客户端组件接口
+描述:定义 UDP 通信客户端组件的所有操作方法和属性访问方法
+************************************************************************/
+class IUdpClient : public IClient
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) */
+	virtual void SetMaxDatagramSize	(DWORD dwMaxDatagramSize)	= 0;
+	/* 获取数据报文最大长度 */
+	virtual DWORD GetMaxDatagramSize()							= 0;
+
+	/* 设置监测包尝试次数(0 则不发送监测跳包,如果超过最大尝试次数则认为已断线) */
+	virtual void SetDetectAttempts	(DWORD dwDetectAttempts)	= 0;
+	/* 设置监测包发送间隔(秒,0 不发送监测包) */
+	virtual void SetDetectInterval	(DWORD dwDetectInterval)	= 0;
+	/* 获取心跳检查次数 */
+	virtual DWORD GetDetectAttempts	()							= 0;
+	/* 获取心跳检查间隔 */
+	virtual DWORD GetDetectInterval	()							= 0;
+};
+
+/************************************************************************
+名称:UDP 传播组件接口
+描述:定义 UDP 传播(组播或广播)组件的所有操作方法和属性访问方法
+************************************************************************/
+class IUdpCast : public IClient
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) */
+	virtual void SetMaxDatagramSize	(DWORD dwMaxDatagramSize)		= 0;
+	/* 获取数据报文最大长度 */
+	virtual DWORD GetMaxDatagramSize()								= 0;
+
+	/* 设置是否启用地址重用机制(默认:不启用) */
+	virtual void SetReuseAddress	(BOOL bReuseAddress)			= 0;
+	/* 检测是否启用地址重用机制 */
+	virtual BOOL IsReuseAddress		()								= 0;
+
+	/* 设置传播模式(组播或广播) */
+	virtual void SetCastMode		(EnCastMode enCastMode)			= 0;
+	/* 获取传播模式 */
+	virtual EnCastMode GetCastMode	()								= 0;
+
+	/* 设置组播报文的 TTL(0 - 255) */
+	virtual void SetMultiCastTtl	(int iMCTtl)					= 0;
+	/* 获取组播报文的 TTL */
+	virtual int GetMultiCastTtl		()								= 0;
+
+	/* 设置是否启用组播环路(TRUE or FALSE) */
+	virtual void SetMultiCastLoop	(BOOL bMCLoop)					= 0;
+	/* 检测是否启用组播环路 */
+	virtual BOOL IsMultiCastLoop	()								= 0;
+
+	/* 获取当前数据报的远程地址信息(通常在 OnReceive 事件中调用) */
+	virtual BOOL GetRemoteAddress	(TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort)	= 0;
+};
+
+/************************************************************************
+名称:Server/Agent PULL 模型组件接口
+描述:定义 Server/Agent 组件的 PULL 模型组件的所有操作方法
+************************************************************************/
+class IPullSocket
+{
+public:
+
+	/*
+	* 名称:抓取数据
+	* 描述:用户通过该方法从 Socket 组件中抓取数据
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			pData		-- 抓取缓冲区
+	*			iLength		-- 抓取数据长度
+	* 返回值:	EnFetchResult
+	*/
+	virtual EnFetchResult Fetch	(CONNID dwConnID, BYTE* pData, int iLength)	= 0;
+
+	/*
+	* 名称:窥探数据(不会移除缓冲区数据)
+	* 描述:用户通过该方法从 Socket 组件中窥探数据
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			pData		-- 窥探缓冲区
+	*			iLength		-- 窥探数据长度
+	* 返回值:	EnFetchResult
+	*/
+	virtual EnFetchResult Peek	(CONNID dwConnID, BYTE* pData, int iLength)	= 0;
+
+public:
+	virtual ~IPullSocket() {}
+};
+
+/************************************************************************
+名称:Client PULL 模型组件接口
+描述:定义 Client 组件的 PULL 模型组件的所有操作方法
+************************************************************************/
+class IPullClient
+{
+public:
+
+	/*
+	* 名称:抓取数据
+	* 描述:用户通过该方法从 Socket 组件中抓取数据
+	*		
+	* 参数:		pData		-- 抓取缓冲区
+	*			iLength		-- 抓取数据长度
+	* 返回值:	EnFetchResult
+	*/
+	virtual EnFetchResult Fetch	(BYTE* pData, int iLength)	= 0;
+
+	/*
+	* 名称:窥探数据(不会移除缓冲区数据)
+	* 描述:用户通过该方法从 Socket 组件中窥探数据
+	*		
+	* 参数:		pData		-- 窥探缓冲区
+	*			iLength		-- 窥探数据长度
+	* 返回值:	EnFetchResult
+	*/
+	virtual EnFetchResult Peek	(BYTE* pData, int iLength)	= 0;
+
+public:
+	virtual ~IPullClient() {}
+};
+
+/************************************************************************
+名称:TCP Server PULL 模型组件接口
+描述:继承了 ITcpServer 和 IPullSocket
+************************************************************************/
+class ITcpPullServer : public IPullSocket, public ITcpServer
+{
+public:
+	/* IServer* 转换为 IPullSocket* */
+	inline static IPullSocket* ToPull(IServer* pServer)
+	{
+		return (IPullSocket*)((char*)pServer - sizeof(IPullSocket));
+	}
+
+	/* IPullSocket* 转换为 ITcpServer* */
+	inline static ITcpServer* ToServer(IPullSocket* pPullSocket)
+	{
+		return (ITcpServer*)((char*)pPullSocket + sizeof(IPullSocket));
+	}
+};
+
+/************************************************************************
+名称:TCP Agent PULL 模型组件接口
+描述:继承了 ITcpAgent 和 IPullSocket
+************************************************************************/
+class ITcpPullAgent : public IPullSocket, public ITcpAgent
+{
+public:
+	/* IAgent* 转换为 IPullSocket* */
+	inline static IPullSocket* ToPull(IAgent* pAgent)
+	{
+		return (IPullSocket*)((char*)pAgent - sizeof(IPullSocket));
+	}
+
+	/* IPullSocket* 转换为 ITcpAgent* */
+	inline static ITcpAgent* ToAgent(IPullSocket* pPullSocket)
+	{
+		return (ITcpAgent*)((char*)pPullSocket + sizeof(IPullSocket));
+	}
+};
+
+/************************************************************************
+名称:TCP Client PULL 模型组件接口
+描述:继承了 ITcpClient 和 IPullClient
+************************************************************************/
+class ITcpPullClient : public IPullClient, public ITcpClient
+{
+public:
+	/* IClient* 转换为 IPullClient* */
+	inline static IPullClient* ToPull(IClient* pClient)
+	{
+		return (IPullClient*)((char*)pClient - sizeof(IPullClient));
+	}
+
+	/* IPullClient* 转换为 ITcpClient* */
+	inline static ITcpClient* ToClient(IPullClient* pPullClient)
+	{
+		return (ITcpClient*)((char*)pPullClient + sizeof(IPullClient));
+	}
+};
+
+/************************************************************************
+名称:Server/Agent PACK 模型组件接口
+描述:定义 Server/Agent 组件的 PACK 模型组件的所有操作方法
+************************************************************************/
+class IPackSocket
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置数据包最大长度(有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000) */
+	virtual void SetMaxPackSize		(DWORD dwMaxPackSize)			= 0;
+	/* 设置包头标识(有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0) */
+	virtual void SetPackHeaderFlag	(USHORT usPackHeaderFlag)		= 0;
+
+	/* 获取数据包最大长度 */
+	virtual DWORD GetMaxPackSize	()								= 0;
+	/* 获取包头标识 */
+	virtual USHORT GetPackHeaderFlag()								= 0;
+
+public:
+	virtual ~IPackSocket() {}
+};
+
+/************************************************************************
+名称:Client PACK 模型组件接口
+描述:定义 Client 组件的 PACK 模型组件的所有操作方法
+************************************************************************/
+class IPackClient
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置数据包最大长度(有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000) */
+	virtual void SetMaxPackSize		(DWORD dwMaxPackSize)			= 0;
+	/* 设置包头标识(有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0) */
+	virtual void SetPackHeaderFlag	(USHORT usPackHeaderFlag)		= 0;
+
+	/* 获取数据包最大长度 */
+	virtual DWORD GetMaxPackSize	()								= 0;
+	/* 获取包头标识 */
+	virtual USHORT GetPackHeaderFlag()								= 0;
+
+public:
+	virtual ~IPackClient() {}
+};
+
+/************************************************************************
+名称:TCP Server PACK 模型组件接口
+描述:继承了 ITcpServer 和 IPackSocket
+************************************************************************/
+class ITcpPackServer : public IPackSocket, public ITcpServer
+{
+public:
+	/* IServer* 转换为 IPackSocket* */
+	inline static IPackSocket* ToPack(IServer* pServer)
+	{
+		return (IPackSocket*)((char*)pServer - sizeof(IPackSocket));
+	}
+
+	/* IPackSocket* 转换为 ITcpServer* */
+	inline static ITcpServer* ToServer(IPackSocket* pPackSocket)
+	{
+		return (ITcpServer*)((char*)pPackSocket + sizeof(IPackSocket));
+	}
+};
+
+/************************************************************************
+名称:TCP Agent PACK 模型组件接口
+描述:继承了 ITcpAgent 和 IPackSocket
+************************************************************************/
+class ITcpPackAgent : public IPackSocket, public ITcpAgent
+{
+public:
+	/* IAgent* 转换为 IPackSocket* */
+	inline static IPackSocket* ToPack(IAgent* pAgent)
+	{
+		return (IPackSocket*)((char*)pAgent - sizeof(IPackSocket));
+	}
+
+	/* IPackSocket* 转换为 ITcpAgent* */
+	inline static ITcpAgent* ToAgent(IPackSocket* pPackSocket)
+	{
+		return (ITcpAgent*)((char*)pPackSocket + sizeof(IPackSocket));
+	}
+};
+
+/************************************************************************
+名称:TCP Client PACK 模型组件接口
+描述:继承了 ITcpClient 和 IPackClient
+************************************************************************/
+class ITcpPackClient : public IPackClient, public ITcpClient
+{
+public:
+	/* IClient* 转换为 IPackClient* */
+	inline static IPackClient* ToPack(IClient* pClient)
+	{
+		return (IPackClient*)((char*)pClient - sizeof(IPackClient));
+	}
+
+	/* IPackClient* 转换为 ITcpClient* */
+	inline static ITcpClient* ToClient(IPackClient* pPackClient)
+	{
+		return (ITcpClient*)((char*)pPackClient + sizeof(IPackClient));
+	}
+};
+
+/*****************************************************************************************************************************************************/
+/****************************************************************** HTTP Interfaces ******************************************************************/
+/*****************************************************************************************************************************************************/
+
+/************************************************************************
+名称:IComplexHttp 组件监听器基接口
+描述:定义 IComplexHttp 组件监听器的所有事件
+************************************************************************/
+class IComplexHttpListener
+{
+public:
+
+	/*
+	* 名称:开始解析通知
+	* 描述:开始解析 HTTP 报文时,向监听器发送该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnMessageBegin(CONNID dwConnID)										= 0;
+
+	/*
+	* 名称:请求行解析完成通知(仅用于 HTTP 服务端)
+	* 描述:请求行解析完成后,向监听器发送该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			lpszMethod	-- 请求方法名
+	*			lpszUrl		-- 请求行中的 URL 域
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnRequestLine(CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl)		= 0;
+
+	/*
+	* 名称:状态行解析完成通知(仅用于 HTTP 客户端)
+	* 描述:状态行解析完成后,向监听器发送该通知
+	*		
+	* 参数:		dwConnID		-- 连接 ID
+	*			usStatusCode	-- HTTP 状态码
+	*			lpszDesc		-- 状态描述
+	* 返回值:	HPR_OK			-- 继续执行
+	*			HPR_ERROR		-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnStatusLine(CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc)	= 0;
+
+	/*
+	* 名称:请求头通知
+	* 描述:每当解析完成一个请求头后,向监听器发送该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			lpszName	-- 请求头名称
+	*			lpszValue	-- 请求头值
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnHeader(CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)			= 0;
+
+	/*
+	* 名称:请求头完成通知
+	* 描述:解析完成所有请求头后,向监听器发送该通知
+	*		
+	* 参数:		dwConnID		-- 连接 ID
+	* 返回值:	HPR_OK			-- 继续执行
+	*			HPR_SKIP_BODY	-- 跳过当前请求的 HTTP BODY
+	*			HPR_UPGRADE		-- 升级协议
+	*			HPR_ERROR		-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnHeadersComplete(CONNID dwConnID)									= 0;
+
+	/*
+	* 名称:BODY 报文通知
+	* 描述:每当接收到 HTTP BODY 报文,向监听器发送该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			pData		-- 数据缓冲区
+	*			iLength		-- 数据长度
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnBody(CONNID dwConnID, const BYTE* pData, int iLength)				= 0;
+
+	/*
+	* 名称:Chunked 报文头通知
+	* 描述:每当解析出一个 Chunked 报文头,向监听器发送该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	*			iLength		-- Chunked 报文体数据长度
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnChunkHeader(CONNID dwConnID, int iLength)							= 0;
+
+	/*
+	* 名称:Chunked 报文结束通知
+	* 描述:每当解析完一个 Chunked 报文,向监听器发送该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnChunkComplete(CONNID dwConnID)										= 0;
+
+	/*
+	* 名称:完成解析通知
+	* 描述:每当解析完成一个完整 HTTP 报文,向监听器发送该通知
+	*		
+	* 参数:		dwConnID	-- 连接 ID
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnMessageComplete(CONNID dwConnID)									= 0;
+
+	/*
+	* 名称:升级协议通知
+	* 描述:当需要升级协议时,向监听器发送该通知
+	*		
+	* 参数:		dwConnID		-- 连接 ID
+	*			enUpgradeType	-- 协议类型
+	* 返回值:	HPR_OK			-- 继续执行
+	*			HPR_ERROR		-- 引发 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnUpgrade(CONNID dwConnID, EnHttpUpgradeType enUpgradeType)			= 0;
+
+	/*
+	* 名称:解析错误通知
+	* 描述:当解析 HTTP 报文错误时,向监听器发送该通知
+	*		
+	* 参数:		dwConnID		-- 连接 ID
+	*			iErrorCode		-- 错误代码
+	*			lpszErrorDesc	-- 错误描述
+	* 返回值:	HPR_OK			-- 继续执行
+	*			HPR_ERROR		-- 引发 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnParseError(CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc)	= 0;
+
+public:
+	virtual ~IComplexHttpListener() {}
+};
+
+/************************************************************************
+名称:IHttpServer 组件端监听器接口
+描述:定义 IHttpServer 监听器的所有事件
+************************************************************************/
+class IHttpServerListener : public IComplexHttpListener, public ITcpServerListener
+{
+public:
+
+};
+
+/************************************************************************
+名称:IHttpAgent 组件端监听器接口
+描述:定义 IHttpAgent 监听器的所有事件
+************************************************************************/
+class IHttpAgentListener : public IComplexHttpListener, public ITcpAgentListener
+{
+public:
+
+};
+
+/************************************************************************
+名称:IHttpServerListener 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CHttpServerListener : public IHttpServerListener
+{
+public:
+	virtual EnHandleResult OnPrepareListen(SOCKET soListen)											{return HR_IGNORE;}
+	virtual EnHandleResult OnAccept(CONNID dwConnID, SOCKET soClient)								{return HR_IGNORE;}
+	virtual EnHandleResult OnHandShake(CONNID dwConnID)												{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(CONNID dwConnID, int iLength)									{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(CONNID dwConnID, const BYTE* pData, int iLength)				{return HR_IGNORE;}
+	virtual EnHandleResult OnSend(CONNID dwConnID, const BYTE* pData, int iLength)					{return HR_IGNORE;}
+	virtual EnHandleResult OnShutdown()																{return HR_IGNORE;}
+
+	virtual EnHttpParseResult OnMessageBegin(CONNID dwConnID)										{return HPR_OK;}
+	virtual EnHttpParseResult OnRequestLine(CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl)		{return HPR_OK;}
+	virtual EnHttpParseResult OnStatusLine(CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc)	{return HPR_OK;}
+	virtual EnHttpParseResult OnHeader(CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)			{return HPR_OK;}
+	virtual EnHttpParseResult OnChunkHeader(CONNID dwConnID, int iLength)							{return HPR_OK;}
+	virtual EnHttpParseResult OnChunkComplete(CONNID dwConnID)										{return HPR_OK;}
+	virtual EnHttpParseResult OnUpgrade(CONNID dwConnID, EnHttpUpgradeType enUpgradeType)			{return HPR_OK;}
+};
+
+/************************************************************************
+名称:IHttpAgentListener 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+class CHttpAgentListener : public IHttpAgentListener
+{
+public:
+	virtual EnHandleResult OnPrepareConnect(CONNID dwConnID, SOCKET socket)							{return HR_IGNORE;}
+	virtual EnHandleResult OnConnect(CONNID dwConnID)												{return HR_IGNORE;}
+	virtual EnHandleResult OnHandShake(CONNID dwConnID)												{return HR_IGNORE;}
+	virtual EnHandleResult OnShutdown()																{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(CONNID dwConnID, int iLength)									{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(CONNID dwConnID, const BYTE* pData, int iLength)				{return HR_IGNORE;}
+	virtual EnHandleResult OnSend(CONNID dwConnID, const BYTE* pData, int iLength)					{return HR_IGNORE;}
+
+	virtual EnHttpParseResult OnMessageBegin(CONNID dwConnID)										{return HPR_OK;}
+	virtual EnHttpParseResult OnRequestLine(CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl)		{return HPR_OK;}
+	virtual EnHttpParseResult OnStatusLine(CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc)	{return HPR_OK;}
+	virtual EnHttpParseResult OnHeader(CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)			{return HPR_OK;}
+	virtual EnHttpParseResult OnChunkHeader(CONNID dwConnID, int iLength)							{return HPR_OK;}
+	virtual EnHttpParseResult OnChunkComplete(CONNID dwConnID)										{return HPR_OK;}
+	virtual EnHttpParseResult OnUpgrade(CONNID dwConnID, EnHttpUpgradeType enUpgradeType)			{return HPR_OK;}
+};
+
+/************************************************************************
+名称:IHttp 组件监听器基接口
+描述:定义 IHttp 组件监听器的所有事件
+************************************************************************/
+
+class IHttp;
+
+class IHttpListener
+{
+public:
+
+	/*
+	* 名称:开始解析通知
+	* 描述:开始解析 HTTP 报文时,向监听器发送该通知
+	*		
+	* 参数:		pHttp		-- 组件对象指针
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnMessageBegin(IHttp* pHttp)										= 0;
+
+	/*
+	* 名称:请求行解析完成通知(仅用于 HTTP 服务端)
+	* 描述:请求行解析完成后,向监听器发送该通知
+	*		
+	* 参数:		pHttp		-- 组件对象指针
+	*			lpszMethod	-- 请求方法名
+	*			lpszUrl		-- 请求行中的 URL 域
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnRequestLine(IHttp* pHttp, LPCSTR lpszMethod, LPCSTR lpszUrl)	= 0;
+
+	/*
+	* 名称:状态行解析完成通知(仅用于 HTTP 客户端)
+	* 描述:状态行解析完成后,向监听器发送该通知
+	*		
+	* 参数:		pHttp			-- 组件对象指针
+	*			usStatusCode	-- HTTP 状态码
+	*			lpszDesc		-- 状态描述
+	* 返回值:	HPR_OK			-- 继续执行
+	*			HPR_ERROR		-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnStatusLine(IHttp* pHttp, USHORT usStatusCode, LPCSTR lpszDesc)	= 0;
+
+	/*
+	* 名称:请求头通知
+	* 描述:每当解析完成一个请求头后,向监听器发送该通知
+	*		
+	* 参数:		pHttp		-- 组件对象指针
+	*			lpszName	-- 请求头名称
+	*			lpszValue	-- 请求头值
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnHeader(IHttp* pHttp, LPCSTR lpszName, LPCSTR lpszValue)			= 0;
+
+	/*
+	* 名称:请求头完成通知
+	* 描述:解析完成所有请求头后,向监听器发送该通知
+	*		
+	* 参数:		pHttp			-- 组件对象指针
+	* 返回值:	HPR_OK			-- 继续执行
+	*			HPR_SKIP_BODY	-- 跳过当前请求的 HTTP BODY
+	*			HPR_UPGRADE		-- 升级协议
+	*			HPR_ERROR		-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnHeadersComplete(IHttp* pHttp)									= 0;
+
+	/*
+	* 名称:BODY 报文通知
+	* 描述:每当接收到 HTTP BODY 报文,向监听器发送该通知
+	*		
+	* 参数:		pHttp		-- 组件对象指针
+	*			pData		-- 数据缓冲区
+	*			iLength		-- 数据长度
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnBody(IHttp* pHttp, const BYTE* pData, int iLength)				= 0;
+
+	/*
+	* 名称:Chunked 报文头通知
+	* 描述:每当解析出一个 Chunked 报文头,向监听器发送该通知
+	*		
+	* 参数:		pHttp		-- 组件对象指针
+	*			iLength		-- Chunked 报文体数据长度
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnChunkHeader(IHttp* pHttp, int iLength)							= 0;
+
+	/*
+	* 名称:Chunked 报文结束通知
+	* 描述:每当解析完一个 Chunked 报文,向监听器发送该通知
+	*		
+	* 参数:		pHttp		-- 组件对象指针
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnChunkComplete(IHttp* pHttp)										= 0;
+
+	/*
+	* 名称:完成解析通知
+	* 描述:每当解析完成一个完整 HTTP 报文,向监听器发送该通知
+	*		
+	* 参数:		pHttp		-- 组件对象指针
+	* 返回值:	HPR_OK		-- 继续执行
+	*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnMessageComplete(IHttp* pHttp)									= 0;
+
+	/*
+	* 名称:升级协议通知
+	* 描述:当需要升级协议时,向监听器发送该通知
+	*		
+	* 参数:		pHttp			-- 组件对象指针
+	*			enUpgradeType	-- 协议类型
+	* 返回值:	HPR_OK			-- 继续执行
+	*			HPR_ERROR		-- 引发 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnUpgrade(IHttp* pHttp, EnHttpUpgradeType enUpgradeType)			= 0;
+
+	/*
+	* 名称:解析错误通知
+	* 描述:当解析 HTTP 报文错误时,向监听器发送该通知
+	*		
+	* 参数:		pHttp			-- 组件对象指针
+	*			iErrorCode		-- 错误代码
+	*			lpszErrorDesc	-- 错误描述
+	* 返回值:	HPR_OK			-- 继续执行
+	*			HPR_ERROR		-- 引发 OnClose() 事件并关闭连接
+	*/
+	virtual EnHttpParseResult OnParseError(IHttp* pHttp, int iErrorCode, LPCSTR lpszErrorDesc)	= 0;
+
+public:
+	virtual ~IHttpListener() {}
+};
+
+/************************************************************************
+名称:IHttpClient 组件端监听器接口
+描述:定义 IHttpClient 监听器的所有事件
+************************************************************************/
+class IHttpClientListener : public IHttpListener, public ITcpClientListener
+{
+public:
+
+};
+
+/************************************************************************
+名称:IHttpClientListener 监听器抽象基类
+描述:定义某些事件的默认处理方法(忽略事件)
+************************************************************************/
+
+class CHttpClientListener : public IHttpClientListener
+{
+public:
+	virtual EnHandleResult OnPrepareConnect(IClient* pClient, SOCKET socket)					{return HR_IGNORE;}
+	virtual EnHandleResult OnConnect(IClient* pClient)											{return HR_IGNORE;}
+	virtual EnHandleResult OnHandShake(IClient* pClient)										{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(IClient* pClient, int iLength)								{return HR_IGNORE;}
+	virtual EnHandleResult OnReceive(IClient* pClient, const BYTE* pData, int iLength)			{return HR_IGNORE;}
+	virtual EnHandleResult OnSend(IClient* pClient, const BYTE* pData, int iLength)				{return HR_IGNORE;}
+
+	virtual EnHttpParseResult OnMessageBegin(IHttp* pClient)									{return HPR_OK;}
+	virtual EnHttpParseResult OnRequestLine(IHttp* pHttp, LPCSTR lpszMethod, LPCSTR lpszUrl)	{return HPR_OK;}
+	virtual EnHttpParseResult OnStatusLine(IHttp* pHttp, USHORT usStatusCode, LPCSTR lpszDesc)	{return HPR_OK;}
+	virtual EnHttpParseResult OnHeader(IHttp* pClient, LPCSTR lpszName, LPCSTR lpszValue)		{return HPR_OK;}
+	virtual EnHttpParseResult OnChunkHeader(IHttp* pClient, int iLength)						{return HPR_OK;}
+	virtual EnHttpParseResult OnChunkComplete(IHttp* pClient)									{return HPR_OK;}
+	virtual EnHttpParseResult OnUpgrade(IHttp* pClient, EnHttpUpgradeType enUpgradeType)		{return HPR_OK;}
+};
+
+/************************************************************************
+名称:复合 Http 组件接口
+描述:定义复合 Http 组件的所有操作方法和属性访问方法,复合 Http 组件同时管理多个 Http 连接
+************************************************************************/
+class IComplexHttp
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置本地协议版本 */
+	virtual void SetLocalVersion(EnHttpVersion usVersion)								= 0;
+	/* 获取本地协议版本 */
+	virtual EnHttpVersion GetLocalVersion()												= 0;
+
+	/* 检查是否升级协议 */
+	virtual BOOL IsUpgrade(CONNID dwConnID)												= 0;
+	/* 检查是否有 Keep-Alive 标识 */
+	virtual BOOL IsKeepAlive(CONNID dwConnID)											= 0;
+	/* 获取协议版本 */
+	virtual USHORT GetVersion(CONNID dwConnID)											= 0;
+	/* 获取内容长度 */
+	virtual ULONGLONG GetContentLength(CONNID dwConnID)									= 0;
+	/* 获取内容类型 */
+	virtual LPCSTR GetContentType(CONNID dwConnID)										= 0;
+	/* 获取协议升级类型 */
+	virtual EnHttpUpgradeType GetUpgradeType(CONNID dwConnID)							= 0;
+	/* 获取解析错误代码 */
+	virtual USHORT GetParseErrorCode(CONNID dwConnID, LPCSTR* lpszErrorDesc = nullptr)	= 0;
+
+	/* 获取某个请求头(单值) */
+	virtual BOOL GetHeader(CONNID dwConnID, LPCSTR lpszName, LPCSTR* lpszValue)						= 0;
+	/* 获取某个请求头(多值) */
+	virtual BOOL GetHeaders(CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue[], DWORD& dwCount)	= 0;
+	/* 获取所有请求头 */
+	virtual BOOL GetAllHeaders(CONNID dwConnID, THeader lpHeaders[], DWORD& dwCount)				= 0;
+	/* 获取所有请求头名称 */
+	virtual BOOL GetAllHeaderNames(CONNID dwConnID, LPCSTR lpszName[], DWORD& dwCount)				= 0;
+
+	/* 获取 Cookie */
+	virtual BOOL GetCookie(CONNID dwConnID, LPCSTR lpszName, LPCSTR* lpszValue)						= 0;
+	/* 获取所有 Cookie */
+	virtual BOOL GetAllCookies(CONNID dwConnID, TCookie lpCookies[], DWORD& dwCount)				= 0;
+
+	/*
+	// !! maybe implemented in future !! //
+
+	virtual BOOL GetParam(CONNID dwConnID, LPCSTR lpszName, LPCSTR* lpszValue)						= 0;
+	virtual BOOL GetParams(CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue[], DWORD& dwCount)	= 0;
+	virtual BOOL GetAllParams(CONNID dwConnID, LPPARAM lpszParam[], DWORD& dwCount)					= 0;
+	virtual BOOL GetAllParamNames(CONNID dwConnID, LPCSTR lpszName[], DWORD& dwCount)				= 0;
+	*/
+
+public:
+	virtual ~IComplexHttp() {}
+};
+
+/************************************************************************
+名称:复合 Http 请求者组件接口
+描述:定义复合 Http 请求者组件的所有操作方法和属性访问方法
+************************************************************************/
+class IComplexHttpRequester : public IComplexHttp
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+	/*
+	* 名称:发送请求
+	* 描述:向服务端发送 HTTP 请求
+	*		
+	* 参数:		dwConnID		-- 连接 ID
+	*			lpszMethod		-- 请求方法
+	*			lpszPath		-- 请求路径
+	*			lpHeaders		-- 请求头
+	*			iHeaderCount	-- 请求头数量
+	*			pBody			-- 请求体
+	*			iLength			-- 请求体长度
+	* 返回值:	TRUE			-- 成功
+	*			FALSE			-- 失败
+	*/
+	virtual BOOL SendRequest(CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0, const BYTE* pBody = nullptr, int iLength = 0)	= 0;
+
+	/* 发送 POST 请求 */
+	virtual BOOL SendPost(CONNID dwConnID, LPCSTR lpszPath, const THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength)													= 0;
+	/* 发送 PUT 请求 */
+	virtual BOOL SendPut(CONNID dwConnID, LPCSTR lpszPath, const THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength)														= 0;
+	/* 发送 PATCH 请求 */
+	virtual BOOL SendPatch(CONNID dwConnID, LPCSTR lpszPath, const THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength)													= 0;
+	/* 发送 GET 请求 */
+	virtual BOOL SendGet(CONNID dwConnID, LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																		= 0;
+	/* 发送 DELETE 请求 */
+	virtual BOOL SendDelete(CONNID dwConnID, LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																	= 0;
+	/* 发送 HEAD 请求 */
+	virtual BOOL SendHead(CONNID dwConnID, LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																		= 0;
+	/* 发送 TRACE 请求 */
+	virtual BOOL SendTrace(CONNID dwConnID, LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																		= 0;
+	/* 发送 OPTIONS 请求 */
+	virtual BOOL SendOptions(CONNID dwConnID, LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																	= 0;
+	/* 发送 CONNECT 请求 */
+	virtual BOOL SendConnect(CONNID dwConnID, LPCSTR lpszHost, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																	= 0;
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 获取 HTTP 状态码 */
+	virtual USHORT GetStatusCode(CONNID dwConnID)														= 0;
+
+	/* 添加 Cookie */
+	virtual BOOL AddCookie(CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue, BOOL bRelpace = TRUE)	= 0;
+	/* 删除 Cookie */
+	virtual BOOL DeleteCookie(CONNID dwConnID, LPCSTR lpszName)											= 0;
+	/* 删除所有 Cookie */
+	virtual BOOL DeleteAllCookies(CONNID dwConnID)														= 0;
+
+
+};
+
+/************************************************************************
+名称:复合 Http 响应者组件接口
+描述:定义复合 Http 响应者组件的所有操作方法和属性访问方法
+************************************************************************/
+class IComplexHttpResponder : public IComplexHttp
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+	/*
+	* 名称:回复请求
+	* 描述:向客户端回复 HTTP 请求
+	*		
+	* 参数:		dwConnID		-- 连接 ID
+	*			usStatusCode	-- HTTP 状态码
+	*			lpszDesc		-- HTTP 状态描述
+	*			lpHeaders		-- 回复请求头
+	*			iHeaderCount	-- 回复请求头数量
+	*			pData			-- 回复请求体
+	*			iLength			-- 回复请求体长度
+	* 返回值:	TRUE			-- 成功
+	*			FALSE			-- 失败
+	*/
+	virtual BOOL SendResponse(CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc = nullptr, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0, const BYTE* pData = nullptr, int iLength = 0)	= 0;
+
+	/*
+	* 名称:释放连接
+	* 描述:把连接放入释放队列,等待某个时间(通过 SetReleaseDelay() 设置)关闭连接
+	*		
+	* 参数:		dwConnID		-- 连接 ID
+	* 返回值:	TRUE			-- 成功
+	*			FALSE			-- 失败
+	*/
+	virtual BOOL Release(CONNID dwConnID)								= 0;
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置连接释放延时(默认:3000 毫秒) */
+	virtual void SetReleaseDelay(DWORD dwReleaseDelay)					= 0;
+	/* 获取连接释放延时 */
+	virtual DWORD GetReleaseDelay()										= 0;
+
+	/* 获取请求行 URL 域掩码(URL 域参考:EnHttpUrlField) */
+	virtual USHORT GetUrlFieldSet(CONNID dwConnID)						= 0;
+	/* 获取某个 URL 域值 */
+	virtual LPCSTR GetUrlField(CONNID dwConnID, EnHttpUrlField enField)	= 0;
+	/* 获取请求方法 */
+	virtual LPCSTR GetMethod(CONNID dwConnID)							= 0;
+
+};
+
+/************************************************************************
+名称:简单 HTTP 组件接口
+描述:定义 简单 HTTP 组件的所有操作方法和属性访问方法
+************************************************************************/
+class IHttp
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+	/* 设置本地协议版本 */
+	virtual void SetLocalVersion(EnHttpVersion usVersion)				= 0;
+	/* 获取本地协议版本 */
+	virtual EnHttpVersion GetLocalVersion()								= 0;
+
+	/* 检查是否升级协议 */
+	virtual BOOL IsUpgrade()											= 0;
+	/* 检查是否有 Keep-Alive 标识 */
+	virtual BOOL IsKeepAlive()											= 0;
+	/* 获取协议版本 */
+	virtual USHORT GetVersion()											= 0;
+	/* 获取内容长度 */
+	virtual ULONGLONG GetContentLength()								= 0;
+	/* 获取内容类型 */
+	virtual LPCSTR GetContentType()										= 0;
+	/* 获取协议升级类型 */
+	virtual EnHttpUpgradeType GetUpgradeType()							= 0;
+	/* 获取解析错误代码 */
+	virtual USHORT GetParseErrorCode(LPCSTR* lpszErrorDesc = nullptr)	= 0;
+
+	/* 获取 HTTP 状态码 */
+	virtual USHORT GetStatusCode()										= 0;
+
+	/* 获取某个请求头(单值) */
+	virtual BOOL GetHeader(LPCSTR lpszName, LPCSTR* lpszValue)							= 0;
+	/* 获取某个请求头(多值) */
+	virtual BOOL GetHeaders(LPCSTR lpszName, LPCSTR lpszValue[], DWORD& dwCount)		= 0;
+	/* 获取所有请求头 */
+	virtual BOOL GetAllHeaders(THeader lpHeaders[], DWORD& dwCount)						= 0;
+	/* 获取所有请求头名称 */
+	virtual BOOL GetAllHeaderNames(LPCSTR lpszName[], DWORD& dwCount)					= 0;
+
+	/* 获取 Cookie */
+	virtual BOOL GetCookie(LPCSTR lpszName, LPCSTR* lpszValue)							= 0;
+	/* 获取所有 Cookie */
+	virtual BOOL GetAllCookies(TCookie lpCookies[], DWORD& dwCount)						= 0;
+	/* 添加 Cookie */
+	virtual BOOL AddCookie(LPCSTR lpszName, LPCSTR lpszValue, BOOL bRelpace = TRUE)		= 0;
+	/* 删除 Cookie */
+	virtual BOOL DeleteCookie(LPCSTR lpszName)											= 0;
+	/* 删除所有 Cookie */
+	virtual BOOL DeleteAllCookies()														= 0;
+
+	/*
+	// !! maybe implemented in future !! //
+
+	virtual BOOL GetParam(LPCSTR lpszName, LPCSTR* lpszValue)						= 0;
+	virtual BOOL GetParams(LPCSTR lpszName, LPCSTR lpszValue[], DWORD& dwCount)		= 0;
+	virtual BOOL GetAllParams(LPPARAM lpszParam[], DWORD& dwCount)					= 0;
+	virtual BOOL GetAllParamNames(LPCSTR lpszName[], DWORD& dwCount)				= 0;
+	*/
+
+public:
+	virtual ~IHttp() {}
+};
+
+/************************************************************************
+名称:简单 Http 请求者组件接口
+描述:定义简单 Http 请求者组件的所有操作方法和属性访问方法
+************************************************************************/
+class IHttpRequester : public IHttp
+{
+public:
+
+	/***********************************************************************/
+	/***************************** 组件操作方法 *****************************/
+
+	/*
+	* 名称:发送请求
+	* 描述:向服务端发送 HTTP 请求
+	*		
+	* 参数:		lpszMethod		-- 请求方法
+	*			lpszPath		-- 请求路径
+	*			lpHeaders		-- 请求头
+	*			iHeaderCount	-- 请求头数量
+	*			pBody			-- 请求体
+	*			iLength			-- 请求体长度
+	* 返回值:	TRUE			-- 成功
+	*			FALSE			-- 失败
+	*/
+	virtual BOOL SendRequest(LPCSTR lpszMethod, LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0, const BYTE* pBody = nullptr, int iLength = 0)	= 0;
+
+	/* 发送 POST 请求 */
+	virtual BOOL SendPost(LPCSTR lpszPath, const THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength)														= 0;
+	/* 发送 PUT 请求 */
+	virtual BOOL SendPut(LPCSTR lpszPath, const THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength)														= 0;
+	/* 发送 PATCH 请求 */
+	virtual BOOL SendPatch(LPCSTR lpszPath, const THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength)													= 0;
+	/* 发送 GET 请求 */
+	virtual BOOL SendGet(LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																		= 0;
+	/* 发送 DELETE 请求 */
+	virtual BOOL SendDelete(LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																		= 0;
+	/* 发送 HEAD 请求 */
+	virtual BOOL SendHead(LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																		= 0;
+	/* 发送 TRACE 请求 */
+	virtual BOOL SendTrace(LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																		= 0;
+	/* 发送 OPTIONS 请求 */
+	virtual BOOL SendOptions(LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																	= 0;
+	/* 发送 CONNECT 请求 */
+	virtual BOOL SendConnect(LPCSTR lpszHost, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)																	= 0;
+
+public:
+
+	/***********************************************************************/
+	/***************************** 属性访问方法 *****************************/
+
+};
+
+/************************************************************************
+名称:HTTP Server 组件接口
+描述:继承了 ITcpServer 和 IComplexHttpResponder
+************************************************************************/
+class IHttpServer : public IComplexHttpResponder, public ITcpServer
+{
+public:
+	/* IServer* 转换为 IComplexHttpResponder* */
+	inline static IComplexHttpResponder* ToHttpResponder(IServer* pServer)
+	{
+		return (IComplexHttpResponder*)((char*)pServer - sizeof(IComplexHttpResponder));
+	}
+
+	/* IComplexHttpResponder* 转换为 ITcpServer* */
+	inline static ITcpServer* ToServer(IComplexHttpResponder* pHttpResponder)
+	{
+		return (ITcpServer*)((char*)pHttpResponder + sizeof(IComplexHttpResponder));
+	}
+};
+
+/************************************************************************
+名称:HTTP Agent 组件接口
+描述:继承了 ITcpAgent 和 IComplexHttpRequester
+************************************************************************/
+class IHttpAgent : public IComplexHttpRequester, public ITcpAgent
+{
+public:
+	/* IAgent* 转换为 IComplexHttpRequester* */
+	inline static IComplexHttpRequester* ToHttpRequester(IAgent* pAgent)
+	{
+		return (IComplexHttpRequester*)((char*)pAgent - sizeof(IComplexHttpRequester));
+	}
+
+	/* IComplexHttpRequester* 转换为 ITcpAgent* */
+	inline static ITcpAgent* ToAgent(IComplexHttpRequester* pHttpRequester)
+	{
+		return (ITcpAgent*)((char*)pHttpRequester + sizeof(IComplexHttpRequester));
+	}
+};
+
+/************************************************************************
+名称:HTTP Client 组件接口
+描述:继承了 ITcpClient 和 IHttpRequester
+************************************************************************/
+class IHttpClient : public IHttpRequester, public ITcpClient
+{
+public:
+	/* IClient* 转换为 IHttpRequester* */
+	inline static IHttpRequester* ToHttpRequester(IClient* pClient)
+	{
+		return (IHttpRequester*)((char*)pClient - sizeof(IHttpRequester));
+	}
+
+	/* IHttpRequester* 转换为 ITcpClient* */
+	inline static ITcpClient* ToClient(IHttpRequester* pHttpRequester)
+	{
+		return (ITcpClient*)((char*)pHttpRequester + sizeof(IHttpRequester));
+	}
+};

+ 819 - 0
source/hook/hp-src/Win32Helper.h

@@ -0,0 +1,819 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#pragma once
+
+#include "GeneralHelper.h"
+
+// RECT 帮助宏
+#define RC_WIDTH(rc)		(rc.right - rc.left)
+#define RC_HEIGHT(rc)		(rc.bottom - rc.top)
+#define RC_CENTER_X(rc)		((rc.right + rc.left) / 2)
+#define RC_CENTER_Y(rc)		((rc.bottom + rc.top) / 2)
+
+/************************************************************************/
+/*                 			  消息映射帮助宏			 					*/
+/************************************************************************/
+
+/* see: WindowsX.h */
+#define HANDLE_SYS_MSG(hwnd, message, fn)	HANDLE_MSG(hwnd, message, fn)
+
+/* LRESULT Cls_OnMessage(HWND hwnd, WPARAM wParam, LPARAM lParam) */
+#define HANDLE_USER_MSG(hwnd, message, fn)								\
+	case (message): return (LRESULT)(fn)((hwnd), (wParam), (lParam))
+
+#define FORWARD_USER_MSG(hwnd, message, wParam, lParam, fn)				\
+	(LRESULT)(fn)((hwnd), (message), (wParam), (lParam))
+
+#define GET_WND_PROC_INTERNAL(theClass, flag)	((WNDPROC)theClass##flag##WndProc)
+#define GET_DLG_PROC_INTERNAL(theClass, flag)	((DLGPROC)theClass##flag##DlgProc)
+
+#define DECLARE_MSG_MAP_INTERNAL(theClass, flag)		\
+	static LRESULT CALLBACK theClass##flag##WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+#define DECLARE_DLG_MSG_MAP_INTERNAL(theClass, flag)	\
+	static BOOL CALLBACK theClass##flag##DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+#define BEGIN_MSG_MAP_INTERNAL(theClass, flag)			\
+	LRESULT theClass##flag##WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)	\
+	{																					\
+		LRESULT result = 0;																\
+																						\
+		switch(msg)																		\
+		{
+
+#define BEGIN_DLG_MSG_MAP_INTERNAL(theClass, flag)		\
+	BOOL theClass##flag##DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)		\
+	{																					\
+		BOOL	retVal = TRUE;															\
+		LRESULT result = 0;																\
+																						\
+		switch(msg)																		\
+		{
+
+// 窗口过程为类中的静态成员函数
+#define GET_WND_PROC(theClass)			GET_WND_PROC_INTERNAL(theClass, ::)
+#define GET_DLG_PROC(theClass)			GET_DLG_PROC_INTERNAL(theClass, ::)
+
+#define DECLARE_MSG_MAP(theClass)					\
+public:												\
+	DECLARE_MSG_MAP_INTERNAL(theClass, ::)
+
+#define DECLARE_DLG_MSG_MAP(theClass)				\
+public:												\
+	DECLARE_DLG_MSG_MAP_INTERNAL(theClass, ::)
+
+#define BEGIN_MSG_MAP(theClass)			BEGIN_MSG_MAP_INTERNAL(theClass, ::)
+#define BEGIN_DLG_MSG_MAP(theClass)		BEGIN_DLG_MSG_MAP_INTERNAL(theClass, ::)
+
+/* 消息处理函数的声明请参考: <WindowsX.h> 的 HANDLE_MSG */
+#define ADD_MSG_MAP(msg, fn)						\
+		case (msg): result = HANDLE_##msg((hWnd), (wParam), (lParam), (fn));	break;
+
+/* LRESULT Cls_OnMessage(HWND hwnd, WPARAM wParam, LPARAM lParam) */
+#define ADD_USER_MSG_MAP(msg, fn)					\
+		case (msg): result = (LRESULT)(fn)((hWnd), (wParam), (lParam));			break;
+
+#define END_MSG_MAP()								\
+		default:									\
+			result = ::DefWindowProc(hWnd, msg, wParam, lParam);						\
+		}																				\
+																						\
+		return result;																	\
+	}
+
+#define END_DLG_MSG_MAP()							\
+		default:									\
+			retVal = FALSE;																\
+		}																				\
+																						\
+		if(retVal)																		\
+			SetDlgMsgResult(hWnd, msg, result);											\
+																						\
+		return retVal;																	\
+	}
+
+// 窗口过程为全局函数
+#define GET_GLOBAL_WND_PROC(theClass)			GET_WND_PROC_INTERNAL(theClass,			_)
+#define DECLARE_GLOBAL_MSG_MAP(theClass)		DECLARE_MSG_MAP_INTERNAL(theClass,		_)
+#define BEGIN_GLOBAL_MSG_MAP(theClass)			BEGIN_MSG_MAP_INTERNAL(theClass,		_)
+#define END_GLOBAL_MSG_MAP()					END_MSG_MAP()
+
+#define GET_GLOBAL_DLG_PROC(theClass)			GET_DLG_PROC_INTERNAL(theClass,			_)
+#define DECLARE_GLOBAL_DLG_MSG_MAP(theClass)	DECLARE_DLG_MSG_MAP_INTERNAL(theClass,	_)
+#define BEGIN_GLOBAL_DLG_MSG_MAP(theClass)		BEGIN_DLG_MSG_MAP_INTERNAL(theClass,	_)
+#define END_GLOBAL_DLG_MSG_MAP()				END_DLG_MSG_MAP()
+
+// 绑定对象指针到窗口
+#define ATTACH_OBJ_PTR_TO_WINDOW(hwnd, objPtr)	::SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)objPtr)
+#define GET_OBJ_PTR_FROM_WINDOW(hwnd, theClass)	(theClass*)(LONG_PTR)::GetWindowLongPtr(hwnd, GWL_USERDATA)
+
+#define DEFINE_OBJ_PTR_FROM_WINDOW(hwnd, theClass, pObj)		\
+	theClass* pObj = GET_OBJ_PTR_FROM_WINDOW(hwnd, theClass);	\
+	ASSERT(pObj);
+
+
+/************************************************************************/
+/*                 		  应用程序唯一实例			 	            */
+/************************************************************************/
+
+class COnlyOneApp
+{
+public:
+	BOOL IsFirstApp	() {return m_bIsFirstApp;}
+	DWORD GetProcID	() {return m_dwProcID;}
+
+	COnlyOneApp(LPCTSTR pszAppFlag)
+	: m_dwProcID(0), m_bIsFirstApp(FALSE)
+	{
+		m_hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, sizeof(DWORD), pszAppFlag);
+
+		if(m_hMap)
+		{
+			if(::GetLastError() != ERROR_ALREADY_EXISTS)
+			{
+				m_bIsFirstApp	= TRUE;
+				m_dwProcID		= ::GetCurrentProcessId();
+
+				LPVOID lpBuff	= ::MapViewOfFile(m_hMap, FILE_MAP_WRITE, 0, 0, sizeof(DWORD));
+				ASSERT(lpBuff);
+
+				memcpy(lpBuff, &m_dwProcID, sizeof(DWORD));
+				::UnmapViewOfFile(lpBuff);
+			}
+			else
+			{
+				m_bIsFirstApp	= FALSE;
+				LPVOID lpBuff	= ::MapViewOfFile(m_hMap, FILE_MAP_READ, 0, 0, sizeof(DWORD));
+				ASSERT(lpBuff);
+
+				memcpy(&m_dwProcID, lpBuff, sizeof(DWORD));
+				::UnmapViewOfFile(lpBuff);
+			}
+		}
+		else
+		{
+			ASSERT(FALSE);
+		}
+	}
+
+	~COnlyOneApp() {if(m_hMap) {::CloseHandle(m_hMap); m_hMap = nullptr;}}
+
+private:
+	HANDLE	m_hMap;
+	DWORD	m_dwProcID;
+	BOOL	m_bIsFirstApp;
+
+	DECLARE_NO_COPY_CLASS(COnlyOneApp)
+};
+
+class COnlyOneWndApp
+{
+public:
+	BOOL IsFirstApp()			{return m_hwndPre == nullptr;}
+	HWND GetPreInstanceWindow()	{return m_hwndPre;}
+
+	COnlyOneWndApp(LPCTSTR lpszClassName, LPCTSTR lpszWindowName = nullptr)
+	{
+		m_hwndPre = ::FindWindow(lpszClassName, lpszWindowName);
+	}
+
+private:
+	HWND m_hwndPre;
+
+	DECLARE_NO_COPY_CLASS(COnlyOneWndApp)
+};
+
+/************************************************************************/
+/*                   	句柄 (HANDLE) 智能包装器 		 		        */
+/************************************************************************/
+
+template<HANDLE NULL_VALUE>
+class auto_handle
+{
+public:
+	auto_handle(HANDLE h = NULL_VALUE)			{set(h);}
+	auto_handle(auto_handle<NULL_VALUE>& other)	{set(other.release());}
+
+	~auto_handle()	{reset();}
+
+	auto_handle<NULL_VALUE>& reset(HANDLE h = NULL_VALUE)
+	{
+		if(h != m_h)
+		{
+			if(is_valid())
+				VERIFY(::CloseHandle(m_h));
+
+			set(h);
+		}
+
+		return *this;
+	}
+
+	auto_handle<NULL_VALUE>& reset(auto_handle<NULL_VALUE>& other)
+	{
+		if(this != &other)
+			reset(other.release());
+
+		return *this;
+	}
+
+	HANDLE release()
+	{
+		HANDLE h = get();
+		set(NULL_VALUE);
+	
+		return h;
+	}
+
+	operator HANDLE	()	const	{return m_h;}
+	HANDLE get		()	const	{return m_h;}
+	HANDLE& get_ref	()	const	{return m_h;}
+	bool is_valid	()	const	{return m_h != NULL_VALUE;}
+
+	auto_handle<NULL_VALUE>& operator = (HANDLE h)							{return reset(h);}
+	auto_handle<NULL_VALUE>& operator = (auto_handle<NULL_VALUE>& other)	{return reset(other);}
+
+	bool operator == (HANDLE h)								const	{return m_h == h;}
+	bool operator != (HANDLE h)								const	{return !(operator == (h));	}
+	bool operator == (const auto_handle<NULL_VALUE>& other)	const	{return m_h == other.m_h;}
+	bool operator != (const auto_handle<NULL_VALUE>& other)	const	{return !(operator == (other));}
+
+private:
+	void set(HANDLE h)	{m_h = h;}
+
+	// ~! do not define these conversion, because it's very easy to making mistake !~
+	template<HANDLE _Other> auto_handle(const auto_handle<_Other>&);
+	template<HANDLE _Other> auto_handle<NULL_VALUE>& operator = (const auto_handle<_Other>&);
+
+private:
+	HANDLE	m_h;
+};
+
+typedef auto_handle<INVALID_HANDLE_VALUE>	auto_file_handle;	// 文件智能句柄
+typedef auto_handle<nullptr>				auto_res_handle;	// 普通资源智能句柄
+
+/************************************************************************/
+/*                 	  	 	DC 智能包装器 					            */
+/************************************************************************/
+
+class auto_dc
+{
+public:
+	auto_dc(HDC h = nullptr, HWND w = nullptr, bool is_create = false)
+	{
+		set(h, w, is_create);
+	}
+
+	auto_dc(auto_dc& other)
+	{
+		set(other.m_h, other.m_w, other.m_is_create);
+		other.release();
+	}
+
+	~auto_dc()	{reset();}
+
+	HDC GetDC(HWND hWnd)
+	{
+		HDC h = ::GetDC(hWnd);
+		reset(h, hWnd, false);
+
+		return h;
+	}
+
+	HDC GetWindowDC(HWND hWnd)
+	{
+		HDC h = ::GetWindowDC(hWnd);
+		reset(h, hWnd, false);
+
+		return h;
+	}
+
+	HDC GetDCEx(HWND hWnd, HRGN hrgnClip, DWORD flags)
+	{
+		HDC h = ::GetDCEx(hWnd, hrgnClip, flags);
+		reset(h, hWnd, false);
+
+		return h;
+	}
+
+	HDC CreateDC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, CONST DEVMODE* lpInitData)
+	{
+		HDC h = ::CreateDC(lpszDriver, lpszDevice, lpszOutput, lpInitData);
+		reset(h, nullptr, true);
+
+		return h;
+	}
+
+	HDC CreateCompatibleDC(HDC hSrc)
+	{
+		HDC h = ::CreateCompatibleDC(hSrc);
+		reset(h, nullptr, true);
+
+		return h;
+	}
+
+	HGDIOBJ GetCurrentObject(UINT uObjectType)
+	{
+		return ::GetCurrentObject(m_h, uObjectType);
+	}
+
+	HBITMAP _GetCurrentBitmap()
+	{
+		return (HBITMAP)GetCurrentObject(OBJ_BITMAP);
+	}
+
+	HBRUSH _GetCurrentBrush()
+	{
+		return (HBRUSH)GetCurrentObject(OBJ_BRUSH);
+	}
+
+	HPALETTE _GetCurrentPalette()
+	{
+		return (HPALETTE)GetCurrentObject(OBJ_PAL);
+	}
+
+	HPEN _GetCurrentPen()
+	{
+		return (HPEN)GetCurrentObject(OBJ_PEN);
+	}
+
+	HFONT _GetCurrentFont()
+	{
+		return (HFONT)GetCurrentObject(OBJ_FONT);
+	}
+
+	int SelectClipRgn(HRGN hrgn)
+	{
+		return ::SelectClipRgn(m_h, hrgn);
+	}
+
+	int ExtSelectClipRgn(HRGN hrgn, int mode)
+	{
+		return ::ExtSelectClipRgn(m_h, hrgn, mode);
+	}
+
+	HGDIOBJ SelectObject(HGDIOBJ hgdiobj)
+	{
+		return ::SelectObject(m_h, hgdiobj);
+	}
+
+	HPALETTE SelectPalette(HPALETTE hpal, BOOL bForceBackground)
+	{
+		return ::SelectPalette(m_h, hpal, bForceBackground);
+	}
+
+	HBITMAP _SelectBitmap(HBITMAP hbm)
+	{
+		return (HBITMAP)SelectObject(hbm);
+	}
+
+	HBRUSH _SelectBrush(HBRUSH hbr)
+	{
+		return (HBRUSH)SelectObject(hbr);
+	}
+
+	HPEN _SelectPen(HPEN hpen)
+	{
+		return (HPEN)SelectObject(hpen);
+	}
+
+	HRGN _SelectRgn(HRGN hrgn)
+	{
+		return (HRGN)SelectObject(hrgn);
+	}
+
+	HFONT _SelectFont(HFONT hf)
+	{
+		return (HFONT)SelectObject(hf);
+	}
+
+	auto_dc& reset(HDC h = nullptr, HWND w = nullptr, bool is_create = false)
+	{
+		if(h != m_h || w != m_w)
+		{
+			if(is_valid())
+			{
+				if(m_is_create)
+					VERIFY(::DeleteDC(m_h));
+				else
+					VERIFY(::ReleaseDC(m_w, m_h));
+			}
+
+			set(h, w, is_create);
+		}
+
+		return *this;
+	}
+
+	auto_dc& reset(auto_dc& other)
+	{
+		if(this != &other)
+		{
+			reset(other.m_h, other.m_w, other.m_is_create);
+			other.release();
+		}
+
+		return *this;
+	}
+
+	HDC release()
+	{
+		HDC h = get_dc();
+		set(nullptr, nullptr, false);
+
+		return h;
+	}
+
+	/*
+	auto_dc& operator = (HDC h)
+	{
+		return reset(h);
+	}
+	*/
+
+	auto_dc& operator = (auto_dc& other)	{return reset(other);}
+
+	operator	HDC			()	const	{return m_h;}
+	HDC			get_dc		()	const	{return m_h;}
+	const HDC&	get_dc_ref	()	const	{return m_h;}
+	HWND		get_wnd		()	const	{return m_w;}
+	bool		is_valid	()	const	{return m_h != nullptr;}
+	bool		is_create	()	const	{return m_is_create;}
+
+private:
+	void set(HDC h, HWND w, bool is_create)
+	{
+		m_h			= h;
+		m_w			= w;
+		m_is_create	= is_create;
+	}
+
+private:
+	HDC		m_h;
+	HWND	m_w;
+	bool	m_is_create;
+};
+
+class paint_dc
+{
+public:
+	paint_dc(HWND hwnd) : m_hwnd(hwnd)
+	{
+		VERIFY(m_hdc = ::BeginPaint(m_hwnd, &m_ps));
+	}
+
+	~paint_dc()
+	{
+		VERIFY(::EndPaint(m_hwnd, &m_ps));
+	}
+
+	operator HDC ()	const	{return m_hdc;}
+	bool is_valid()	const	{return m_hdc != nullptr;}
+
+public:
+	PAINTSTRUCT	m_ps;
+	HWND		m_hwnd;
+	HDC			m_hdc;
+};
+/************************************************************************/
+/*                 	  	 	GDI Object 智能包装器 					    */
+/************************************************************************/
+
+template<class T>
+class auto_gdi_obj
+{
+public:
+	auto_gdi_obj(T obj = nullptr)				{set(obj);}
+	auto_gdi_obj(auto_gdi_obj<T>& other)	{set(other.release());}
+
+	~auto_gdi_obj()	{reset();}
+
+	auto_gdi_obj<T>& reset(T obj = nullptr)
+	{
+		if(obj != m_obj)
+		{
+			if(is_valid())
+			{
+				VERIFY(::DeleteObject(m_obj));
+			}
+
+			set(obj);
+		}
+
+		return *this;
+	}
+
+	auto_gdi_obj<T>& reset(auto_gdi_obj<T>& other)
+	{
+		if(this != &other)
+			reset(other.release());
+
+		return *this;
+	}
+
+	T release()
+	{
+		T obj = get();
+		set(nullptr);
+
+		return obj;
+	}
+
+	auto_gdi_obj<T>& operator = (T obj)						{return reset(obj);}
+	auto_gdi_obj<T>& operator = (auto_gdi_obj<T>& other)	{return reset(other);}
+
+	operator	T		()	const	{return m_obj;}
+	T			get		()	const	{return m_obj;}
+	const T&	get_ref	()	const	{return m_obj;}
+	bool		is_valid()	const	{return m_obj != nullptr;}
+
+private:
+	void set(T obj)	{m_obj = obj;}
+
+protected:
+	T m_obj;
+};
+
+typedef auto_gdi_obj<HBITMAP>		auto_bitmap_base;
+typedef auto_gdi_obj<HBRUSH>		auto_brush_base;
+typedef auto_gdi_obj<HPALETTE>		auto_palette_base;
+typedef auto_gdi_obj<HPEN>			auto_pen_base;
+typedef auto_gdi_obj<HRGN>			auto_rgn_base;
+typedef auto_gdi_obj<HFONT>			auto_font_base;
+
+class auto_bitmap : public auto_bitmap_base
+{
+public:
+	auto_bitmap(HBITMAP obj = nullptr) : auto_bitmap_base(obj) {}
+
+	auto_bitmap& operator = (HBITMAP obj)
+	{
+		return (auto_bitmap&)reset(obj);
+	}
+
+	HBITMAP CreateBitmap(int nWidth, int nHeight, UINT cPlanes, UINT cBitsPerPel, CONST VOID* lpvBits)
+	{
+		HBITMAP obj = ::CreateBitmap(nWidth, nHeight, cPlanes, cBitsPerPel, lpvBits);
+		reset(obj);
+
+		return obj;
+	}
+
+	HBITMAP CreateBitmapIndirect(CONST BITMAP *lpbm)
+	{
+		HBITMAP obj = ::CreateBitmapIndirect(lpbm);
+		reset(obj);
+
+		return obj;
+	}
+
+	HBITMAP CreateCompatibleBitmap(HDC hdc, int nWidth, int nHeight)
+	{
+		HBITMAP obj = ::CreateCompatibleBitmap(hdc, nWidth, nHeight);
+		reset(obj);
+
+		return obj;
+	}
+
+	HBITMAP CreateDIBSection(HDC hdc, const BITMAPINFO* pbmi, UINT iUsage, void** ppvBits, HANDLE hSection, DWORD dwOffset)
+	{
+		HBITMAP obj = ::CreateDIBSection(hdc, pbmi, iUsage, ppvBits, hSection, dwOffset);
+		reset(obj);
+
+		return obj;
+	}
+
+	HBITMAP LoadBitmap(HINSTANCE hInstance, LPCTSTR lpBitmapName)
+	{
+		HBITMAP obj = ::LoadBitmap(hInstance, lpBitmapName);
+		reset(obj);
+
+		return obj;
+	}
+
+	int GetBitmap(BITMAP* pBitMap)
+	{
+		ASSERT(m_obj != nullptr);
+		return ::GetObject(m_obj, sizeof(BITMAP), pBitMap);
+	}
+
+	int GetDIBSection(DIBSECTION* pDIBSection)
+	{
+		ASSERT(m_obj != nullptr);
+		return ::GetObject(m_obj, sizeof(DIBSECTION), pDIBSection);
+	}
+};
+
+class auto_brush : public auto_brush_base
+{
+public:
+	auto_brush(HBRUSH obj = nullptr) : auto_brush_base(obj) {}
+
+	auto_brush& operator = (HBRUSH obj)
+	{
+		return (auto_brush&)reset(obj);
+	}
+
+	HBRUSH CreateDIBPatternBrushPt(const void* lpPackedDIB, UINT iUsage)
+	{
+		HBRUSH obj = ::CreateDIBPatternBrushPt(lpPackedDIB, iUsage);
+		reset(obj);
+
+		return obj;
+	}
+
+	HBRUSH CreatePatternBrush(HBITMAP hbmp)
+	{
+		HBRUSH obj = ::CreatePatternBrush(hbmp);
+		reset(obj);
+
+		return obj;
+	}
+
+	HBRUSH CreateSolidBrush(COLORREF crColor)
+	{
+		HBRUSH obj = ::CreateSolidBrush(crColor);
+		reset(obj);
+
+		return obj;
+	}
+
+	int GetLogBrush(LOGBRUSH* pLogBrush)
+	{
+		ASSERT(m_obj != nullptr);
+		return ::GetObject(m_obj, sizeof(LOGBRUSH), pLogBrush);
+	}
+};
+
+class auto_palette : public auto_palette_base
+{
+public:
+	auto_palette(HPALETTE obj = nullptr) : auto_palette_base(obj) {}
+
+	auto_palette& operator = (HPALETTE obj)
+	{
+		return (auto_palette&)reset(obj);
+	}
+
+	HPALETTE CreatePalette(CONST LOGPALETTE* lplgpl)
+	{
+		HPALETTE obj = ::CreatePalette(lplgpl);
+		reset(obj);
+
+		return obj;
+	}
+
+	int GetEntryCount()
+	{
+		ASSERT(m_obj != nullptr);
+
+		WORD nEntries;
+		::GetObject(m_obj, sizeof(WORD), &nEntries);
+		return (int)nEntries;
+	}
+};
+
+class auto_pen : public auto_pen_base
+{
+public:
+	auto_pen(HPEN obj = nullptr) : auto_pen_base(obj) {}
+
+	auto_pen& operator = (HPEN obj)
+	{
+		return (auto_pen&)reset(obj);
+	}
+
+	HPEN CreatePen(int fnPenStyle, int nWidth, COLORREF crColor)
+	{
+		HPEN obj = ::CreatePen(fnPenStyle, nWidth, crColor);
+		reset(obj);
+
+		return obj;
+	}
+
+	HPEN CreatePenIndirect(const LOGPEN* lplgpn)
+	{
+		HPEN obj = ::CreatePenIndirect(lplgpn);
+		reset(obj);
+
+		return obj;
+	}
+
+	int GetLogPen(LOGPEN* pLogPen)
+	{
+		ASSERT(m_obj != nullptr);
+		return ::GetObject(m_obj, sizeof(LOGPEN), pLogPen);
+	}
+};
+
+class auto_rgn : public auto_rgn_base
+{
+public:
+	auto_rgn(HRGN obj = nullptr) : auto_rgn_base(obj) {}
+
+	auto_rgn& operator = (HRGN obj)
+	{
+		return (auto_rgn&)reset(obj);
+	}
+
+	HRGN CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)
+	{
+		HRGN obj = ::CreateRectRgn(nLeftRect, nTopRect, nRightRect, nBottomRect);
+		reset(obj);
+
+		return obj;
+	}
+
+	HRGN CreateRectRgnIndirect(const RECT* lprc)
+	{
+		HRGN obj = ::CreateRectRgnIndirect(lprc);
+		reset(obj);
+
+		return obj;
+	}
+};
+
+class auto_font : public auto_font_base
+{
+public:
+	auto_font(HFONT obj = nullptr) : auto_font_base(obj) {}
+
+	auto_font& operator = (HFONT obj)
+	{
+		return (auto_font&)reset(obj);
+	}
+
+	HFONT CreateFont(
+						int nHeight,				// height of font
+						int nWidth,					// average character width
+						int nEscapement,			// angle of escapement
+						int nOrientation,			// base-line orientation angle
+						int fnWeight,				// font weight
+						DWORD bItalic,				// italic attribute option
+						DWORD bUnderline,			// underline attribute option
+						DWORD cStrikeOut,			// strikeout attribute option
+						DWORD nCharSet,				// character set identifier
+						DWORD nOutPrecision,		// output precision
+						DWORD nClipPrecision,		// clipping precision
+						DWORD nQuality,				// output quality
+						DWORD nPitchAndFamily,		// pitch and family
+						LPCTSTR lpszFace           // typeface name
+					)
+	{
+		HFONT obj = ::CreateFont(
+									nHeight,
+									nWidth,
+									nEscapement,
+									nOrientation,
+									fnWeight,
+									bItalic,
+									bUnderline,
+									cStrikeOut,
+									nCharSet,
+									nOutPrecision,
+									nClipPrecision,
+									nQuality,
+									nPitchAndFamily,
+									lpszFace
+								);
+		reset(obj);
+
+		return obj;
+	}
+
+	HFONT CreateFontIndirect(const LOGFONT* lplf)
+	{
+		HFONT obj = ::CreateFontIndirect(lplf);
+		reset(obj);
+
+		return obj;
+	}
+
+	int GetLogFont(LOGFONT* pLogFont)
+	{
+		ASSERT(m_obj != nullptr);
+		return ::GetObject(m_obj, sizeof(LOGFONT), pLogFont);
+	}
+};

+ 437 - 0
source/hook/hp-src/bufferpool.cpp

@@ -0,0 +1,437 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/******************************************************************************
+Module:  BufferPool.cpp
+Notices: Copyright (c) 2013 Bruce Liang
+Purpose: ¼òµ¥Äڴ滺³å³Ø
+Desc:
+******************************************************************************/
+
+#include "stdafx.h"
+#include "bufferpool.h"
+#include "SysHelper.h"
+#include "WaitFor.h"
+
+const DWORD TItem::DEFAULT_ITEM_CAPACITY			= ::SysGetPageSize();
+const DWORD CBufferPool::DEFAULT_MAX_CACHE_SIZE		= 0;
+const DWORD CBufferPool::DEFAULT_ITEM_CAPACITY		= CItemPool::DEFAULT_ITEM_CAPACITY;
+const DWORD CBufferPool::DEFAULT_ITEM_POOL_SIZE		= CItemPool::DEFAULT_POOL_SIZE;
+const DWORD CBufferPool::DEFAULT_ITEM_POOL_HOLD		= CItemPool::DEFAULT_POOL_HOLD;
+const DWORD CBufferPool::DEFAULT_BUFFER_LOCK_TIME	= 10 * 1000;
+const DWORD CBufferPool::DEFAULT_BUFFER_POOL_SIZE	= 150;
+const DWORD CBufferPool::DEFAULT_BUFFER_POOL_HOLD	= 600;
+
+TItem* TItem::Construct(CPrivateHeap& heap, int capacity, BYTE* pData, int length)
+{
+	ASSERT(capacity > 0);
+
+	int item_size	= sizeof(TItem);
+	TItem* pItem	= (TItem*)heap.Alloc(item_size + capacity);
+	pItem->head		= (BYTE*)pItem + item_size;
+
+	pItem->TItem::TItem(heap, capacity, pData, length);
+
+	return pItem;
+}
+
+void TItem::Destruct(TItem* pItem)
+{
+	ASSERT(pItem != nullptr);
+
+	CPrivateHeap& heap = pItem->heap;
+	pItem->TItem::~TItem();
+	heap.Free(pItem);
+}
+
+inline int TItem::Cat(const BYTE* pData, int length)
+{
+	ASSERT(pData != nullptr && length > 0);
+
+	int cat = min(Remain(), length);
+
+	if(cat > 0)
+	{
+		memcpy(end, pData, cat);
+		end += cat;
+	}
+
+	return cat;
+}
+
+inline int TItem::Cat(const TItem& other)
+{
+	ASSERT(this != &other);
+	return Cat(other.Ptr(), other.Size());
+}
+
+inline int TItem::Fetch(BYTE* pData, int length)
+{
+	ASSERT(pData != nullptr && length > 0);
+
+	int fetch = min(Size(), length);
+	memcpy(pData, begin, fetch);
+	begin	 += fetch;
+
+	return fetch;
+}
+
+inline int TItem::Peek(BYTE* pData, int length)
+{
+	ASSERT(pData != nullptr && length > 0);
+
+	int peek = min(Size(), length);
+	memcpy(pData, begin, peek);
+
+	return peek;
+}
+
+inline int TItem::Reduce(int length)
+{
+	ASSERT(length > 0);
+
+	int reduce   = min(Size(), length);
+	begin		+= reduce;
+
+	return reduce;
+}
+
+inline void	TItem::Reset(int first, int last)
+{
+	ASSERT(first >= -1 && first <= capacity);
+	ASSERT(last >= -1 && last <= capacity);
+
+	if(first >= 0)	begin	= head + min(first, capacity);
+	if(last >= 0)	end		= head + min(last, capacity);
+}
+
+int TItemList::Cat(const BYTE* pData, int length)
+{
+	int remain = length;
+
+	while(remain > 0)
+	{
+		TItem* pItem = Back();
+
+		if(pItem == nullptr || pItem->IsFull())
+			pItem = PushBack(itPool.PickFreeItem());
+
+		int cat  = pItem->Cat(pData, remain);
+
+		pData	+= cat;
+		remain	-= cat;
+	}
+
+	return length;
+}
+
+int TItemList::Cat(const TItem* pItem)
+{
+	return Cat(pItem->Ptr(), pItem->Size());
+}
+
+int TItemList::Cat(const TItemList& other)
+{
+	ASSERT(this != &other);
+
+	int length = 0;
+
+	for(TItem* pItem = other.Front(); pItem != nullptr; pItem = pItem->next)
+		length += Cat(pItem);
+
+	return length;
+}
+
+int TItemList::Fetch(BYTE* pData, int length)
+{
+	int remain = length;
+
+	while(remain > 0 && Size() > 0)
+	{
+		TItem* pItem = Front();
+		int fetch	 = pItem->Fetch(pData, remain);
+
+		pData	+= fetch;
+		remain	-= fetch;
+
+		if(pItem->IsEmpty())
+			itPool.PutFreeItem(PopFront());
+	}
+
+	return length - remain;
+}
+
+int TItemList::Peek(BYTE* pData, int length)
+{
+	int remain	 = length;
+	TItem* pItem = Front();
+
+	while(remain > 0 && pItem != nullptr)
+	{
+		int peek = pItem->Peek(pData, remain);
+
+		pData	+= peek;
+		remain	-= peek;
+		pItem	 = pItem->next;
+	}
+
+	return length - remain;
+}
+
+int TItemList::Reduce(int length)
+{
+	int remain = length;
+
+	while(remain > 0 && Size() > 0)
+	{
+		TItem* pItem = Front();
+		remain		-= pItem->Reduce(remain);
+
+		if(pItem->IsEmpty())
+			itPool.PutFreeItem(PopFront());
+	}
+
+	return length - remain;
+}
+
+void TItemList::Release()
+{
+	itPool.PutFreeItem(*this);
+}
+
+TBuffer* TBuffer::Construct(CBufferPool& pool, ULONG_PTR dwID)
+{
+	ASSERT(dwID != 0);
+
+	CPrivateHeap& heap	= pool.GetPrivateHeap();
+	TBuffer* pBuffer	= (TBuffer*)heap.Alloc(sizeof(TBuffer));
+
+	pBuffer->TBuffer::TBuffer(heap, pool.GetItemPool(), dwID);
+
+	return pBuffer;
+}
+
+void TBuffer::Destruct(TBuffer* pBuffer)
+{
+	ASSERT(pBuffer != nullptr);
+
+	CPrivateHeap& heap = pBuffer->heap;
+	pBuffer->TBuffer::~TBuffer();
+	heap.Free(pBuffer);
+}
+
+inline void TBuffer::Reset()
+{
+	id		 = 0;
+	length	 = 0;
+	freeTime = ::TimeGetTime();
+}
+
+int TBuffer::Cat(const BYTE* pData, int len)
+{
+	items.Cat(pData, len);
+	return IncreaseLength(len);
+}
+
+int TBuffer::Cat(const TItem* pItem)
+{
+	items.Cat(pItem);
+	return IncreaseLength(pItem->Size());
+}
+
+int TBuffer::Cat(const TItemList& other)
+{
+	ASSERT(&items != &other);
+
+	for(TItem* pItem = other.Front(); pItem != nullptr; pItem = pItem->next)
+		Cat(pItem);
+
+	return length;
+}
+
+int TBuffer::Fetch(BYTE* pData, int len)
+{
+	int fetch = items.Fetch(pData, len);
+	DecreaseLength(fetch);
+
+	return fetch;
+}
+
+int TBuffer::Peek(BYTE* pData, int len)
+{
+	return items.Peek(pData, len);
+}
+
+int TBuffer::Reduce(int len)
+{
+	int reduce = items.Reduce(len);
+	DecreaseLength(reduce);
+
+	return reduce;
+}
+
+void CBufferPool::PutFreeBuffer(ULONG_PTR dwID)
+{
+	ASSERT(dwID != 0);
+
+	TBuffer* pBuffer = FindCacheBuffer(dwID);
+
+	if(pBuffer != nullptr)
+		PutFreeBuffer(pBuffer);
+}
+
+void CBufferPool::PutFreeBuffer(TBuffer* pBuffer)
+{
+	ASSERT(pBuffer != nullptr);
+
+	if(!pBuffer->IsValid())
+		return;
+
+	m_bfCache.Remove(pBuffer->ID());
+
+	BOOL bOK = FALSE;
+
+	{
+		CCriSecLock locallock(pBuffer->cs);
+
+		if(pBuffer->IsValid())
+		{
+			pBuffer->Reset();
+			bOK = TRUE;
+		}
+	}
+
+	if(bOK)
+	{
+		m_itPool.PutFreeItem(pBuffer->items);
+
+		if(!m_lsFreeBuffer.TryPut(pBuffer))
+		{
+			m_lsGCBuffer.PushBack(pBuffer);
+
+			if(m_lsGCBuffer.Size() > m_dwBufferPoolSize)
+				ReleaseGCBuffer();
+		}
+	}
+}
+
+void CBufferPool::ReleaseGCBuffer(BOOL bForce)
+{
+	TBuffer* pBuffer = nullptr;
+	DWORD now		 = ::TimeGetTime();
+
+	while(m_lsGCBuffer.PopFront(&pBuffer))
+	{
+		if(bForce || (int)(now - pBuffer->freeTime) >= (int)m_dwBufferLockTime)
+			TBuffer::Destruct(pBuffer);
+		else
+		{
+			m_lsGCBuffer.PushBack(pBuffer);
+			break;
+		}
+	}
+}
+
+TBuffer* CBufferPool::PutCacheBuffer(ULONG_PTR dwID)
+{
+	ASSERT(dwID != 0);
+
+	TBuffer* pBuffer = PickFreeBuffer(dwID);
+	m_bfCache.Set(dwID, pBuffer);
+
+	return pBuffer;
+}
+
+TBuffer* CBufferPool::PickFreeBuffer(ULONG_PTR dwID)
+{
+	ASSERT( dwID != 0);
+
+	DWORD dwIndex;
+	TBuffer* pBuffer = nullptr;
+
+	if(m_lsFreeBuffer.TryLock(&pBuffer, dwIndex))
+	{
+		if(::GetTimeGap32(pBuffer->freeTime) >= m_dwBufferLockTime)
+			m_lsFreeBuffer.ReleaseLock(nullptr, dwIndex);
+		else
+		{
+			m_lsFreeBuffer.ReleaseLock(pBuffer, dwIndex);
+			pBuffer = nullptr;
+		}
+	}
+
+	if(pBuffer)	pBuffer->id	= dwID;
+	else		pBuffer		= TBuffer::Construct(*this, dwID);
+
+	ASSERT(pBuffer);
+	return pBuffer;
+}
+
+TBuffer* CBufferPool::FindCacheBuffer(ULONG_PTR dwID)
+{
+	ASSERT(dwID != 0);
+
+	TBuffer* pBuffer = nullptr;
+
+	if(!m_bfCache.Get(dwID, &pBuffer))
+		pBuffer = nullptr;
+
+	return pBuffer;
+}
+
+void CBufferPool::Prepare()
+{
+	m_itPool.Prepare();
+
+	m_bfCache.Reset(m_dwMaxCacheSize);
+	m_lsFreeBuffer.Reset(m_dwBufferPoolHold);
+}
+
+void CBufferPool::Clear()
+{
+	DWORD size					= 0;
+	unique_ptr<ULONG_PTR[]> ids	= m_bfCache.GetAllElementIndexes(size, FALSE);
+
+	for(DWORD i = 0; i < size; i++)
+	{
+		TBuffer* pBuffer = FindCacheBuffer(ids[i]);
+		if(pBuffer) TBuffer::Destruct(pBuffer);
+	}
+
+	m_bfCache.Reset();
+
+	TBuffer* pBuffer = nullptr;
+
+	while(m_lsFreeBuffer.TryGet(&pBuffer))
+		TBuffer::Destruct(pBuffer);
+
+	VERIFY(m_lsFreeBuffer.IsEmpty());
+	m_lsFreeBuffer.Reset();
+
+	ReleaseGCBuffer(TRUE);
+	VERIFY(m_lsGCBuffer.IsEmpty());
+
+	m_itPool.Clear();
+	m_heap.Reset();
+}

+ 683 - 0
source/hook/hp-src/bufferpool.h

@@ -0,0 +1,683 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/******************************************************************************
+Module:  BufferPool.h
+Notices: Copyright (c) 2013 Bruce Liang
+Purpose: ¼òµ¥Äڴ滺³å³Ø
+Desc:
+******************************************************************************/
+
+#pragma once
+
+#include "Singleton.h"
+#include "STLHelper.h"
+#include "RingBuffer.h"
+#include "PrivateHeap.h"
+
+struct TItem
+{
+	template<typename T> friend struct	TSimpleList;
+	template<typename T> friend class	CNodePoolT;
+
+	friend struct	TItemList;
+	friend struct	TBuffer;
+
+public:
+	inline int Cat		(const BYTE* pData, int length);
+	inline int Cat		(const TItem& other);
+	inline int Fetch	(BYTE* pData, int length);
+	inline int Peek		(BYTE* pData, int length);
+	inline int Reduce	(int length);
+	inline void	Reset	(int first = 0, int last = 0);
+
+	BYTE*		Ptr		()			{return begin;}
+	const BYTE*	Ptr		()	const	{return begin;}
+	int			Size	()	const	{return (int)(end - begin);}
+	int			Remain	()	const	{return capacity - (int)(end - head);}
+	int			Capacity()	const	{return capacity;}
+	bool		IsEmpty	()	const	{return Size()	 == 0;}
+	bool		IsFull	()	const	{return Remain() == 0;}
+
+public:
+	operator		BYTE*	()			{return Ptr();}
+	operator const	BYTE*	() const	{return Ptr();}
+
+public:
+	static TItem* Construct(CPrivateHeap& heap,
+							int		capacity	= DEFAULT_ITEM_CAPACITY,
+							BYTE*	pData		= nullptr,
+							int		length		= 0);
+
+	static void Destruct(TItem* pItem);
+
+private:
+	TItem(CPrivateHeap& hp, int cap = DEFAULT_ITEM_CAPACITY, BYTE* pData = nullptr, int length = 0)
+	: heap(hp), capacity(cap), begin(head), end(head), next(nullptr), last(nullptr)
+	{
+		if(pData != nullptr && length != 0)
+			Cat(pData, length);
+	}
+
+	~TItem() {}
+
+	DECLARE_NO_COPY_CLASS(TItem)
+
+public:
+	static const DWORD DEFAULT_ITEM_CAPACITY;
+
+private:
+	CPrivateHeap& heap;
+
+private:
+	TItem* next;
+	TItem* last;
+
+	int		capacity;
+	BYTE*	head;
+	BYTE*	begin;
+	BYTE*	end;
+};
+
+template<class T> struct TSimpleList
+{
+public:
+	T* PushFront(T* pItem)
+	{
+		if(pFront != nullptr)
+		{
+			pFront->last = pItem;
+			pItem->next	 = pFront;
+		}
+		else
+		{
+			pItem->last = nullptr;
+			pItem->next = nullptr;
+			pBack		= pItem;
+		}
+
+		pFront = pItem;
+		++size;
+
+		return pItem;
+	}
+
+	T* PushBack(T* pItem)
+	{
+		if(pBack != nullptr)
+		{
+			pBack->next	= pItem;
+			pItem->last	= pBack;
+		}
+		else
+		{
+			pItem->last = nullptr;
+			pItem->next = nullptr;
+			pFront		= pItem;
+		}
+
+		pBack = pItem;
+		++size;
+
+		return pItem;
+	}
+
+	T* PopFront()
+	{
+		T* pItem = pFront;
+
+		if(pFront != pBack)
+		{
+			pFront = pFront->next;
+			pFront->last = nullptr;
+		}
+		else if(pFront != nullptr)
+		{
+			pFront	= nullptr;
+			pBack	= nullptr;
+		}
+
+		if(pItem != nullptr)
+		{
+			pItem->next = nullptr;
+			pItem->last = nullptr;
+
+			--size;
+		}
+
+		return pItem;
+	}
+
+	T* PopBack()
+	{
+		T* pItem = pBack;
+
+		if(pFront != pBack)
+		{
+			pBack = pBack->last;
+			pBack->next	= nullptr;
+		}
+		else if(pBack != nullptr)
+		{
+			pFront	= nullptr;
+			pBack	= nullptr;
+		}
+
+		if(pItem != nullptr)
+		{
+			pItem->next = nullptr;
+			pItem->last = nullptr;
+
+			--size;
+		}
+
+		return pItem;
+	}
+
+	TSimpleList<T>& Shift(TSimpleList<T>& other)
+	{
+		if(&other != this && other.size > 0)
+		{
+			if(size > 0)
+			{
+				pBack->next = other.pFront;
+				other.pFront->last = pBack;
+			}
+			else
+			{
+				pFront = other.pFront;
+			}
+
+			pBack	 = other.pBack;
+			size	+= other.size;
+
+			other.Reset();
+		}
+
+		return *this;
+	}
+
+	void Clear()
+	{
+		if(size > 0)
+		{
+			T* pItem;
+			while((pItem = PopFront()) != nullptr)
+				T::Destruct(pItem);
+		}
+	}
+
+	T*		Front	()	const	{return pFront;}
+	T*		Back	()	const	{return pBack;}
+	int		Size	()	const	{return size;}
+	bool	IsEmpty	()	const	{return size == 0;}
+
+public:
+	TSimpleList()	{Reset();}
+	~TSimpleList()	{Clear();}
+
+	DECLARE_NO_COPY_CLASS(TSimpleList<T>)
+
+private:
+	void Reset()
+	{
+		pFront	= nullptr;
+		pBack	= nullptr;
+		size	= 0;
+	}
+
+private:
+	int	size;
+	T*	pFront;
+	T*	pBack;
+};
+
+template<class T> class CNodePoolT
+{
+public:
+	void PutFreeItem(T* pItem)
+	{
+		ASSERT(pItem != nullptr);
+
+		if(!m_lsFreeItem.TryPut(pItem))
+			T::Destruct(pItem);
+	}
+
+	void PutFreeItem(TSimpleList<T>& lsItem)
+	{
+		if(lsItem.IsEmpty())
+			return;
+
+		T* pItem;
+		while((pItem = lsItem.PopFront()) != nullptr)
+			PutFreeItem(pItem);
+	}
+
+	T* PickFreeItem()
+	{
+		T* pItem = nullptr;
+
+		if(m_lsFreeItem.TryGet(&pItem))
+			pItem->Reset();
+		else
+			pItem = T::Construct(m_heap, m_dwItemCapacity);
+
+		return pItem;
+	}
+
+	inline void Prepare()
+	{
+		m_lsFreeItem.Reset(m_dwPoolHold);
+	}
+
+	inline void Clear()
+	{
+		T* pItem = nullptr;
+
+		while(m_lsFreeItem.TryGet(&pItem))
+			T::Destruct(pItem);
+
+		VERIFY(m_lsFreeItem.IsEmpty());
+		m_lsFreeItem.Reset();
+
+		m_heap.Reset();
+	}
+
+public:
+	void SetItemCapacity(DWORD dwItemCapacity)	{m_dwItemCapacity	= dwItemCapacity;}
+	void SetPoolSize	(DWORD dwPoolSize)		{m_dwPoolSize		= dwPoolSize;}
+	void SetPoolHold	(DWORD dwPoolHold)		{m_dwPoolHold		= dwPoolHold;}
+	DWORD GetItemCapacity	()					{return m_dwItemCapacity;}
+	DWORD GetPoolSize		()					{return m_dwPoolSize;}
+	DWORD GetPoolHold		()					{return m_dwPoolHold;}
+
+public:
+	CNodePoolT(	DWORD dwPoolSize	 = DEFAULT_POOL_SIZE,
+				DWORD dwPoolHold	 = DEFAULT_POOL_HOLD,
+				DWORD dwItemCapacity = DEFAULT_ITEM_CAPACITY)
+				: m_dwPoolSize(dwPoolSize)
+				, m_dwPoolHold(dwPoolHold)
+				, m_dwItemCapacity(dwItemCapacity)
+	{
+	}
+
+	~CNodePoolT()	{Clear();}
+
+	DECLARE_NO_COPY_CLASS(CNodePoolT)
+
+public:
+	static const DWORD DEFAULT_ITEM_CAPACITY;
+	static const DWORD DEFAULT_POOL_SIZE;
+	static const DWORD DEFAULT_POOL_HOLD;
+
+private:
+	CPrivateHeap	m_heap;
+
+	DWORD			m_dwItemCapacity;
+	DWORD			m_dwPoolSize;
+	DWORD			m_dwPoolHold;
+
+	CRingPool<T>	m_lsFreeItem;
+};
+
+template<class T> const DWORD CNodePoolT<T>::DEFAULT_ITEM_CAPACITY	= TItem::DEFAULT_ITEM_CAPACITY;
+template<class T> const DWORD CNodePoolT<T>::DEFAULT_POOL_SIZE		= 300;
+template<class T> const DWORD CNodePoolT<T>::DEFAULT_POOL_HOLD		= 1200;
+
+typedef CNodePoolT<TItem>	CItemPool;
+
+struct TItemList : public TSimpleList<TItem>
+{
+public:
+	int Cat		(const BYTE* pData, int length);
+	int Cat		(const TItem* pItem);
+	int Cat		(const TItemList& other);
+	int Fetch	(BYTE* pData, int length);
+	int Peek	(BYTE* pData, int length);
+	int Reduce	(int length);
+	void Release();
+
+public:
+	TItemList(CItemPool& pool) : itPool(pool)
+	{
+	}
+
+private:
+	CItemPool& itPool;
+};
+
+struct TItemListEx : public TItemList
+{
+public:
+	TItem* PushFront(TItem* pItem)
+	{
+		length += pItem->Size();
+		return __super::PushFront(pItem);
+	}
+
+	TItem* PushBack(TItem* pItem)
+	{
+		length += pItem->Size();
+		return __super::PushBack(pItem);
+	}
+
+	TItem* PopFront()
+	{
+		TItem* pItem = __super::PopFront();
+
+		if(pItem != nullptr)
+			length -= pItem->Size();
+
+		return pItem;
+	}
+
+	TItem* PopBack()
+	{
+		TItem* pItem = __super::PopBack();
+
+		if(pItem != nullptr)
+			length -= pItem->Size();
+
+		return pItem;
+	}
+
+	TItemListEx& Shift(TItemListEx& other)
+	{
+		if(&other != this && other.length > 0)
+		{
+			length += other.length;
+			other.length = 0;
+
+			__super::Shift(other);
+		}
+
+		return *this;
+	}
+
+	void Clear()
+	{
+		__super::Clear();
+		length = 0;
+	}
+
+	void Release()
+	{
+		__super::Release();
+		length = 0;
+	}
+
+public:
+	int Cat(const BYTE* pData, int length)
+	{
+		int cat = __super::Cat(pData, length);
+		this->length += cat;
+
+		return cat;
+	}
+
+	int Cat(const TItem* pItem)
+	{
+		int cat = __super::Cat(pItem->Ptr(), pItem->Size());
+		this->length += cat;
+
+		return cat;
+	}
+
+	int Cat(const TItemList& other)
+	{
+		int cat = __super::Cat(other);
+		this->length += cat;
+
+		return cat;
+	}
+
+	int Fetch(BYTE* pData, int length)
+	{
+		int fetch	  = __super::Fetch(pData, length);
+		this->length -= fetch;
+
+		return fetch;
+	}
+
+	int Reduce(int length)
+	{
+		int reduce	  = __super::Reduce(length);
+		this->length -= reduce;
+
+		return reduce;
+	}
+	
+	int Length() const {return length;}
+
+public:
+	TItemListEx(CItemPool& pool) : TItemList(pool), length(0)
+	{
+	}
+
+	~TItemListEx()
+	{
+		ASSERT(length >= 0);
+	}
+
+	DECLARE_NO_COPY_CLASS(TItemListEx)
+
+private:
+	int length;
+};
+
+struct TItemPtr
+{
+public:
+	TItem* Reset(TItem* pItem = nullptr)
+	{
+		if(m_pItem != nullptr)
+			itPool.PutFreeItem(m_pItem);
+
+		m_pItem = pItem;
+
+		return m_pItem;
+	}
+
+	TItem* Attach(TItem* pItem)
+	{
+		return Reset(pItem);
+	}
+
+	TItem* Detach()
+	{
+		TItem* pItem = m_pItem;
+		m_pItem		 = nullptr;
+
+		return pItem;
+	}
+
+	bool IsValid			()				{return m_pItem != nullptr;}
+	TItem* operator ->		()				{return m_pItem;}
+	TItem* operator =		(TItem* pItem)	{return Reset(pItem);}
+	operator TItem*			()				{return m_pItem;}
+	TItem* Ptr				()				{return m_pItem;}
+	const TItem* Ptr		()	const		{return m_pItem;}
+	operator const TItem*	()	const		{return m_pItem;}
+
+public:
+	TItemPtr(CItemPool& pool, TItem* pItem = nullptr)
+	: itPool(pool), m_pItem(pItem)
+	{
+
+	}
+
+	~TItemPtr()
+	{
+		Reset();
+	}
+
+	DECLARE_NO_COPY_CLASS(TItemPtr)
+
+private:
+	CItemPool&	itPool;
+	TItem*		m_pItem;
+};
+
+struct TBuffer
+{
+	template<typename T> friend struct TSimpleList;
+	friend class CBufferPool;
+
+public:
+	static TBuffer* Construct(CBufferPool& pool, ULONG_PTR dwID);
+	static void Destruct(TBuffer* pBuffer);
+
+public:
+	int Cat		(const BYTE* pData, int len);
+	int Cat		(const TItem* pItem);
+	int Cat		(const TItemList& other);
+	int Fetch	(BYTE* pData, int length);
+	int Peek	(BYTE* pData, int length);
+	int Reduce	(int len);
+
+public:
+	CCriSec&	CriSec	()	{return cs;}
+	TItemList&	ItemList()	{return items;}
+
+	ULONG_PTR ID		()	const	{return id;}
+	int Length			()	const	{return length;}
+	bool IsValid		()	const	{return id != 0;}
+
+private:
+	int IncreaseLength	(int len)	{return (length += len);}
+	int DecreaseLength	(int len)	{return (length -= len);}
+
+	inline void Reset	();
+
+private:
+	TBuffer(CPrivateHeap& hp, CItemPool& itPool, ULONG_PTR dwID = 0)
+	: heap(hp), items(itPool), id(dwID), length(0)
+	{
+	}
+
+	~TBuffer()	{}
+
+	DECLARE_NO_COPY_CLASS(TBuffer)
+
+private:
+	CPrivateHeap&	heap;
+
+private:
+	ULONG_PTR		id;
+	int				length;
+	DWORD			freeTime;
+
+private:
+	TBuffer*		next;
+	TBuffer*		last;
+
+	CCriSec			cs;
+	TItemList		items;
+};
+
+class CBufferPool
+{
+	typedef CRingPool<TBuffer>						TBufferList;
+	typedef CCASQueue<TBuffer>						TBufferQueue;
+
+	typedef CRingCache<TBuffer, ULONG_PTR, true>	TBufferCache;
+
+public:
+	void		PutFreeBuffer	(ULONG_PTR dwID);
+	TBuffer*	PutCacheBuffer	(ULONG_PTR dwID);
+	TBuffer*	FindCacheBuffer	(ULONG_PTR dwID);
+	TBuffer*	PickFreeBuffer	(ULONG_PTR dwID);
+	void		PutFreeBuffer	(TBuffer* pBuffer);
+
+	void		Prepare			();
+	void		Clear			();
+
+private:
+	void ReleaseGCBuffer	(BOOL bForce = FALSE);
+
+public:
+	void SetItemCapacity	(DWORD dwItemCapacity)		{m_itPool.SetItemCapacity(dwItemCapacity);}
+	void SetItemPoolSize	(DWORD dwItemPoolSize)		{m_itPool.SetPoolSize(dwItemPoolSize);}
+	void SetItemPoolHold	(DWORD dwItemPoolHold)		{m_itPool.SetPoolHold(dwItemPoolHold);}
+
+	void SetMaxCacheSize	(DWORD dwMaxCacheSize)		{m_dwMaxCacheSize	= dwMaxCacheSize;}
+	void SetBufferLockTime	(DWORD dwBufferLockTime)	{m_dwBufferLockTime	= dwBufferLockTime;}
+	void SetBufferPoolSize	(DWORD dwBufferPoolSize)	{m_dwBufferPoolSize	= dwBufferPoolSize;}
+	void SetBufferPoolHold	(DWORD dwBufferPoolHold)	{m_dwBufferPoolHold	= dwBufferPoolHold;}
+
+	DWORD GetItemCapacity	()							{return m_itPool.GetItemCapacity();}
+	DWORD GetItemPoolSize	()							{return m_itPool.GetPoolSize();}
+	DWORD GetItemPoolHold	()							{return m_itPool.GetPoolHold();}
+
+	DWORD GetMaxCacheSize	()							{return m_dwMaxCacheSize;}
+	DWORD GetBufferLockTime	()							{return m_dwBufferLockTime;}
+	DWORD GetBufferPoolSize	()							{return m_dwBufferPoolSize;}
+	DWORD GetBufferPoolHold	()							{return m_dwBufferPoolHold;}
+
+	TBuffer* operator []	(ULONG_PTR dwID)			{return FindCacheBuffer(dwID);}
+
+public:
+	CBufferPool(DWORD dwPoolSize	 = DEFAULT_BUFFER_POOL_SIZE,
+				DWORD dwPoolHold	 = DEFAULT_BUFFER_POOL_HOLD,
+				DWORD dwLockTime	 = DEFAULT_BUFFER_LOCK_TIME,
+				DWORD dwMaxCacheSize = DEFAULT_MAX_CACHE_SIZE)
+	: m_dwBufferPoolSize(dwPoolSize)
+	, m_dwBufferPoolHold(dwPoolHold)
+	, m_dwBufferLockTime(dwLockTime)
+	, m_dwMaxCacheSize(dwMaxCacheSize)
+	{
+
+	}
+
+	~CBufferPool()	{Clear();}
+
+	DECLARE_NO_COPY_CLASS(CBufferPool)
+
+public:
+	CPrivateHeap&	GetPrivateHeap()	{return m_heap;}
+	CItemPool&		GetItemPool()		{return m_itPool;}
+
+public:
+	static const DWORD DEFAULT_MAX_CACHE_SIZE;
+	static const DWORD DEFAULT_ITEM_CAPACITY;
+	static const DWORD DEFAULT_ITEM_POOL_SIZE;
+	static const DWORD DEFAULT_ITEM_POOL_HOLD;
+	static const DWORD DEFAULT_BUFFER_LOCK_TIME;
+	static const DWORD DEFAULT_BUFFER_POOL_SIZE;
+	static const DWORD DEFAULT_BUFFER_POOL_HOLD;
+
+private:
+	DWORD			m_dwMaxCacheSize;
+	DWORD			m_dwBufferLockTime;
+	DWORD			m_dwBufferPoolSize;
+	DWORD			m_dwBufferPoolHold;
+
+	CPrivateHeap	m_heap;
+	CItemPool		m_itPool;
+
+	TBufferCache	m_bfCache;
+
+	TBufferList		m_lsFreeBuffer;
+	TBufferQueue	m_lsGCBuffer;
+};

+ 26 - 0
source/hook/hp-src/bufferptr.cpp

@@ -0,0 +1,26 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+#include "bufferptr.h"

+ 184 - 0
source/hook/hp-src/bufferptr.h

@@ -0,0 +1,184 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory.h>
+#include <malloc.h>
+
+template<class T, size_t MAX_CACHE_SIZE = 0>
+class CBufferPtrT
+{
+public:
+	explicit CBufferPtrT(size_t size = 0, bool zero = false)		{Reset(); Malloc(size, zero);}
+	explicit CBufferPtrT(const T* pch, size_t size)					{Reset(); Copy(pch, size);}
+	CBufferPtrT(const CBufferPtrT& other)							{Reset(); Copy(other);}
+	template<size_t S> CBufferPtrT(const CBufferPtrT<T, S>& other)	{Reset(); Copy(other);}
+
+	~CBufferPtrT() {Free();}
+
+	T* Malloc(size_t size = 1, bool zero = false)
+	{
+		Free();
+		return Alloc(size, zero, false);
+	}
+
+	T* Realloc(size_t size, bool zero = false)
+	{
+		return Alloc(size, zero, true);
+	}
+
+	void Free()
+	{
+		if(m_pch)
+		{
+			free(m_pch);
+			Reset();
+		}
+	}
+
+	template<size_t S> CBufferPtrT& Copy(const CBufferPtrT<T, S>& other)
+	{
+		if((void*)&other != (void*)this)
+			Copy(other.Ptr(), other.Size());
+
+		return *this;
+	}
+
+	CBufferPtrT& Copy(const T* pch, size_t size)
+	{
+		Malloc(size);
+
+		if(m_pch)
+			memcpy(m_pch, pch, size * sizeof(T));
+
+		return *this;
+	}
+
+	template<size_t S> CBufferPtrT& Cat(const CBufferPtrT<T, S>& other)
+	{
+		if((void*)&other != (void*)this)
+			Cat(other.Ptr(), other.Size());
+
+		return *this;
+	}
+
+	CBufferPtrT& Cat(const T* pch, size_t size = 1)
+	{
+		size_t pre_size = m_size;
+		Realloc(m_size + size);
+
+		if(m_pch)
+			memcpy(m_pch + pre_size, pch, size * sizeof(T));
+
+		return *this;
+	}
+
+	template<size_t S> bool Equal(const CBufferPtrT<T, S>& other) const
+	{
+		if((void*)&other == (void*)this)
+			return true;
+		else if(m_size != other.Size())
+			return false;
+		else if(m_size == 0)
+			return true;
+		else
+			return (memcmp(m_pch, other.Ptr(), m_size * sizeof(T)) == 0);
+	}
+
+	bool Equal(T* pch) const
+	{
+		if(m_pch == pch)
+			return true;
+		else if(!m_pch || !pch)
+			return false;
+		else
+			return (memcmp(m_pch, pch, m_size * sizeof(T)) == 0);
+	}
+
+	T*			Ptr()					{return m_pch;}
+	const T*	Ptr()			const	{return m_pch;}
+	T&			Get(int i)				{return *(m_pch + i);}
+	const T&	Get(int i)		const	{return *(m_pch + i);}
+	size_t		Size()			const	{return m_size;}
+	bool		IsValid()		const	{return m_pch != 0;}
+
+	operator							T*	()									{return Ptr();}
+	operator const						T*	()			const					{return Ptr();}
+	T& operator							[]	(int i)								{return Get(i);}
+	const T& operator					[]	(int i)		const					{return Get(i);}
+	bool operator						==	(T* pv)		const					{return Equal(pv);}
+	template<size_t S> bool operator	==	(const CBufferPtrT<T, S>& other)	{return Equal(other);}
+	CBufferPtrT& operator				=	(const CBufferPtrT& other)			{return Copy(other);}
+	template<size_t S> CBufferPtrT& operator = (const CBufferPtrT<T, S>& other)	{return Copy(other);}
+
+private:
+	void Reset()						{m_pch = 0; m_size = 0; m_capacity = 0;}
+	size_t GetAllocSize(size_t size)	{return max(size, min(size * 2, m_size + MAX_CACHE_SIZE));}
+
+	T* Alloc(size_t size, bool zero = false, bool is_realloc = false)
+	{
+		if(size >= 0 && size != m_size)
+		{
+			size_t rsize = GetAllocSize(size);
+			if(size > m_capacity || rsize < m_size)
+			{
+				m_pch = is_realloc							?
+					(T*)realloc(m_pch, rsize * sizeof(T))	:
+					(T*)malloc(rsize * sizeof(T))			;
+
+				if(m_pch || rsize == 0)
+				{
+					m_size		= size;
+					m_capacity	= rsize;
+				}
+				else
+					Reset();
+			}
+			else
+				m_size = size;
+		}
+
+		if(zero && m_pch)
+			memset(m_pch, 0, m_size * sizeof(T));
+
+		return m_pch;
+	}
+
+private:
+	T*		m_pch;
+	size_t	m_size;
+	size_t	m_capacity;
+};
+
+typedef CBufferPtrT<char>			CCharBufferPtr;
+typedef CBufferPtrT<wchar_t>		CWCharBufferPtr;
+typedef CBufferPtrT<unsigned char>	CByteBufferPtr;
+typedef CByteBufferPtr				CBufferPtr;
+
+#ifdef _UNICODE
+	typedef CWCharBufferPtr			CTCharBufferPtr;
+#else
+	typedef CCharBufferPtr			CTCharBufferPtr;
+#endif

+ 32 - 0
source/hook/hp-src/debug/win32_crtdbg.cpp

@@ -0,0 +1,32 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "stdafx.h"
+#include "win32_crtdbg.h"
+
+#if defined _DEBUG && defined _DETECT_MEMORY_LEAK
+
+__dbg_impl::CDebugEnv __dbgEnv;
+
+#endif // _DEBUG && defined _DETECT_MEMORY_LEAK

+ 143 - 0
source/hook/hp-src/debug/win32_crtdbg.h

@@ -0,0 +1,143 @@
+/*
+ * Copyright: JessMA Open Source (ldcsaa@gmail.com)
+ *
+ * Version	: 2.3.15
+ * Author	: Bruce Liang
+ * Website	: http://www.jessma.org
+ * Project	: https://github.com/ldcsaa
+ * Blog		: http://www.cnblogs.com/ldcsaa
+ * Wiki		: http://www.oschina.net/p/hp-socket
+ * QQ Group	: 75375912
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#pragma once
+
+#if defined _DEBUG && defined _DETECT_MEMORY_LEAK
+
+#ifdef new
+	#undef new
+#endif
+
+#ifdef delete
+	#undef delete
+#endif
+
+#ifndef _CRTDBG_MAP_ALLOC
+	#define _CRTDBG_MAP_ALLOC
+#endif
+
+#include <crtdbg.h>
+
+namespace __dbg_impl
+{
+	class CDebugEnv
+	{
+	public:
+		CDebugEnv()
+		{
+			::_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
+			::_CrtMemCheckpoint(&s1);
+		}
+
+		~CDebugEnv()
+		{
+			::_CrtMemCheckpoint(&s2);
+
+			if (::_CrtMemDifference( &s3, &s1, &s2))
+			{
+				TRACE("!! Memory stats !!\n");
+				TRACE("----------------------------------------\n");
+				::_CrtMemDumpStatistics(&s3);
+				TRACE("----------------------------------------\n");
+			}
+		}
+
+	private:
+		_CrtMemState s1, s2, s3;
+	};
+
+	static __dbg_impl::CDebugEnv __dbgEnv;
+}
+
+#pragma warning(push)
+#pragma warning(disable: 4595)
+
+inline void* __cdecl operator new(size_t nSize, const char* lpszFileName, int nLine)
+{
+	// __dbg_impl::CGuard guard;
+	return ::_malloc_dbg(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
+}
+
+inline void* __cdecl operator new[](size_t nSize, const char* lpszFileName, int nLine)
+{
+	return operator new(nSize, lpszFileName, nLine);
+}
+
+inline void* __cdecl operator new(size_t nSize)
+{
+	return operator new(nSize, __FILE__, __LINE__);
+}
+
+inline void* __cdecl operator new[](size_t nSize)
+{
+	return operator new(nSize, __FILE__, __LINE__);
+}
+
+inline void* __cdecl operator new(size_t nSize, const std::nothrow_t&)
+{
+	return operator new(nSize, __FILE__, __LINE__);
+}
+
+inline void* __cdecl operator new[](size_t nSize, const std::nothrow_t&)
+{
+	return operator new(nSize, __FILE__, __LINE__);
+}
+
+inline void __cdecl operator delete(void* p)
+{
+	// __dbg_impl::CGuard guard;
+	::_free_dbg(p, _NORMAL_BLOCK);
+}
+
+inline void __cdecl operator delete[](void* p)
+{
+	operator delete(p);
+}
+
+inline void __cdecl operator delete(void* p, const char* lpszFileName, int nLine)
+{
+	operator delete(p);
+}
+
+inline void __cdecl operator delete[](void* p, const char* lpszFileName, int nLine)
+{
+	operator delete(p);
+}
+
+inline void __cdecl operator delete(void *p, const std::nothrow_t&)
+{
+	operator delete(p);
+}
+
+inline void __cdecl operator delete[](void *p, const std::nothrow_t&)
+{
+	operator delete(p);
+}
+
+#pragma warning(pop)
+
+#define new new(__FILE__, __LINE__)
+
+#endif // _DEBUG && defined _DETECT_MEMORY_LEAK

+ 705 - 0
source/hook/hp-src/helper.cpp

@@ -0,0 +1,705 @@
+#include "stdafx.h"
+#include "helper.h"
+
+CWnd*		g_pMainWnd;
+CListBox*	g_pInfoList;
+
+info_msg* info_msg::Construct(CONNID dwConnID, LPCTSTR lpszEvent, int iContentLength, LPCTSTR lpszContent, LPCTSTR lpszName)
+{
+	return new info_msg(dwConnID, lpszEvent, iContentLength, lpszContent, lpszName);
+}
+
+void info_msg::Destruct(info_msg* pMsg)
+{
+	delete pMsg;
+}
+
+info_msg::info_msg(CONNID dwConnID, LPCTSTR lpszEvent, int iContentLength, LPCTSTR lpszContent, LPCTSTR lpszName)
+	: connID(dwConnID), evt(lpszEvent), contentLength(iContentLength), content(lpszContent), name(nullptr)
+{
+	if(lpszName)
+	{
+		int len = lstrlen(lpszName);
+
+		if(len > 0)
+		{
+			name = new TCHAR[len + 1];
+			memcpy((LPSTR)name, lpszName, (len + 1) * sizeof(TCHAR));
+		}
+	}
+}
+
+info_msg::~info_msg()
+{
+	if(name)
+		delete[] name;
+
+	if(contentLength > 0)
+		delete[] content;
+}
+
+void SetMainWnd(CWnd* pWnd)
+{
+	g_pMainWnd = pWnd;
+}
+
+void SetInfoList(CListBox* pInfoList)
+{
+	g_pInfoList = pInfoList;
+}
+
+inline CString SafeString(LPCTSTR lpszName)
+{
+	CString str(lpszName);
+
+	if(lpszName) str.AppendChar(' ');
+
+	return str;
+}
+
+inline CString SafeString2(LPCTSTR lpszName)
+{
+	CString str(lpszName);
+
+	if(lpszName) str.Append(_T(" #"));
+
+	return str;
+}
+
+void LogServerStart(LPCTSTR lpszAddress, USHORT port, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %sServer Start OK --> (%s : %d)"), SafeString(lpszName), lpszAddress, port);
+	LogMsg(msg);
+}
+
+void LogServerStartFail(DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %sServer Start Fail --> %s (%d)"), SafeString(lpszName), lpszDesc, code);
+	LogMsg(msg);
+}
+
+void LogServerStop(LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %sServer Stop"), SafeString(lpszName));
+
+	LogMsg(msg);
+}
+
+void LogServerStopFail(DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %sServer Stop Fail --> %s (%d)"), SafeString(lpszName), lpszDesc, code);
+	LogMsg(msg);
+}
+
+void LogClientStart(LPCTSTR lpszAddress, USHORT port, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %sClient Start OK --> (%s : %d)"), SafeString(lpszName), lpszAddress, port);
+	LogMsg(msg);
+}
+
+void LogClientStarting(LPCTSTR lpszAddress, USHORT port, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %sClient Starting ... --> (%s : %d)"), SafeString(lpszName), lpszAddress, port);
+	LogMsg(msg);
+}
+
+void LogClientStartFail(DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %sClient Start Fail --> %s (%d)"), SafeString(lpszName), lpszDesc, code);
+	LogMsg(msg);
+}
+
+void LogClientStopping(CONNID dwConnID, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %sClient Stopping ... --> (%Iu)"), SafeString(lpszName), dwConnID);
+	LogMsg(msg);
+}
+
+void LogClientStopFail(DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %sClient Stop Fail --> %s (%d)"), SafeString(lpszName), lpszDesc, code);
+	LogMsg(msg);
+}
+
+void LogClientSendFail(int iSequence, int iSocketIndex, DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %sClient Send Fail [SOCK: %d, SEQ: %d] --> %s (%d)"), SafeString(lpszName), iSocketIndex, iSequence, lpszDesc, code);
+	LogMsg(msg);
+}
+
+void LogSend(CONNID dwConnID, LPCTSTR lpszContent, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %s(%Iu) Send OK --> %s"), SafeString2(lpszName), dwConnID, lpszContent);
+	LogMsg(msg);
+}
+
+void LogSendFail(CONNID dwConnID, DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %s(%Iu) Send Fail --> %s (%d)"), SafeString2(lpszName), dwConnID, lpszDesc, code, lpszName);
+	LogMsg(msg);
+}
+
+void LogDisconnect(CONNID dwConnID, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %s(%Iu) Disconnect OK"), SafeString2(lpszName), dwConnID);
+	LogMsg(msg);
+}
+
+void LogDisconnectFail(CONNID dwConnID, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %s(%Iu) Disconnect Fail"), SafeString2(lpszName), dwConnID, lpszName);
+	LogMsg(msg);
+}
+
+void LogRelease(CONNID dwConnID, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %s(%Iu) Release OK"), SafeString2(lpszName), dwConnID);
+	LogMsg(msg);
+}
+
+void LogReleaseFail(CONNID dwConnID, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %s(%Iu) Release Fail"), SafeString2(lpszName), dwConnID);
+	LogMsg(msg);
+}
+
+void LogDetect(CONNID dwConnID, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %s(%Iu) Detect Connection OK"), SafeString2(lpszName), dwConnID);
+	LogMsg(msg);
+}
+
+void LogDetectFail(CONNID dwConnID, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("$ %s(%Iu) Detect Connection Fail"), SafeString2(lpszName), dwConnID);
+	LogMsg(msg);
+}
+
+void LogOnConnect(CONNID dwConnID, const CString& strAddress, USHORT usPort, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[100];
+	wsprintf(lpszContent, _T("local address: %s:%d"), strAddress, usPort);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_CONNECT, content_len, lpszContent, lpszName);
+
+	LogInfoMsg(msg);
+}
+
+void LogOnConnect2(CONNID dwConnID, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("  > [ %s%Iu, %s ]"), SafeString2(lpszName), dwConnID, EVT_ON_CONNECT);
+	LogMsg(msg);
+}
+
+void LogOnHandShake2(CONNID dwConnID, LPCTSTR lpszName)
+{
+	CString msg;
+	msg.Format(_T("  > [ %s%Iu, %s ]"), SafeString2(lpszName), dwConnID, EVT_ON_HAND_SHAKE);
+	LogMsg(msg);
+}
+
+void PostOnSend(CONNID dwConnID, const BYTE* pData, int iLength, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[20];
+	wsprintf(lpszContent, _T("(%d bytes)"), iLength);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_SEND, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnReceive(CONNID dwConnID, const BYTE* pData, int iLength, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[20];
+	wsprintf(lpszContent, _T("(%d bytes)"), iLength);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_RECEIVE, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnReceiveCast(CONNID dwConnID, LPCTSTR lpszAddress, USHORT usPort, const BYTE* pData, int iLength, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[100];
+	wsprintf(lpszContent, _T("<%s:%d> (%d bytes)"), lpszAddress, usPort, iLength);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_RECEIVE, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnClose(CONNID dwConnID, LPCTSTR lpszName)
+{
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_CLOSE, 0, nullptr, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnError(CONNID dwConnID, int enOperation, int iErrorCode, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[100];
+	wsprintf(lpszContent, _T("OP: %d, CODE: %d"), enOperation, iErrorCode);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_ERROR, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnAccept(CONNID dwConnID, LPCTSTR lpszAddress, USHORT usPort, BOOL bPass, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[100];
+	wsprintf(lpszContent, _T("%s (%s:%d)"), bPass ? _T("PASS") : _T("REJECT"), lpszAddress, usPort);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_ACCEPT, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnAccept2(CONNID dwConnID, LPCTSTR lpszName)
+{
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_ACCEPT, 0, nullptr, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnHandShake(CONNID dwConnID, LPCTSTR lpszName)
+{
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_HAND_SHAKE, 0, nullptr, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnPrepareListen(LPCTSTR lpszAddress, USHORT usPort, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[100];
+	wsprintf(lpszContent, _T("bind address: %s:%d"), lpszAddress, usPort);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(0, EVT_ON_PREPARE_LISTEN, content_len, lpszContent, lpszName);
+
+	LogInfoMsg(msg);
+}
+
+void PostOnPrepareConnect(CONNID dwConnID, LPCTSTR lpszName)
+{
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_PREPARE_CONNECT, 0, nullptr, lpszName);
+
+	LogInfoMsg(msg);
+}
+
+void PostOnConnect(CONNID dwConnID, LPCTSTR lpszAddress, USHORT usPort, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[100];
+	wsprintf(lpszContent, _T("local address: %s:%d"), lpszAddress, usPort);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_CONNECT, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnConnect2(CONNID dwConnID, LPCTSTR lpszAddress, USHORT usPort, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[100];
+	wsprintf(lpszContent, _T("remote address: %s:%d"), lpszAddress, usPort);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_CONNECT, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnConnect3(CONNID dwConnID, LPCTSTR lpszName)
+{
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_CONNECT, 0, nullptr, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnShutdown(LPCTSTR lpszName)
+{
+	info_msg* msg = info_msg::Construct(0, EVT_ON_SHUTDOWN, 0, nullptr, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostServerStatics(const LONGLONG& llTotalSent, const LONGLONG& llTotalReceived, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[100];
+	wsprintf(lpszContent, _T(" *** Summary: send - %I64d, recv - %I64d"), llTotalSent, llTotalReceived);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(0, EVT_ON_END_TEST, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostTimeConsuming(DWORD dwTickCount, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[100];
+	wsprintf(lpszContent, _T("Total Time Consuming: %u"), dwTickCount);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(0, EVT_ON_END_TEST, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnMessageBegin(CONNID dwConnID, LPCTSTR lpszName)
+{
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_MESSAGE_BEGIN, 0, nullptr, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnRequestLine(CONNID dwConnID, LPCSTR lpszMethod, USHORT usUrlFieldSet, LPCSTR lpszUrl, LPCTSTR lpszName)
+{
+	USES_CONVERSION;
+
+	int content_len		= (int)(strlen(lpszMethod) + strlen(lpszUrl) + 20);
+	LPTSTR lpszContent	= new TCHAR[content_len];
+
+	wsprintf(lpszContent, _T("[%s/0x%02X] : %s"), A2T(lpszMethod), usUrlFieldSet, A2T(lpszUrl));
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_REQUEST_LINE, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnStatusLine(CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc, LPCTSTR lpszName)
+{
+	USES_CONVERSION;
+
+	int content_len		= (int)(strlen(lpszDesc) + 10);
+	LPTSTR lpszContent	= new TCHAR[content_len];
+
+	wsprintf(lpszContent, _T("(%u) : %s"), usStatusCode, A2T(lpszDesc));
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_STATUS_LINE, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnHeader(CONNID dwConnID, LPCSTR lpszHeaderName, LPCSTR lpszHeaderValue, LPCTSTR lpszName)
+{
+	USES_CONVERSION;
+
+	int content_len		= (int)(strlen(lpszHeaderName) + strlen(lpszHeaderValue) + 10);
+	LPTSTR lpszContent	= new TCHAR[content_len];
+
+	wsprintf(lpszContent, _T("%s: %s"), A2T(lpszHeaderName), A2T(lpszHeaderValue));
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_HEADER, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnHeadersComplete(CONNID dwConnID, LPCSTR lpszSummary, LPCTSTR lpszName)
+{
+	USES_CONVERSION;
+
+	static LPCTSTR PREFIX = _T("* * * * * * * * * Summary * * * * * * * * *\r\n");
+	static int PREFIX_LEN = lstrlen(PREFIX);
+
+	LPCTSTR lpszSummaryT = A2CT(lpszSummary);
+
+
+	int content_len		= lstrlen(lpszSummaryT) + PREFIX_LEN + 1;
+	LPTSTR lpszContent	= new TCHAR[content_len];
+
+	memcpy(lpszContent, PREFIX, PREFIX_LEN * sizeof(TCHAR));
+	memcpy(lpszContent + PREFIX_LEN, lpszSummaryT, (content_len - PREFIX_LEN) * sizeof(TCHAR));
+
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_HEADERS_COMPLETE, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnBody(CONNID dwConnID, const BYTE* pData, int iLength, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[20];
+	wsprintf(lpszContent, _T("(%d bytes)"), iLength);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_BODY, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnChunkHeader(CONNID dwConnID, int iLength, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[20];
+	wsprintf(lpszContent, _T("(%d bytes)"), iLength);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_CHUNK_HEADER, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnChunkComplete(CONNID dwConnID, LPCTSTR lpszName)
+{
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_CHUNK_COMPLETE, 0, nullptr, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnMessageComplete(CONNID dwConnID, LPCTSTR lpszName)
+{
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_MESSAGE_COMPLETE, 0, nullptr, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnUpgrade(CONNID dwConnID, EnHttpUpgradeType enUpgradeType, LPCTSTR lpszName)
+{
+	LPTSTR lpszContent = new TCHAR[20];
+	wsprintf(lpszContent, _T("(type: %d)"), enUpgradeType);
+	int content_len = lstrlen(lpszContent);
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_UPGRADE, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostOnParseError(CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc, LPCTSTR lpszName)
+{
+	USES_CONVERSION;
+
+	int content_len		= (int)(strlen(lpszErrorDesc) + 10);
+	LPTSTR lpszContent	= new TCHAR[content_len];
+
+	wsprintf(lpszContent, _T("(%i) : %s"), iErrorCode, A2T(lpszErrorDesc));
+	info_msg* msg = info_msg::Construct(dwConnID, EVT_ON_PARSE_ERROR, content_len, lpszContent, lpszName);
+
+	PostInfoMsg(msg);
+}
+
+void PostInfoMsg(info_msg* msg)
+{
+	if(	g_pMainWnd == nullptr								||
+		g_pMainWnd->GetSafeHwnd() == nullptr				||
+		!g_pMainWnd->PostMessage(USER_INFO_MSG, (WPARAM)msg	))
+		info_msg::Destruct(msg);
+}
+
+void LogInfoMsg(info_msg* pInfoMsg)
+{
+	CString msg;
+
+	if(pInfoMsg->name)
+	{
+		if(pInfoMsg->connID > 0)
+		{
+			if(pInfoMsg->contentLength > 0)
+				msg.Format(_T("  > [ %s #%Iu, %s ] -> %s"), pInfoMsg->name, pInfoMsg->connID, pInfoMsg->evt, pInfoMsg->content);
+			else
+				msg.Format(_T("  > [ %s #%Iu, %s ]"), pInfoMsg->name, pInfoMsg->connID, pInfoMsg->evt);
+		}
+		else
+		{
+			if(pInfoMsg->contentLength > 0)
+				msg.Format(_T("  > [ %s - %s ] -> %s"), pInfoMsg->name, pInfoMsg->evt, pInfoMsg->content);
+			else
+				msg.Format(_T("  > [ %s - %s ]"), pInfoMsg->name, pInfoMsg->evt);
+		}
+	}
+	else
+	{
+		if(pInfoMsg->connID > 0)
+		{
+			if(pInfoMsg->contentLength > 0)
+				msg.Format(_T("  > [ %Iu, %s ] -> %s"), pInfoMsg->connID, pInfoMsg->evt, pInfoMsg->content);
+			else
+				msg.Format(_T("  > [ %Iu, %s ]"), pInfoMsg->connID, pInfoMsg->evt);
+		}
+		else
+		{
+			if(pInfoMsg->contentLength > 0)
+				msg.Format(_T("  > [ %s ] -> %s"), pInfoMsg->evt, pInfoMsg->content);
+			else
+				msg.Format(_T("  > [ %s ]"), pInfoMsg->evt);
+		}
+	}
+
+	LogMsg(msg);
+
+	info_msg::Destruct(pInfoMsg);
+}
+
+void LogMsg(const CString& msg)
+{
+	if(!g_pInfoList || !g_pInfoList->GetSafeHwnd())
+		return;
+
+	g_pInfoList->SetRedraw(FALSE);
+
+	int iCurIndex	= g_pInfoList->GetCurSel();
+
+	BOOL bFirst		= TRUE;
+	int iStart		= 0;
+	int iAdd		= 0;
+
+	while(true)
+	{
+		CString item = msg.Tokenize(_T("\r\n"), iStart);
+
+		if(iStart == -1)
+			break;
+
+		if(bFirst)
+			bFirst = FALSE;
+		else
+			item.Insert(0, _T("      | "));
+
+		g_pInfoList->AddString(item);
+		++iAdd;
+	}
+
+	int iCount		= g_pInfoList->GetCount();
+	BOOL bCurLast	= (iCurIndex == LB_ERR || iCurIndex + iAdd == iCount - 1);
+
+	int iDec = 0;
+	while(g_pInfoList->GetCount() > MAX_LOG_RECORD_LENGTH)
+	{
+		g_pInfoList->DeleteString(0);
+		++iDec;
+	}
+
+	if(bCurLast)
+	{
+		iCurIndex = iCount - iDec - 1;
+		g_pInfoList->SetCurSel(iCurIndex);
+	}
+	else if(iCurIndex < iDec)
+	{
+		iCurIndex = 0;
+		g_pInfoList->SetCurSel(iCurIndex);
+	}
+	else
+		iCurIndex = g_pInfoList->GetCurSel();
+
+	g_pInfoList->SetAnchorIndex(iCurIndex);
+	g_pInfoList->SetRedraw(TRUE);
+}
+
+CBufferPtr* GeneratePkgBuffer(DWORD seq, LPCTSTR lpszName, short age, LPCTSTR lpszDesc)
+{
+	USES_CONVERSION;
+
+	LPCSTR name = T2A((LPTSTR)lpszName);
+	LPCSTR desc = T2A((LPTSTR)lpszDesc);
+	int desc_len = (int)strlen(desc) + 1;
+	int body_len = offsetof(TPkgBody, desc) + desc_len;
+
+	TPkgBody* pBody = (TPkgBody*)_alloca(body_len);
+	memset(pBody, 0, body_len);
+
+	pBody->age = age;
+	strcpy(pBody->name, name);
+	strcpy(pBody->desc, desc);
+
+	TPkgHeader header;
+	header.seq = seq;
+	header.body_len = body_len;
+
+	return GeneratePkgBuffer(header, *pBody);
+}
+
+CBufferPtr* GeneratePkgBuffer(const TPkgHeader& header, const TPkgBody& body)
+{
+	int header_len	= sizeof(TPkgHeader);
+	int body_len	= header.body_len;
+	
+	CBufferPtr* pBuffer = new CBufferPtr(header_len + body_len);
+
+	memcpy(pBuffer->Ptr(), (BYTE*)&header, header_len);
+	memcpy(pBuffer->Ptr() + header_len, (BYTE*)&body, body_len);
+
+	return pBuffer;
+}
+
+#ifdef _SSL_SUPPORT
+
+#include "../../../Common/Src/FuncHelper.h"
+
+CString g_c_strCAPemCertFileOrPath;
+CString g_c_strPemCertFile;
+CString g_c_strPemKeyFile;
+
+CString g_s_strCAPemCertFileOrPath;
+CString g_s_strPemCertFile;
+CString g_s_strPemKeyFile;
+
+int g_c_iVerifyMode					= SSL_VM_PEER;
+LPCTSTR g_c_lpszCAPemCertFileOrPath	= _T("ssl-cert\\ca.crt");
+LPCTSTR g_c_lpszPemCertFile			= _T("ssl-cert\\client.cer");
+LPCTSTR g_c_lpszPemKeyFile			= _T("ssl-cert\\client.key");
+LPCTSTR g_c_lpszKeyPasswod			= _T("123456");
+
+int g_s_iVerifyMode					= SSL_VM_PEER | SSL_VM_FAIL_IF_NO_PEER_CERT;
+LPCTSTR g_s_lpszCAPemCertFileOrPath	= _T("ssl-cert\\ca.crt");
+LPCTSTR g_s_lpszPemCertFile			= _T("ssl-cert\\server.cer");
+LPCTSTR g_s_lpszPemKeyFile			= _T("ssl-cert\\server.key");
+LPCTSTR g_s_lpszKeyPasswod			= _T("123456");
+
+BOOL InitSSLParams();
+BOOL g_SSLParams = InitSSLParams();
+
+BOOL InitSSLParams()
+{
+	::SetCurrentPathToModulePath();
+
+	CString strPath;
+	::GetCurrentDirectory(MAX_PATH, strPath.GetBuffer(MAX_PATH));
+	strPath.ReleaseBuffer();
+	strPath += PATH_SEPARATOR_CHAR;
+
+	if(g_c_lpszPemCertFile)
+	{
+		g_c_strPemCertFile	= strPath + g_c_lpszPemCertFile;
+		g_c_lpszPemCertFile	= g_c_strPemCertFile;
+	}
+
+	if(g_c_lpszPemKeyFile)
+	{
+		g_c_strPemKeyFile	= strPath + g_c_lpszPemKeyFile;
+		g_c_lpszPemKeyFile	= g_c_strPemKeyFile;
+	}
+
+	if(g_c_lpszCAPemCertFileOrPath)
+	{
+		g_c_strCAPemCertFileOrPath	= strPath + g_c_lpszCAPemCertFileOrPath;
+		g_c_lpszCAPemCertFileOrPath	= g_c_strCAPemCertFileOrPath;
+	}
+
+	if(g_s_lpszPemCertFile)
+	{
+		g_s_strPemCertFile	= strPath + g_s_lpszPemCertFile;
+		g_s_lpszPemCertFile	= g_s_strPemCertFile;
+	}
+
+	if(g_s_lpszPemKeyFile)
+	{
+		g_s_strPemKeyFile	= strPath + g_s_lpszPemKeyFile;
+		g_s_lpszPemKeyFile	= g_s_strPemKeyFile;
+	}
+
+	if(g_s_lpszCAPemCertFileOrPath)
+	{
+		g_s_strCAPemCertFileOrPath	= strPath + g_s_lpszCAPemCertFileOrPath;
+		g_s_lpszCAPemCertFileOrPath	= g_s_strCAPemCertFileOrPath;
+	}
+
+	return TRUE;
+}
+
+#endif

+ 360 - 0
source/hook/hp-src/helper.h

@@ -0,0 +1,360 @@
+#pragma once
+
+#include "SocketInterface.h"
+#include "GeneralHelper.h"
+
+#define USER_INFO_MSG			(WM_USER + 100)
+#define MAX_LOG_RECORD_LENGTH	1000
+
+#define EVT_ON_SEND				_T("OnSend")
+#define EVT_ON_RECEIVE			_T("OnReceive")
+#define EVT_ON_CLOSE			_T("OnClose")
+#define EVT_ON_ERROR			_T("OnError")
+#define EVT_ON_PREPARE_CONNECT	_T("OnPrepareConnect")
+#define EVT_ON_PREPARE_LISTEN	_T("OnPrepareListen")
+#define EVT_ON_ACCEPT			_T("OnAccept")
+#define EVT_ON_CONNECT			_T("OnConnect")
+#define EVT_ON_HAND_SHAKE		_T("OnHandShake")
+#define EVT_ON_SHUTDOWN			_T("OnShutdown")
+#define EVT_ON_END_TEST			_T("END TEST")
+
+#define EVT_ON_MESSAGE_BEGIN	_T("OnMessageBegin")
+#define EVT_ON_REQUEST_LINE		_T("OnRequestLine")
+#define EVT_ON_STATUS_LINE		_T("OnStatusLine")
+#define EVT_ON_HEADER			_T("OnHeader")
+#define EVT_ON_HEADERS_COMPLETE	_T("OnHeadersComplete")
+#define EVT_ON_BODY				_T("OnBody")
+#define EVT_ON_CHUNK_HEADER		_T("OnChunkHeader")
+#define EVT_ON_CHUNK_COMPLETE	_T("OnChunkComplete")
+#define EVT_ON_MESSAGE_COMPLETE	_T("OnMessageComplete")
+#define EVT_ON_UPGRADE			_T("OnUpgrade")
+#define EVT_ON_PARSE_ERROR		_T("OnParseError")
+
+#define MAX_STUDIOID_LENGTH		37
+#define MAX_ACCOUNT_LENGTH		17
+#define MAX_PASSWORD_LENGTH		17
+
+enum EnAppState
+{
+	ST_STARTING, ST_STARTED, ST_CONNECTING, ST_CONNECTED, ST_STOPPING, ST_STOPPED
+};
+
+enum ProtocolCmd
+{
+	//----------------------------:common comand.type:  1~999----------------------------------------------------
+	CMD_HEART							= 1,		// 心跳包;
+	CMD_TOCHAT							= 2,		// 文字聊天;
+	CMD_FILEINFO_TRANSFER				= 3,		// 文件传输-文件信息;
+	CMD_FILECONT_TRANSFER				= 4,		// 文件传输-文件内容;
+	CMD_UPDATA							= 5,		// 有升级信息(用户终端每次登录时,请求检测是否有新版本可升级的信息);
+	CMD_DATABASEINFO					= 6,		// 向请求端返回数据库信息;
+	CMD_OHTER_INFO						= 999,		// 其他信息;
+
+
+	//------------------------C2L:consumer terminal to lyfz.service: 1000~1999------------------------------------
+	C2LCMD_REQ_LOGIN					= 1000,		// 用户终端请求登录利亚方舟服务端(外网ip+登录信息);
+	//C2LCMD_GET_DOG_DATA					= 1001,		// 利亚方舟获取用户终端机器加密狗数据信息;
+	C2LCMD_DOGINFO						= 1001,		// 用户终端向利亚方舟发送加密狗信息;
+	C2LCMD_GET_VAR						= 1002,		// 请求用户终端的版本号;
+	C2LCMD_DEAL_ILLEGAL					= 1003,		// 处理盗版、过期用户:停止用户终端工作、启用定时关机、程序文件自动删除等等操作命令;
+	C2LCMD_DEAL_SMS						= 1004,		// 利亚方舟服务端处理用户终端的短信发送工作;
+	C2LCMD_GET_DBINFO					= 1005,		// 利亚方舟服务端获取用户终端电脑数据库信息;
+
+	// .预留,若SQL数据库引擎未启用TCP/IP作为远程连接方式,需定义读写表的具体命令;(Jeff.100%的不建议使用这种方式获取数据,占用太多带宽和资源)
+	// .若要使用SQL,则只允许SQL的updata、insert、delete、drop……等命令,不允许使用select来返回查询到数据;
+
+	C2LCMD_OTHER_INFO					= 1999,     // 读其它信息;
+
+	//------------------------C2C:consumer client to consumer service: 2000~2999--------------------------------
+	C2CCMD_REQ_LOGIN					= 2000,     // 客户端请求登录服务器;
+	C2CCMD_REQ_LOGOUT					= 2001,		// 客户端注销;
+	C2CCMD_REQ_DOG_DATA					= 2002,     // 读软件狗数据;
+	C2CCMD_AUTO_UPDATA					= 2003,		// 服务端向所有客户发送自动数据更新命令;
+	C2CCMD_REQ_SERVER_VAR				= 2004,		// 请求服务端的版本号;
+	C2CCMD_GET_DBINFO					= 2005,		// 利亚方舟服务端获取用户终端电脑数据库信息;
+	C2CCMD_ORD_PHOTO_BAK				= 2006,		// 客户端端向备份程序发送订单相片重新备份命令(导片与备份存在写备份无法锁定现象,need to Notify);
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_ORDERINFO				= 2007,		// 开单;
+	C2CCMD_DEL_ORDERINFO				= 2008,		// 删除订单;
+	C2CCMD_MOD_ORDERINFO				= 2009,		// 修改订单;
+	C2CCMD_MOD_ORDERINFO2				= 2089,		// 修改订单;
+	C2CCMD_QRY_ORDERINFO				= 2010,		// 查询订单;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_PRODUCT					= 2012,		// 添加商品;
+	C2CCMD_MOD_PRODUCT					= 2013,		// 修改商品;
+	C2CCMD_DEL_PRODUCT					= 2014,		// 删除商品;
+	C2CCMD_QRY_PRODUCT					= 2015,		// 查询商品;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_CUSTOMERFROM				= 2016,		// 添加顾客来源;
+	C2CCMD_DEL_CUSTOMERFROM				= 2017,		// 删除顾客来源;
+	C2CCMD_MOD_CUSTOMERFROM				= 2018,		// 修改顾客来源;
+	C2CCMD_QRY_CUSTOMERFROM				= 2019,		// 查询顾客来源;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_CUSTOMERINFO				= 2020,		// 添加新顾客信息;
+	C2CCMD_DEL_CUSTOMERINFO				= 2021,		// 删除顾客信息;
+	C2CCMD_MOD_CUSTOMERINFO				= 2022,		// 修改顾客信息;
+	C2CCMD_QRY_CUSTOMERINFO				= 2023,		// 查询顾客信息;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_DEPARTMENT				= 2024,		// 新增部门信息;
+	C2CCMD_DEL_DEPARTMENT				= 2025,		// 删除部门信息;
+	C2CCMD_MOD_DEPARTMENT				= 2026,		// 修改部门信息;
+	C2CCMD_QRY_DEPARTMENT				= 2027,		// 查询部门信息;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_STAFFINFO				= 2028,		// 新增员工信息;
+	C2CCMD_DEL_STAFFINFO				= 2029,		// 删除员工信息;
+	C2CCMD_MOD_STAFFINFO				= 2030,		// 修改员工信息;
+	C2CCMD_QRY_STAFFINFO				= 2031,		// 查询员工信息;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_USERINFO					= 2032,		// 新增用户信息;
+	C2CCMD_DEL_USERINFO					= 2033,		// 删除用户信息;
+	C2CCMD_MOD_USERINFO					= 2034,		// 修改用户信息;
+	C2CCMD_QRY_USERINFO					= 2035,		// 查询用户信息;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_SCENERY					= 2036,		// 新增景点信息;
+	C2CCMD_DEL_SCENERY					= 2037,		// 删除景点信息;
+	C2CCMD_MOD_SCENERY					= 2038,		// 修改景点信息;
+	C2CCMD_QRY_SCENERY					= 2039,		// 查询景点信息;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_ORDERTYPE				= 2040,		// 新增订单类型信息;
+	C2CCMD_DEL_ORDERTYPE				= 2041,		// 删除订单类型信息;
+	C2CCMD_MOD_ORDERTYPE				= 2042,		// 修改订单类型信息;
+	C2CCMD_QRY_ORDERTYPE				= 2043,		// 查询订单类型信息;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_PRODUCTTYPE				= 2044,		// 添加商品类型;
+	C2CCMD_MOD_PRODUCTTYPE				= 2045,		// 修改商品类型;
+	C2CCMD_DEL_PRODUCTTYPE				= 2046,		// 删除商品类型;
+	C2CCMD_QRY_PRODUCTTYPE				= 2047,		// 查询商品类型;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_PACKAGETYPE				= 2048,		// 添加套系类型;
+	C2CCMD_DEL_PACKAGETYPE				= 2049,		// 修改套系类型;
+	C2CCMD_MOD_PACKAGETYPE				= 2050,		// 删除套系类型;
+	C2CCMD_QRY_PACKAGETYPE				= 2051,		// 查询套系类型;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_PACKAGEINFO				= 2052,		// 添加套系信息;
+	C2CCMD_DEL_PACKAGEINFO				= 2053,		// 删除套系信息;
+	C2CCMD_MOD_PACKAGEINFO				= 2054,		// 修改套系信息;
+	C2CCMD_QRY_PACKAGEINFO				= 2055,		// 查询套系信息;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_PACKAGEITEM				= 2056,		// 添加套系项目;
+	C2CCMD_DEL_PACKAGEITEM				= 2057,		// 修改套系项目;
+	C2CCMD_MOD_PACKAGEITEM				= 2058,		// 删除套系项目;
+	C2CCMD_QRY_PACKAGEITEM				= 2059,		// 查询套系项目;
+	C2CCMD_QRY_PACKAGEITEM_DETAIL		= 2072,		// 查询套系项目详情;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_ORDERPACKAGEITEM			= 2060,		// 添加套系项目;
+	C2CCMD_NEW_ORDERPACKAGEITEM2		= 2087,		// 添加订单套餐项目(删除以前的);
+	C2CCMD_DEL_ORDERPACKAGEITEM			= 2061,		// 修改套系项目;
+	C2CCMD_MOD_ORDERPACKAGEITEM			= 2062,		// 删除套系项目;
+	C2CCMD_QRY_ORDERPACKAGEITEM			= 2063,		// 查询套系项目;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_SYSCONFING				= 2064,		// 添加影楼配置信息;
+	C2CCMD_DEL_SYSCONFING				= 2065,		// 删除影楼配置信息;
+	C2CCMD_MOD_SYSCONFING				= 2066,		// 修改影楼配置信息;
+	C2CCMD_QRY_SYSCONFING				= 2067,		// 查询影楼配置信息;
+	//////////////////////////////////////////////////////////////////////////
+	C2CCMD_NEW_STUDIOINFO				= 2068,		// 添加影楼信息;
+	C2CCMD_DEL_STUDIOINFO				= 2069,		// 删除影楼信息;
+	C2CCMD_MOD_STUDIOINFO				= 2070,		// 修改影楼信息;
+	C2CCMD_QRY_STUDIOINFO				= 2071,		// 查询影楼信息;
+	// .预留,若SQL数据库引擎未启用TCP/IP作为远程连接方式,需定义读写表的具体命令;(Jeff.100%的不建议使用这种方式获取数据,占用太多带宽和资源)
+	// .若要使用SQL,则只允许SQL的updata、insert、delete、drop……等命令,不允许使用select来返回查询到数据;
+
+	//C2CCMD_QRY_PACKAGEITEM_DETAIL		= 2072,		// 查询套系项详情;
+	C2CCMD_QRY_PACKAGEITEM_VIEW			= 2073,		// 查询套系项详情;
+	C2CCMD_NEW_PACKAGEITEM_MUTI			= 2074,		// 多个项同时插入到套系中;	
+	C2CCMD_NEW_PACKAGEITEM2				= 2075,		// 添加套系项目;
+
+	// 订单景点信息;
+	C2CCMD_NEW_ORDERSCENERY				= 2076,		// 添加订单景点信息;
+	C2CCMD_NEW_ORDERSCENERY2			= 2088,		// 添加订单景点信息(删除以前的);
+	C2CCMD_DEL_ORDERSCENERY				= 2077,		// 删除订单景点信息,使用autoid;
+	C2CCMD_MOD_ORDERSCENERY				= 2078,		// 修改订单景点信息;
+	C2CCMD_QRY_ORDERSCENERY				= 2079,		// 查询订单景点信息;
+	C2CCMD_DEL_ORDERSCENERY2			= 2080,		// 删除订单景点信息,使用订单号+景点名;
+
+	// 订单商品信息;
+	C2CCMD_NEW_ORDERPRODUCT				= 2081,		// 添加订单商品信息;
+	C2CCMD_DEL_ORDERPRODUCT				= 2082,		// 删除订单商品信息;
+	C2CCMD_MOD_ORDERPRODUCT				= 2083,		// 修改订单商品信息;
+	C2CCMD_QRY_ORDERPRODUCT				= 2084,		// 查询订单商品信息;
+
+	// 获取订单序号;
+	C2CCMD_GET_ORDER_SERIALNUMBER		= 2085,		// 获取订单序号;
+	// 获取打印序号;
+	C2CCMD_GET_PRINT_SERIALNUMBER		= 2086,		// 获取打印序号;
+
+	C2CCMD_OTHER_INFO					= 2999,     // 读其它信息;
+};
+
+enum PackageFlag
+{
+	PACKAGE_ONESELF		= 0,			// 协议包-独立;
+	PACKAGE_MULTIPLE	= 1,			// 协议包-多个;
+};
+
+enum UserLogInStatus
+{
+	USER_LOGIN			= 1,				// 登录成功;
+	USER_PW_MISTAKE		= 2,				// 密码错误;
+	USER_HAVE_LOGIN		= 3,				// 用户已经登录;
+	USER_NULL			= 0					// 没有用户;
+};
+
+typedef struct __LogInUser__
+{
+	TCHAR				szStudioId[MAX_STUDIOID_LENGTH];		// 影楼Guid;
+	TCHAR				szAccount[MAX_ACCOUNT_LENGTH];			// 账号;
+	TCHAR				szPassword[MAX_PASSWORD_LENGTH];		// 密码;
+}LogInUser,*pLogInUser;
+
+
+#pragma pack(push,1)  
+// 协议头-勿更改;
+typedef struct __THEPROPACKAGE__
+{
+	byte				flag;				// 协议包类型标识;
+	short				nCmd;				// 协议携带的命令标识;
+	//unsigned int		nUnCompressLen;
+	unsigned int		nDataLen;			// 数据长度,除了头之外的数据;
+	unsigned int		nSubDataLen;		// 分包大小;
+	DWORD				dwReserve;			// 预留填0;
+	TCHAR				szStudioId[MAX_STUDIOID_LENGTH];		// 影楼Guid;
+	TCHAR				szAccount[MAX_ACCOUNT_LENGTH];			// 账号;
+	TCHAR				szPassword[MAX_PASSWORD_LENGTH];		// 密码;
+	//BYTE				byProp[5];
+	BYTE				byBody[2];			// 包数据;
+
+	__THEPROPACKAGE__(){
+		flag = PACKAGE_ONESELF;
+		nCmd = 0;
+		nDataLen = 0;
+		nSubDataLen = 0;
+		dwReserve = 0;
+		memset(byBody, 0, 2);
+		//memset(byProp, 0, 5);
+		memset(szStudioId, 0, sizeof(TCHAR)*MAX_STUDIOID_LENGTH);
+		memset(szAccount, 0, sizeof(TCHAR)*MAX_ACCOUNT_LENGTH);
+		memset(szPassword, 0, sizeof(TCHAR)*MAX_PASSWORD_LENGTH);
+	}
+}TheProPackage,*pTheProPackage;
+
+#pragma pack(pop) 
+
+
+struct info_msg
+{
+	LPCTSTR name;
+	CONNID connID;
+	LPCTSTR evt;
+	int contentLength;
+	LPCTSTR content;
+
+	static info_msg* Construct(CONNID dwConnID, LPCTSTR lpszEvent, int iContentLength = 0, LPCTSTR lpszContent = nullptr, LPCTSTR lpszName = nullptr);
+	static void Destruct(info_msg* pMsg);
+
+private:
+	info_msg(CONNID dwConnID, LPCTSTR lpszEvent, int iContentLength = 0, LPCTSTR lpszContent = nullptr, LPCTSTR lpszName = nullptr);
+	~info_msg();
+};
+
+struct TPkgHeader 
+{
+	DWORD seq;
+	int body_len;
+};
+
+struct TPkgBody 
+{
+	char name[30];
+	short age;
+	char desc[1];
+};
+
+struct TPkgInfo
+{
+	bool is_header;
+	int length;
+
+	TPkgInfo(bool header = true, int len = sizeof(TPkgHeader)) : is_header(header), length(len) {}
+	void Reset() {is_header = true, length = sizeof(TPkgHeader);}
+	~TPkgInfo() {}
+};
+
+CBufferPtr* GeneratePkgBuffer(DWORD seq, LPCTSTR lpszName, short age, LPCTSTR lpszDesc);
+CBufferPtr* GeneratePkgBuffer(const TPkgHeader& header, const TPkgBody& body);
+
+void SetMainWnd(CWnd* pWnd);
+void SetInfoList(CListBox* pInfoList);
+
+void LogServerStart(LPCTSTR lpszAddress, USHORT port, LPCTSTR lpszName = nullptr);
+void LogServerStartFail(DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName = nullptr);
+void LogServerStop(LPCTSTR lpszName = nullptr);
+void LogServerStopFail(DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName = nullptr);
+void LogClientStart(LPCTSTR lpszAddress, USHORT port, LPCTSTR lpszName = nullptr);
+void LogClientStarting(LPCTSTR lpszAddress, USHORT port, LPCTSTR lpszName = nullptr);
+void LogClientStartFail(DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName = nullptr);
+void LogClientStopping(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void LogClientStopFail(DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName = nullptr);
+void LogSend(CONNID dwConnID, LPCTSTR lpszContent, LPCTSTR lpszName = nullptr);
+void LogClientSendFail(int iSequence, int iSocketIndex, DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName = nullptr);
+void LogSendFail(CONNID dwConnID, DWORD code, LPCTSTR lpszDesc, LPCTSTR lpszName = nullptr);
+void LogDisconnect(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void LogDisconnectFail(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void LogRelease(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void LogReleaseFail(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void LogDetect(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void LogDetectFail(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void LogOnConnect(CONNID dwConnID, const CString& strAddress, USHORT usPort);
+void LogOnConnect2(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void LogOnHandShake2(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+
+void PostOnSend(CONNID dwConnID, const BYTE* pData, int iLength, LPCTSTR lpszName = nullptr);
+void PostOnReceive(CONNID dwConnID, const BYTE* pData, int iLength, LPCTSTR lpszName = nullptr);
+void PostOnReceiveCast(CONNID dwConnID, LPCTSTR lpszAddress, USHORT usPort, const BYTE* pData, int iLength, LPCTSTR lpszName = nullptr);
+void PostOnClose(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void PostOnError(CONNID dwConnID, int enOperation, int iErrorCode, LPCTSTR lpszName = nullptr);
+void PostOnAccept(CONNID dwConnID, LPCTSTR lpszAddress, USHORT usPort, BOOL bPass, LPCTSTR lpszName = nullptr);
+void PostOnAccept2(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void PostOnHandShake(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void PostOnPrepareListen(LPCTSTR lpszAddress, USHORT usPort, LPCTSTR lpszName = nullptr);
+void PostOnPrepareConnect(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void PostOnConnect(CONNID dwConnID, LPCTSTR lpszAddress, USHORT usPort, LPCTSTR lpszName = nullptr);
+void PostOnConnect2(CONNID dwConnID, LPCTSTR lpszAddress, USHORT usPort, LPCTSTR lpszName = nullptr);
+void PostOnConnect3(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void PostOnShutdown(LPCTSTR lpszName = nullptr);
+void PostServerStatics(const LONGLONG& llTotalSent, const LONGLONG& llTotalReceived, LPCTSTR lpszName = nullptr);
+void PostTimeConsuming(DWORD dwTickCount, LPCTSTR lpszName = nullptr);
+
+void PostOnMessageBegin(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void PostOnRequestLine(CONNID dwConnID, LPCSTR lpszMethod, USHORT usUrlFieldSet, LPCSTR lpszUrl, LPCTSTR lpszName = nullptr);
+void PostOnStatusLine(CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc, LPCTSTR lpszName = nullptr);
+void PostOnHeader(CONNID dwConnID, LPCSTR lpszHeaderName, LPCSTR lpszHeaderValue, LPCTSTR lpszName = nullptr);
+void PostOnHeadersComplete(CONNID dwConnID, LPCSTR lpszSummary, LPCTSTR lpszName = nullptr);
+void PostOnBody(CONNID dwConnID, const BYTE* pData, int iLength, LPCTSTR lpszName = nullptr);
+void PostOnChunkHeader(CONNID dwConnID, int iLength, LPCTSTR lpszName = nullptr);
+void PostOnChunkComplete(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void PostOnMessageComplete(CONNID dwConnID, LPCTSTR lpszName = nullptr);
+void PostOnUpgrade(CONNID dwConnID, EnHttpUpgradeType enUpgradeType, LPCTSTR lpszName = nullptr);
+void PostOnParseError(CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc, LPCTSTR lpszName = nullptr);
+
+void PostInfoMsg(info_msg* msg);
+void LogInfoMsg(info_msg* pInfoMsg);
+void LogMsg(const CString& msg);
+
+#ifdef _SSL_SUPPORT
+
+extern int g_c_iVerifyMode;
+extern BOOL g_c_bNeedClientVerification;
+extern LPCTSTR g_c_lpszCAPemCertFileOrPath;
+extern LPCTSTR g_c_lpszPemCertFile;
+extern LPCTSTR g_c_lpszPemKeyFile;
+extern LPCTSTR g_c_lpszKeyPasswod;
+
+extern int g_s_iVerifyMode;
+extern BOOL g_s_bNeedClientVerification;
+extern LPCTSTR g_s_lpszCAPemCertFileOrPath;
+extern LPCTSTR g_s_lpszPemCertFile;
+extern LPCTSTR g_s_lpszPemKeyFile;
+extern LPCTSTR g_s_lpszKeyPasswod;
+
+#endif

+ 5 - 0
source/hook/hp-src/http/Readme.txt

@@ -0,0 +1,5 @@
+修改记录:
+--------------------
+1、enum state 移动到 http_parser.h
+2、http_parser.h 禁止 4005 警告
+3、http_parser.c 禁止 4244 警告

+ 2395 - 0
source/hook/hp-src/http/http_parser.c

@@ -0,0 +1,2395 @@
+/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
+ *
+ * Additional changes are licensed under the same terms as NGINX and
+ * copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "http_parser.h"
+#include <assert.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+
+#ifndef ULLONG_MAX
+# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
+#endif
+
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+#ifndef BIT_AT
+# define BIT_AT(a, i)                                                \
+  (!!((unsigned int) (a)[(unsigned int) (i) >> 3] &                  \
+   (1 << ((unsigned int) (i) & 7))))
+#endif
+
+#ifndef ELEM_AT
+# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
+#endif
+
+#define SET_ERRNO(e)                                                 \
+do {                                                                 \
+  parser->http_errno = (e);                                          \
+} while(0)
+
+#define CURRENT_STATE() p_state
+#define UPDATE_STATE(V) p_state = (enum state) (V);
+#define RETURN(V)                                                    \
+do {                                                                 \
+  parser->state = CURRENT_STATE();                                   \
+  return (V);                                                        \
+} while (0);
+#define REEXECUTE()                                                  \
+  goto reexecute;                                                    \
+
+
+#ifdef __GNUC__
+# define LIKELY(X) __builtin_expect(!!(X), 1)
+# define UNLIKELY(X) __builtin_expect(!!(X), 0)
+#else
+# define LIKELY(X) (X)
+# define UNLIKELY(X) (X)
+#endif
+
+
+/* Run the notify callback FOR, returning ER if it fails */
+#define CALLBACK_NOTIFY_(FOR, ER)                                    \
+do {                                                                 \
+  assert(HTTP_PARSER_ERRNO(parser) == HPE_OK);                       \
+                                                                     \
+  if (LIKELY(settings->on_##FOR)) {                                  \
+    parser->state = CURRENT_STATE();                                 \
+    if (UNLIKELY(0 != settings->on_##FOR(parser))) {                 \
+      SET_ERRNO(HPE_CB_##FOR);                                       \
+    }                                                                \
+    UPDATE_STATE(parser->state);                                     \
+                                                                     \
+    /* We either errored above or got paused; get out */             \
+    if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {             \
+      return (ER);                                                   \
+    }                                                                \
+  }                                                                  \
+} while (0)
+
+/* Run the notify callback FOR and consume the current byte */
+#define CALLBACK_NOTIFY(FOR)            CALLBACK_NOTIFY_(FOR, p - data + 1)
+
+/* Run the notify callback FOR and don't consume the current byte */
+#define CALLBACK_NOTIFY_NOADVANCE(FOR)  CALLBACK_NOTIFY_(FOR, p - data)
+
+/* Run data callback FOR with LEN bytes, returning ER if it fails */
+#define CALLBACK_DATA_(FOR, LEN, ER)                                 \
+do {                                                                 \
+  assert(HTTP_PARSER_ERRNO(parser) == HPE_OK);                       \
+                                                                     \
+  if (FOR##_mark) {                                                  \
+    if (LIKELY(settings->on_##FOR)) {                                \
+      parser->state = CURRENT_STATE();                               \
+      if (UNLIKELY(0 !=                                              \
+                   settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \
+        SET_ERRNO(HPE_CB_##FOR);                                     \
+      }                                                              \
+      UPDATE_STATE(parser->state);                                   \
+                                                                     \
+      /* We either errored above or got paused; get out */           \
+      if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {           \
+        return (ER);                                                 \
+      }                                                              \
+    }                                                                \
+    FOR##_mark = NULL;                                               \
+  }                                                                  \
+} while (0)
+
+/* Run the data callback FOR and consume the current byte */
+#define CALLBACK_DATA(FOR)                                           \
+    CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
+
+/* Run the data callback FOR and don't consume the current byte */
+#define CALLBACK_DATA_NOADVANCE(FOR)                                 \
+    CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
+
+/* Set the mark FOR; non-destructive if mark is already set */
+#define MARK(FOR)                                                    \
+do {                                                                 \
+  if (!FOR##_mark) {                                                 \
+    FOR##_mark = p;                                                  \
+  }                                                                  \
+} while (0)
+
+/* Don't allow the total size of the HTTP headers (including the status
+ * line) to exceed HTTP_MAX_HEADER_SIZE.  This check is here to protect
+ * embedders against denial-of-service attacks where the attacker feeds
+ * us a never-ending header that the embedder keeps buffering.
+ *
+ * This check is arguably the responsibility of embedders but we're doing
+ * it on the embedder's behalf because most won't bother and this way we
+ * make the web a little safer.  HTTP_MAX_HEADER_SIZE is still far bigger
+ * than any reasonable request or response so this should never affect
+ * day-to-day operation.
+ */
+#define COUNT_HEADER_SIZE(V)                                         \
+do {                                                                 \
+  parser->nread += (V);                                              \
+  if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) {            \
+    SET_ERRNO(HPE_HEADER_OVERFLOW);                                  \
+    goto error;                                                      \
+  }                                                                  \
+} while (0)
+
+
+#define PROXY_CONNECTION "proxy-connection"
+#define CONNECTION "connection"
+#define CONTENT_LENGTH "content-length"
+#define TRANSFER_ENCODING "transfer-encoding"
+#define UPGRADE "upgrade"
+#define CHUNKED "chunked"
+#define KEEP_ALIVE "keep-alive"
+#define CLOSE "close"
+
+
+static const char *method_strings[] =
+  {
+#define XX(num, name, string) #string,
+  HTTP_METHOD_MAP(XX)
+#undef XX
+  };
+
+
+/* Tokens as defined by rfc 2616. Also lowercases them.
+ *        token       = 1*<any CHAR except CTLs or separators>
+ *     separators     = "(" | ")" | "<" | ">" | "@"
+ *                    | "," | ";" | ":" | "\" | <">
+ *                    | "/" | "[" | "]" | "?" | "="
+ *                    | "{" | "}" | SP | HT
+ */
+static const char tokens[256] = {
+/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
+        0,       0,       0,       0,       0,       0,       0,       0,
+/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
+        0,       0,       0,       0,       0,       0,       0,       0,
+/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
+        0,       0,       0,       0,       0,       0,       0,       0,
+/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
+        0,       0,       0,       0,       0,       0,       0,       0,
+/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
+        0,      '!',      0,      '#',     '$',     '%',     '&',    '\'',
+/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
+        0,       0,      '*',     '+',      0,      '-',     '.',      0,
+/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
+       '0',     '1',     '2',     '3',     '4',     '5',     '6',     '7',
+/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
+       '8',     '9',      0,       0,       0,       0,       0,       0,
+/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
+        0,      'a',     'b',     'c',     'd',     'e',     'f',     'g',
+/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
+       'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
+/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
+       'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
+/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
+       'x',     'y',     'z',      0,       0,       0,      '^',     '_',
+/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
+       '`',     'a',     'b',     'c',     'd',     'e',     'f',     'g',
+/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
+       'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
+/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
+       'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
+/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
+       'x',     'y',     'z',      0,      '|',      0,      '~',       0 };
+
+
+static const int8_t unhex[256] =
+  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+  , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
+  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+  };
+
+
+#if HTTP_PARSER_STRICT
+# define T(v) 0
+#else
+# define T(v) v
+#endif
+
+
+static const uint8_t normal_url_char[32] = {
+/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
+        0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,
+/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
+        0    | T(2)   |   0    |   0    | T(16)  |   0    |   0    |   0,
+/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
+        0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,
+/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
+        0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,
+/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
+        0    |   2    |   4    |   0    |   16   |   32   |   64   |  128,
+/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |   0,
+/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
+        1    |   2    |   4    |   8    |   16   |   32   |   64   |   0, };
+
+#undef T
+
+
+#define PARSING_HEADER(state) (state <= s_headers_done)
+
+
+enum header_states
+  { h_general = 0
+  , h_C
+  , h_CO
+  , h_CON
+
+  , h_matching_connection
+  , h_matching_proxy_connection
+  , h_matching_content_length
+  , h_matching_transfer_encoding
+  , h_matching_upgrade
+
+  , h_connection
+  , h_content_length
+  , h_transfer_encoding
+  , h_upgrade
+
+  , h_matching_transfer_encoding_chunked
+  , h_matching_connection_token_start
+  , h_matching_connection_keep_alive
+  , h_matching_connection_close
+  , h_matching_connection_upgrade
+  , h_matching_connection_token
+
+  , h_transfer_encoding_chunked
+  , h_connection_keep_alive
+  , h_connection_close
+  , h_connection_upgrade
+  };
+
+enum http_host_state
+  {
+    s_http_host_dead = 1
+  , s_http_userinfo_start
+  , s_http_userinfo
+  , s_http_host_start
+  , s_http_host_v6_start
+  , s_http_host
+  , s_http_host_v6
+  , s_http_host_v6_end
+  , s_http_host_v6_zone_start
+  , s_http_host_v6_zone
+  , s_http_host_port_start
+  , s_http_host_port
+};
+
+/* Macros for character classes; depends on strict-mode  */
+#define CR                  '\r'
+#define LF                  '\n'
+#define LOWER(c)            (unsigned char)(c | 0x20)
+#define IS_ALPHA(c)         (LOWER(c) >= 'a' && LOWER(c) <= 'z')
+#define IS_NUM(c)           ((c) >= '0' && (c) <= '9')
+#define IS_ALPHANUM(c)      (IS_ALPHA(c) || IS_NUM(c))
+#define IS_HEX(c)           (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
+#define IS_MARK(c)          ((c) == '-' || (c) == '_' || (c) == '.' || \
+  (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
+  (c) == ')')
+#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
+  (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
+  (c) == '$' || (c) == ',')
+
+#define STRICT_TOKEN(c)     (tokens[(unsigned char)c])
+
+#if HTTP_PARSER_STRICT
+#define TOKEN(c)            (tokens[(unsigned char)c])
+#define IS_URL_CHAR(c)      (BIT_AT(normal_url_char, (unsigned char)c))
+#define IS_HOST_CHAR(c)     (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
+#else
+#define TOKEN(c)            ((c == ' ') ? ' ' : tokens[(unsigned char)c])
+#define IS_URL_CHAR(c)                                                         \
+  (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
+#define IS_HOST_CHAR(c)                                                        \
+  (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
+#endif
+
+/**
+ * Verify that a char is a valid visible (printable) US-ASCII
+ * character or %x80-FF
+ **/
+#define IS_HEADER_CHAR(ch)                                                     \
+  (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127))
+
+#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
+
+
+#if HTTP_PARSER_STRICT
+# define STRICT_CHECK(cond)                                          \
+do {                                                                 \
+  if (cond) {                                                        \
+    SET_ERRNO(HPE_STRICT);                                           \
+    goto error;                                                      \
+  }                                                                  \
+} while (0)
+# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
+#else
+# define STRICT_CHECK(cond)
+# define NEW_MESSAGE() start_state
+#endif
+
+
+/* Map errno values to strings for human-readable output */
+#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
+static struct {
+  const char *name;
+  const char *description;
+} http_strerror_tab[] = {
+  HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)
+};
+#undef HTTP_STRERROR_GEN
+
+int http_message_needs_eof(const http_parser *parser);
+
+/* Our URL parser.
+ *
+ * This is designed to be shared by http_parser_execute() for URL validation,
+ * hence it has a state transition + byte-for-byte interface. In addition, it
+ * is meant to be embedded in http_parser_parse_url(), which does the dirty
+ * work of turning state transitions URL components for its API.
+ *
+ * This function should only be invoked with non-space characters. It is
+ * assumed that the caller cares about (and can detect) the transition between
+ * URL and non-URL states by looking for these.
+ */
+static enum state
+parse_url_char(enum state s, const char ch)
+{
+  if (ch == ' ' || ch == '\r' || ch == '\n') {
+    return s_dead;
+  }
+
+#if HTTP_PARSER_STRICT
+  if (ch == '\t' || ch == '\f') {
+    return s_dead;
+  }
+#endif
+
+  switch (s) {
+    case s_req_spaces_before_url:
+      /* Proxied requests are followed by scheme of an absolute URI (alpha).
+       * All methods except CONNECT are followed by '/' or '*'.
+       */
+
+      if (ch == '/' || ch == '*') {
+        return s_req_path;
+      }
+
+      if (IS_ALPHA(ch)) {
+        return s_req_schema;
+      }
+
+      break;
+
+    case s_req_schema:
+      if (IS_ALPHA(ch)) {
+        return s;
+      }
+
+      if (ch == ':') {
+        return s_req_schema_slash;
+      }
+
+      break;
+
+    case s_req_schema_slash:
+      if (ch == '/') {
+        return s_req_schema_slash_slash;
+      }
+
+      break;
+
+    case s_req_schema_slash_slash:
+      if (ch == '/') {
+        return s_req_server_start;
+      }
+
+      break;
+
+    case s_req_server_with_at:
+      if (ch == '@') {
+        return s_dead;
+      }
+
+    /* FALLTHROUGH */
+    case s_req_server_start:
+    case s_req_server:
+      if (ch == '/') {
+        return s_req_path;
+      }
+
+      if (ch == '?') {
+        return s_req_query_string_start;
+      }
+
+      if (ch == '@') {
+        return s_req_server_with_at;
+      }
+
+      if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
+        return s_req_server;
+      }
+
+      break;
+
+    case s_req_path:
+      if (IS_URL_CHAR(ch)) {
+        return s;
+      }
+
+      switch (ch) {
+        case '?':
+          return s_req_query_string_start;
+
+        case '#':
+          return s_req_fragment_start;
+      }
+
+      break;
+
+    case s_req_query_string_start:
+    case s_req_query_string:
+      if (IS_URL_CHAR(ch)) {
+        return s_req_query_string;
+      }
+
+      switch (ch) {
+        case '?':
+          /* allow extra '?' in query string */
+          return s_req_query_string;
+
+        case '#':
+          return s_req_fragment_start;
+      }
+
+      break;
+
+    case s_req_fragment_start:
+      if (IS_URL_CHAR(ch)) {
+        return s_req_fragment;
+      }
+
+      switch (ch) {
+        case '?':
+          return s_req_fragment;
+
+        case '#':
+          return s;
+      }
+
+      break;
+
+    case s_req_fragment:
+      if (IS_URL_CHAR(ch)) {
+        return s;
+      }
+
+      switch (ch) {
+        case '?':
+        case '#':
+          return s;
+      }
+
+      break;
+
+    default:
+      break;
+  }
+
+  /* We should never fall out of the switch above unless there's an error */
+  return s_dead;
+}
+
+size_t http_parser_execute (http_parser *parser,
+                            const http_parser_settings *settings,
+                            const char *data,
+                            size_t len)
+{
+  char c, ch;
+  int8_t unhex_val;
+  const char *p = data;
+  const char *header_field_mark = 0;
+  const char *header_value_mark = 0;
+  const char *url_mark = 0;
+  const char *body_mark = 0;
+  const char *status_mark = 0;
+  enum state p_state = (enum state) parser->state;
+  const unsigned int lenient = parser->lenient_http_headers;
+
+  /* We're in an error state. Don't bother doing anything. */
+  if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
+    return 0;
+  }
+
+  if (len == 0) {
+    switch (CURRENT_STATE()) {
+      case s_body_identity_eof:
+        /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if
+         * we got paused.
+         */
+        CALLBACK_NOTIFY_NOADVANCE(message_complete);
+        return 0;
+
+      case s_dead:
+      case s_start_req_or_res:
+      case s_start_res:
+      case s_start_req:
+        return 0;
+
+      default:
+        SET_ERRNO(HPE_INVALID_EOF_STATE);
+        return 1;
+    }
+  }
+
+
+  if (CURRENT_STATE() == s_header_field)
+    header_field_mark = data;
+  if (CURRENT_STATE() == s_header_value)
+    header_value_mark = data;
+  switch (CURRENT_STATE()) {
+  case s_req_path:
+  case s_req_schema:
+  case s_req_schema_slash:
+  case s_req_schema_slash_slash:
+  case s_req_server_start:
+  case s_req_server:
+  case s_req_server_with_at:
+  case s_req_query_string_start:
+  case s_req_query_string:
+  case s_req_fragment_start:
+  case s_req_fragment:
+    url_mark = data;
+    break;
+  case s_res_status:
+    status_mark = data;
+    break;
+  default:
+    break;
+  }
+
+  for (p=data; p != data + len; p++) {
+    ch = *p;
+
+    if (PARSING_HEADER(CURRENT_STATE()))
+      COUNT_HEADER_SIZE(1);
+
+reexecute:
+    switch (CURRENT_STATE()) {
+
+      case s_dead:
+        /* this state is used after a 'Connection: close' message
+         * the parser will error out if it reads another message
+         */
+        if (LIKELY(ch == CR || ch == LF))
+          break;
+
+        SET_ERRNO(HPE_CLOSED_CONNECTION);
+        goto error;
+
+      case s_start_req_or_res:
+      {
+        if (ch == CR || ch == LF)
+          break;
+        parser->flags = 0;
+        parser->content_length = ULLONG_MAX;
+
+        if (ch == 'H') {
+          UPDATE_STATE(s_res_or_resp_H);
+
+          CALLBACK_NOTIFY(message_begin);
+        } else {
+          parser->type = HTTP_REQUEST;
+          UPDATE_STATE(s_start_req);
+          REEXECUTE();
+        }
+
+        break;
+      }
+
+      case s_res_or_resp_H:
+        if (ch == 'T') {
+          parser->type = HTTP_RESPONSE;
+          UPDATE_STATE(s_res_HT);
+        } else {
+          if (UNLIKELY(ch != 'E')) {
+            SET_ERRNO(HPE_INVALID_CONSTANT);
+            goto error;
+          }
+
+          parser->type = HTTP_REQUEST;
+          parser->method = HTTP_HEAD;
+          parser->index = 2;
+          UPDATE_STATE(s_req_method);
+        }
+        break;
+
+      case s_start_res:
+      {
+        parser->flags = 0;
+        parser->content_length = ULLONG_MAX;
+
+        switch (ch) {
+          case 'H':
+            UPDATE_STATE(s_res_H);
+            break;
+
+          case CR:
+          case LF:
+            break;
+
+          default:
+            SET_ERRNO(HPE_INVALID_CONSTANT);
+            goto error;
+        }
+
+        CALLBACK_NOTIFY(message_begin);
+        break;
+      }
+
+      case s_res_H:
+        STRICT_CHECK(ch != 'T');
+        UPDATE_STATE(s_res_HT);
+        break;
+
+      case s_res_HT:
+        STRICT_CHECK(ch != 'T');
+        UPDATE_STATE(s_res_HTT);
+        break;
+
+      case s_res_HTT:
+        STRICT_CHECK(ch != 'P');
+        UPDATE_STATE(s_res_HTTP);
+        break;
+
+      case s_res_HTTP:
+        STRICT_CHECK(ch != '/');
+        UPDATE_STATE(s_res_first_http_major);
+        break;
+
+      case s_res_first_http_major:
+        if (UNLIKELY(ch < '0' || ch > '9')) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        parser->http_major = ch - '0';
+        UPDATE_STATE(s_res_http_major);
+        break;
+
+      /* major HTTP version or dot */
+      case s_res_http_major:
+      {
+        if (ch == '.') {
+          UPDATE_STATE(s_res_first_http_minor);
+          break;
+        }
+
+        if (!IS_NUM(ch)) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        parser->http_major *= 10;
+        parser->http_major += ch - '0';
+
+        if (UNLIKELY(parser->http_major > 999)) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        break;
+      }
+
+      /* first digit of minor HTTP version */
+      case s_res_first_http_minor:
+        if (UNLIKELY(!IS_NUM(ch))) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        parser->http_minor = ch - '0';
+        UPDATE_STATE(s_res_http_minor);
+        break;
+
+      /* minor HTTP version or end of request line */
+      case s_res_http_minor:
+      {
+        if (ch == ' ') {
+          UPDATE_STATE(s_res_first_status_code);
+          break;
+        }
+
+        if (UNLIKELY(!IS_NUM(ch))) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        parser->http_minor *= 10;
+        parser->http_minor += ch - '0';
+
+        if (UNLIKELY(parser->http_minor > 999)) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        break;
+      }
+
+      case s_res_first_status_code:
+      {
+        if (!IS_NUM(ch)) {
+          if (ch == ' ') {
+            break;
+          }
+
+          SET_ERRNO(HPE_INVALID_STATUS);
+          goto error;
+        }
+        parser->status_code = ch - '0';
+        UPDATE_STATE(s_res_status_code);
+        break;
+      }
+
+      case s_res_status_code:
+      {
+        if (!IS_NUM(ch)) {
+          switch (ch) {
+            case ' ':
+              UPDATE_STATE(s_res_status_start);
+              break;
+            case CR:
+              UPDATE_STATE(s_res_line_almost_done);
+              break;
+            case LF:
+              UPDATE_STATE(s_header_field_start);
+              break;
+            default:
+              SET_ERRNO(HPE_INVALID_STATUS);
+              goto error;
+          }
+          break;
+        }
+
+        parser->status_code *= 10;
+        parser->status_code += ch - '0';
+
+        if (UNLIKELY(parser->status_code > 999)) {
+          SET_ERRNO(HPE_INVALID_STATUS);
+          goto error;
+        }
+
+        break;
+      }
+
+      case s_res_status_start:
+      {
+        if (ch == CR) {
+          UPDATE_STATE(s_res_line_almost_done);
+          break;
+        }
+
+        if (ch == LF) {
+          UPDATE_STATE(s_header_field_start);
+          break;
+        }
+
+        MARK(status);
+        UPDATE_STATE(s_res_status);
+        parser->index = 0;
+        break;
+      }
+
+      case s_res_status:
+        if (ch == CR) {
+          UPDATE_STATE(s_res_line_almost_done);
+          CALLBACK_DATA(status);
+          break;
+        }
+
+        if (ch == LF) {
+          UPDATE_STATE(s_header_field_start);
+          CALLBACK_DATA(status);
+          break;
+        }
+
+        break;
+
+      case s_res_line_almost_done:
+        STRICT_CHECK(ch != LF);
+        UPDATE_STATE(s_header_field_start);
+        break;
+
+      case s_start_req:
+      {
+        if (ch == CR || ch == LF)
+          break;
+        parser->flags = 0;
+        parser->content_length = ULLONG_MAX;
+
+        if (UNLIKELY(!IS_ALPHA(ch))) {
+          SET_ERRNO(HPE_INVALID_METHOD);
+          goto error;
+        }
+
+        parser->method = (enum http_method) 0;
+        parser->index = 1;
+        switch (ch) {
+          case 'A': parser->method = HTTP_ACL; break;
+          case 'B': parser->method = HTTP_BIND; break;
+          case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
+          case 'D': parser->method = HTTP_DELETE; break;
+          case 'G': parser->method = HTTP_GET; break;
+          case 'H': parser->method = HTTP_HEAD; break;
+          case 'L': parser->method = HTTP_LOCK; /* or LINK */ break;
+          case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
+          case 'N': parser->method = HTTP_NOTIFY; break;
+          case 'O': parser->method = HTTP_OPTIONS; break;
+          case 'P': parser->method = HTTP_POST;
+            /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
+            break;
+          case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break;
+          case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;
+          case 'T': parser->method = HTTP_TRACE; break;
+          case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
+          default:
+            SET_ERRNO(HPE_INVALID_METHOD);
+            goto error;
+        }
+        UPDATE_STATE(s_req_method);
+
+        CALLBACK_NOTIFY(message_begin);
+
+        break;
+      }
+
+      case s_req_method:
+      {
+        const char *matcher;
+        if (UNLIKELY(ch == '\0')) {
+          SET_ERRNO(HPE_INVALID_METHOD);
+          goto error;
+        }
+
+        matcher = method_strings[parser->method];
+        if (ch == ' ' && matcher[parser->index] == '\0') {
+          UPDATE_STATE(s_req_spaces_before_url);
+        } else if (ch == matcher[parser->index]) {
+          ; /* nada */
+        } else if (IS_ALPHA(ch)) {
+
+          switch (parser->method << 16 | parser->index << 8 | ch) {
+#define XX(meth, pos, ch, new_meth) \
+            case (HTTP_##meth << 16 | pos << 8 | ch): \
+              parser->method = HTTP_##new_meth; break;
+
+            XX(POST,      1, 'U', PUT)
+            XX(POST,      1, 'A', PATCH)
+            XX(CONNECT,   1, 'H', CHECKOUT)
+            XX(CONNECT,   2, 'P', COPY)
+            XX(MKCOL,     1, 'O', MOVE)
+            XX(MKCOL,     1, 'E', MERGE)
+            XX(MKCOL,     2, 'A', MKACTIVITY)
+            XX(MKCOL,     3, 'A', MKCALENDAR)
+            XX(SUBSCRIBE, 1, 'E', SEARCH)
+            XX(REPORT,    2, 'B', REBIND)
+            XX(POST,      1, 'R', PROPFIND)
+            XX(PROPFIND,  4, 'P', PROPPATCH)
+            XX(PUT,       2, 'R', PURGE)
+            XX(LOCK,      1, 'I', LINK)
+            XX(UNLOCK,    2, 'S', UNSUBSCRIBE)
+            XX(UNLOCK,    2, 'B', UNBIND)
+            XX(UNLOCK,    3, 'I', UNLINK)
+#undef XX
+
+            default:
+              SET_ERRNO(HPE_INVALID_METHOD);
+              goto error;
+          }
+        } else if (ch == '-' &&
+                   parser->index == 1 &&
+                   parser->method == HTTP_MKCOL) {
+          parser->method = HTTP_MSEARCH;
+        } else {
+          SET_ERRNO(HPE_INVALID_METHOD);
+          goto error;
+        }
+
+        ++parser->index;
+        break;
+      }
+
+      case s_req_spaces_before_url:
+      {
+        if (ch == ' ') break;
+
+        MARK(url);
+        if (parser->method == HTTP_CONNECT) {
+          UPDATE_STATE(s_req_server_start);
+        }
+
+        UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
+        if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+          SET_ERRNO(HPE_INVALID_URL);
+          goto error;
+        }
+
+        break;
+      }
+
+      case s_req_schema:
+      case s_req_schema_slash:
+      case s_req_schema_slash_slash:
+      case s_req_server_start:
+      {
+        switch (ch) {
+          /* No whitespace allowed here */
+          case ' ':
+          case CR:
+          case LF:
+            SET_ERRNO(HPE_INVALID_URL);
+            goto error;
+          default:
+            UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
+            if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+              SET_ERRNO(HPE_INVALID_URL);
+              goto error;
+            }
+        }
+
+        break;
+      }
+
+      case s_req_server:
+      case s_req_server_with_at:
+      case s_req_path:
+      case s_req_query_string_start:
+      case s_req_query_string:
+      case s_req_fragment_start:
+      case s_req_fragment:
+      {
+        switch (ch) {
+          case ' ':
+            UPDATE_STATE(s_req_http_start);
+            CALLBACK_DATA(url);
+            break;
+          case CR:
+          case LF:
+            parser->http_major = 0;
+            parser->http_minor = 9;
+            UPDATE_STATE((ch == CR) ?
+              s_req_line_almost_done :
+              s_header_field_start);
+            CALLBACK_DATA(url);
+            break;
+          default:
+            UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
+            if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+              SET_ERRNO(HPE_INVALID_URL);
+              goto error;
+            }
+        }
+        break;
+      }
+
+      case s_req_http_start:
+        switch (ch) {
+          case 'H':
+            UPDATE_STATE(s_req_http_H);
+            break;
+          case ' ':
+            break;
+          default:
+            SET_ERRNO(HPE_INVALID_CONSTANT);
+            goto error;
+        }
+        break;
+
+      case s_req_http_H:
+        STRICT_CHECK(ch != 'T');
+        UPDATE_STATE(s_req_http_HT);
+        break;
+
+      case s_req_http_HT:
+        STRICT_CHECK(ch != 'T');
+        UPDATE_STATE(s_req_http_HTT);
+        break;
+
+      case s_req_http_HTT:
+        STRICT_CHECK(ch != 'P');
+        UPDATE_STATE(s_req_http_HTTP);
+        break;
+
+      case s_req_http_HTTP:
+        STRICT_CHECK(ch != '/');
+        UPDATE_STATE(s_req_first_http_major);
+        break;
+
+      /* first digit of major HTTP version */
+      case s_req_first_http_major:
+        if (UNLIKELY(ch < '1' || ch > '9')) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        parser->http_major = ch - '0';
+        UPDATE_STATE(s_req_http_major);
+        break;
+
+      /* major HTTP version or dot */
+      case s_req_http_major:
+      {
+        if (ch == '.') {
+          UPDATE_STATE(s_req_first_http_minor);
+          break;
+        }
+
+        if (UNLIKELY(!IS_NUM(ch))) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        parser->http_major *= 10;
+        parser->http_major += ch - '0';
+
+        if (UNLIKELY(parser->http_major > 999)) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        break;
+      }
+
+      /* first digit of minor HTTP version */
+      case s_req_first_http_minor:
+        if (UNLIKELY(!IS_NUM(ch))) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        parser->http_minor = ch - '0';
+        UPDATE_STATE(s_req_http_minor);
+        break;
+
+      /* minor HTTP version or end of request line */
+      case s_req_http_minor:
+      {
+        if (ch == CR) {
+          UPDATE_STATE(s_req_line_almost_done);
+          break;
+        }
+
+        if (ch == LF) {
+          UPDATE_STATE(s_header_field_start);
+          break;
+        }
+
+        /* XXX allow spaces after digit? */
+
+        if (UNLIKELY(!IS_NUM(ch))) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        parser->http_minor *= 10;
+        parser->http_minor += ch - '0';
+
+        if (UNLIKELY(parser->http_minor > 999)) {
+          SET_ERRNO(HPE_INVALID_VERSION);
+          goto error;
+        }
+
+        break;
+      }
+
+      /* end of request line */
+      case s_req_line_almost_done:
+      {
+        if (UNLIKELY(ch != LF)) {
+          SET_ERRNO(HPE_LF_EXPECTED);
+          goto error;
+        }
+
+        UPDATE_STATE(s_header_field_start);
+        break;
+      }
+
+      case s_header_field_start:
+      {
+        if (ch == CR) {
+          UPDATE_STATE(s_headers_almost_done);
+          break;
+        }
+
+        if (ch == LF) {
+          /* they might be just sending \n instead of \r\n so this would be
+           * the second \n to denote the end of headers*/
+          UPDATE_STATE(s_headers_almost_done);
+          REEXECUTE();
+        }
+
+        c = TOKEN(ch);
+
+        if (UNLIKELY(!c)) {
+          SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
+          goto error;
+        }
+
+        MARK(header_field);
+
+        parser->index = 0;
+        UPDATE_STATE(s_header_field);
+
+        switch (c) {
+          case 'c':
+            parser->header_state = h_C;
+            break;
+
+          case 'p':
+            parser->header_state = h_matching_proxy_connection;
+            break;
+
+          case 't':
+            parser->header_state = h_matching_transfer_encoding;
+            break;
+
+          case 'u':
+            parser->header_state = h_matching_upgrade;
+            break;
+
+          default:
+            parser->header_state = h_general;
+            break;
+        }
+        break;
+      }
+
+      case s_header_field:
+      {
+        const char* start = p;
+        for (; p != data + len; p++) {
+          ch = *p;
+          c = TOKEN(ch);
+
+          if (!c)
+            break;
+
+          switch (parser->header_state) {
+            case h_general:
+              break;
+
+            case h_C:
+              parser->index++;
+              parser->header_state = (c == 'o' ? h_CO : h_general);
+              break;
+
+            case h_CO:
+              parser->index++;
+              parser->header_state = (c == 'n' ? h_CON : h_general);
+              break;
+
+            case h_CON:
+              parser->index++;
+              switch (c) {
+                case 'n':
+                  parser->header_state = h_matching_connection;
+                  break;
+                case 't':
+                  parser->header_state = h_matching_content_length;
+                  break;
+                default:
+                  parser->header_state = h_general;
+                  break;
+              }
+              break;
+
+            /* connection */
+
+            case h_matching_connection:
+              parser->index++;
+              if (parser->index > sizeof(CONNECTION)-1
+                  || c != CONNECTION[parser->index]) {
+                parser->header_state = h_general;
+              } else if (parser->index == sizeof(CONNECTION)-2) {
+                parser->header_state = h_connection;
+              }
+              break;
+
+            /* proxy-connection */
+
+            case h_matching_proxy_connection:
+              parser->index++;
+              if (parser->index > sizeof(PROXY_CONNECTION)-1
+                  || c != PROXY_CONNECTION[parser->index]) {
+                parser->header_state = h_general;
+              } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {
+                parser->header_state = h_connection;
+              }
+              break;
+
+            /* content-length */
+
+            case h_matching_content_length:
+              parser->index++;
+              if (parser->index > sizeof(CONTENT_LENGTH)-1
+                  || c != CONTENT_LENGTH[parser->index]) {
+                parser->header_state = h_general;
+              } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
+                parser->header_state = h_content_length;
+              }
+              break;
+
+            /* transfer-encoding */
+
+            case h_matching_transfer_encoding:
+              parser->index++;
+              if (parser->index > sizeof(TRANSFER_ENCODING)-1
+                  || c != TRANSFER_ENCODING[parser->index]) {
+                parser->header_state = h_general;
+              } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
+                parser->header_state = h_transfer_encoding;
+              }
+              break;
+
+            /* upgrade */
+
+            case h_matching_upgrade:
+              parser->index++;
+              if (parser->index > sizeof(UPGRADE)-1
+                  || c != UPGRADE[parser->index]) {
+                parser->header_state = h_general;
+              } else if (parser->index == sizeof(UPGRADE)-2) {
+                parser->header_state = h_upgrade;
+              }
+              break;
+
+            case h_connection:
+            case h_content_length:
+            case h_transfer_encoding:
+            case h_upgrade:
+              if (ch != ' ') parser->header_state = h_general;
+              break;
+
+            default:
+              assert(0 && "Unknown header_state");
+              break;
+          }
+        }
+
+        COUNT_HEADER_SIZE(p - start);
+
+        if (p == data + len) {
+          --p;
+          break;
+        }
+
+        if (ch == ':') {
+          UPDATE_STATE(s_header_value_discard_ws);
+          CALLBACK_DATA(header_field);
+          break;
+        }
+
+        SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
+        goto error;
+      }
+
+      case s_header_value_discard_ws:
+        if (ch == ' ' || ch == '\t') break;
+
+        if (ch == CR) {
+          UPDATE_STATE(s_header_value_discard_ws_almost_done);
+          break;
+        }
+
+        if (ch == LF) {
+          UPDATE_STATE(s_header_value_discard_lws);
+          break;
+        }
+
+        /* FALLTHROUGH */
+
+      case s_header_value_start:
+      {
+        MARK(header_value);
+
+        UPDATE_STATE(s_header_value);
+        parser->index = 0;
+
+        c = LOWER(ch);
+
+        switch (parser->header_state) {
+          case h_upgrade:
+            parser->flags |= F_UPGRADE;
+            parser->header_state = h_general;
+            break;
+
+          case h_transfer_encoding:
+            /* looking for 'Transfer-Encoding: chunked' */
+            if ('c' == c) {
+              parser->header_state = h_matching_transfer_encoding_chunked;
+            } else {
+              parser->header_state = h_general;
+            }
+            break;
+
+          case h_content_length:
+            if (UNLIKELY(!IS_NUM(ch))) {
+              SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+              goto error;
+            }
+
+            if (parser->flags & F_CONTENTLENGTH) {
+              SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
+              goto error;
+            }
+
+            parser->flags |= F_CONTENTLENGTH;
+            parser->content_length = ch - '0';
+            break;
+
+          case h_connection:
+            /* looking for 'Connection: keep-alive' */
+            if (c == 'k') {
+              parser->header_state = h_matching_connection_keep_alive;
+            /* looking for 'Connection: close' */
+            } else if (c == 'c') {
+              parser->header_state = h_matching_connection_close;
+            } else if (c == 'u') {
+              parser->header_state = h_matching_connection_upgrade;
+            } else {
+              parser->header_state = h_matching_connection_token;
+            }
+            break;
+
+          /* Multi-value `Connection` header */
+          case h_matching_connection_token_start:
+            break;
+
+          default:
+            parser->header_state = h_general;
+            break;
+        }
+        break;
+      }
+
+      case s_header_value:
+      {
+        const char* start = p;
+        enum header_states h_state = (enum header_states) parser->header_state;
+        for (; p != data + len; p++) {
+          ch = *p;
+          if (ch == CR) {
+            UPDATE_STATE(s_header_almost_done);
+            parser->header_state = h_state;
+            CALLBACK_DATA(header_value);
+            break;
+          }
+
+          if (ch == LF) {
+            UPDATE_STATE(s_header_almost_done);
+            COUNT_HEADER_SIZE(p - start);
+            parser->header_state = h_state;
+            CALLBACK_DATA_NOADVANCE(header_value);
+            REEXECUTE();
+          }
+
+          if (!lenient && !IS_HEADER_CHAR(ch)) {
+            SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
+            goto error;
+          }
+
+          c = LOWER(ch);
+
+          switch (h_state) {
+            case h_general:
+            {
+              const char* p_cr;
+              const char* p_lf;
+              size_t limit = data + len - p;
+
+              limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
+
+              p_cr = (const char*) memchr(p, CR, limit);
+              p_lf = (const char*) memchr(p, LF, limit);
+              if (p_cr != NULL) {
+                if (p_lf != NULL && p_cr >= p_lf)
+                  p = p_lf;
+                else
+                  p = p_cr;
+              } else if (UNLIKELY(p_lf != NULL)) {
+                p = p_lf;
+              } else {
+                p = data + len;
+              }
+              --p;
+
+              break;
+            }
+
+            case h_connection:
+            case h_transfer_encoding:
+              assert(0 && "Shouldn't get here.");
+              break;
+
+            case h_content_length:
+            {
+              uint64_t t;
+
+              if (ch == ' ') break;
+
+              if (UNLIKELY(!IS_NUM(ch))) {
+                SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+                parser->header_state = h_state;
+                goto error;
+              }
+
+              t = parser->content_length;
+              t *= 10;
+              t += ch - '0';
+
+              /* Overflow? Test against a conservative limit for simplicity. */
+              if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {
+                SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+                parser->header_state = h_state;
+                goto error;
+              }
+
+              parser->content_length = t;
+              break;
+            }
+
+            /* Transfer-Encoding: chunked */
+            case h_matching_transfer_encoding_chunked:
+              parser->index++;
+              if (parser->index > sizeof(CHUNKED)-1
+                  || c != CHUNKED[parser->index]) {
+                h_state = h_general;
+              } else if (parser->index == sizeof(CHUNKED)-2) {
+                h_state = h_transfer_encoding_chunked;
+              }
+              break;
+
+            case h_matching_connection_token_start:
+              /* looking for 'Connection: keep-alive' */
+              if (c == 'k') {
+                h_state = h_matching_connection_keep_alive;
+              /* looking for 'Connection: close' */
+              } else if (c == 'c') {
+                h_state = h_matching_connection_close;
+              } else if (c == 'u') {
+                h_state = h_matching_connection_upgrade;
+              } else if (STRICT_TOKEN(c)) {
+                h_state = h_matching_connection_token;
+              } else if (c == ' ' || c == '\t') {
+                /* Skip lws */
+              } else {
+                h_state = h_general;
+              }
+              break;
+
+            /* looking for 'Connection: keep-alive' */
+            case h_matching_connection_keep_alive:
+              parser->index++;
+              if (parser->index > sizeof(KEEP_ALIVE)-1
+                  || c != KEEP_ALIVE[parser->index]) {
+                h_state = h_matching_connection_token;
+              } else if (parser->index == sizeof(KEEP_ALIVE)-2) {
+                h_state = h_connection_keep_alive;
+              }
+              break;
+
+            /* looking for 'Connection: close' */
+            case h_matching_connection_close:
+              parser->index++;
+              if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {
+                h_state = h_matching_connection_token;
+              } else if (parser->index == sizeof(CLOSE)-2) {
+                h_state = h_connection_close;
+              }
+              break;
+
+            /* looking for 'Connection: upgrade' */
+            case h_matching_connection_upgrade:
+              parser->index++;
+              if (parser->index > sizeof(UPGRADE) - 1 ||
+                  c != UPGRADE[parser->index]) {
+                h_state = h_matching_connection_token;
+              } else if (parser->index == sizeof(UPGRADE)-2) {
+                h_state = h_connection_upgrade;
+              }
+              break;
+
+            case h_matching_connection_token:
+              if (ch == ',') {
+                h_state = h_matching_connection_token_start;
+                parser->index = 0;
+              }
+              break;
+
+            case h_transfer_encoding_chunked:
+              if (ch != ' ') h_state = h_general;
+              break;
+
+            case h_connection_keep_alive:
+            case h_connection_close:
+            case h_connection_upgrade:
+              if (ch == ',') {
+                if (h_state == h_connection_keep_alive) {
+                  parser->flags |= F_CONNECTION_KEEP_ALIVE;
+                } else if (h_state == h_connection_close) {
+                  parser->flags |= F_CONNECTION_CLOSE;
+                } else if (h_state == h_connection_upgrade) {
+                  parser->flags |= F_CONNECTION_UPGRADE;
+                }
+                h_state = h_matching_connection_token_start;
+                parser->index = 0;
+              } else if (ch != ' ') {
+                h_state = h_matching_connection_token;
+              }
+              break;
+
+            default:
+              UPDATE_STATE(s_header_value);
+              h_state = h_general;
+              break;
+          }
+        }
+        parser->header_state = h_state;
+
+        COUNT_HEADER_SIZE(p - start);
+
+        if (p == data + len)
+          --p;
+        break;
+      }
+
+      case s_header_almost_done:
+      {
+        if (UNLIKELY(ch != LF)) {
+          SET_ERRNO(HPE_LF_EXPECTED);
+          goto error;
+        }
+
+        UPDATE_STATE(s_header_value_lws);
+        break;
+      }
+
+      case s_header_value_lws:
+      {
+        if (ch == ' ' || ch == '\t') {
+          UPDATE_STATE(s_header_value_start);
+          REEXECUTE();
+        }
+
+        /* finished the header */
+        switch (parser->header_state) {
+          case h_connection_keep_alive:
+            parser->flags |= F_CONNECTION_KEEP_ALIVE;
+            break;
+          case h_connection_close:
+            parser->flags |= F_CONNECTION_CLOSE;
+            break;
+          case h_transfer_encoding_chunked:
+            parser->flags |= F_CHUNKED;
+            break;
+          case h_connection_upgrade:
+            parser->flags |= F_CONNECTION_UPGRADE;
+            break;
+          default:
+            break;
+        }
+
+        UPDATE_STATE(s_header_field_start);
+        REEXECUTE();
+      }
+
+      case s_header_value_discard_ws_almost_done:
+      {
+        STRICT_CHECK(ch != LF);
+        UPDATE_STATE(s_header_value_discard_lws);
+        break;
+      }
+
+      case s_header_value_discard_lws:
+      {
+        if (ch == ' ' || ch == '\t') {
+          UPDATE_STATE(s_header_value_discard_ws);
+          break;
+        } else {
+          switch (parser->header_state) {
+            case h_connection_keep_alive:
+              parser->flags |= F_CONNECTION_KEEP_ALIVE;
+              break;
+            case h_connection_close:
+              parser->flags |= F_CONNECTION_CLOSE;
+              break;
+            case h_connection_upgrade:
+              parser->flags |= F_CONNECTION_UPGRADE;
+              break;
+            case h_transfer_encoding_chunked:
+              parser->flags |= F_CHUNKED;
+              break;
+            default:
+              break;
+          }
+
+          /* header value was empty */
+          MARK(header_value);
+          UPDATE_STATE(s_header_field_start);
+          CALLBACK_DATA_NOADVANCE(header_value);
+          REEXECUTE();
+        }
+      }
+
+      case s_headers_almost_done:
+      {
+        STRICT_CHECK(ch != LF);
+
+        if (parser->flags & F_TRAILING) {
+          /* End of a chunked request */
+          UPDATE_STATE(s_message_done);
+          CALLBACK_NOTIFY_NOADVANCE(chunk_complete);
+          REEXECUTE();
+        }
+
+        /* Cannot use chunked encoding and a content-length header together
+           per the HTTP specification. */
+        if ((parser->flags & F_CHUNKED) &&
+            (parser->flags & F_CONTENTLENGTH)) {
+          SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
+          goto error;
+        }
+
+        UPDATE_STATE(s_headers_done);
+
+        /* Set this here so that on_headers_complete() callbacks can see it */
+        parser->upgrade =
+          ((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) ==
+           (F_UPGRADE | F_CONNECTION_UPGRADE) ||
+           parser->method == HTTP_CONNECT);
+
+        /* Here we call the headers_complete callback. This is somewhat
+         * different than other callbacks because if the user returns 1, we
+         * will interpret that as saying that this message has no body. This
+         * is needed for the annoying case of recieving a response to a HEAD
+         * request.
+         *
+         * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
+         * we have to simulate it by handling a change in errno below.
+         */
+        if (settings->on_headers_complete) {
+          switch (settings->on_headers_complete(parser)) {
+            case 0:
+              break;
+
+            case 2:
+              parser->upgrade = 1;
+
+            case 1:
+              parser->flags |= F_SKIPBODY;
+              break;
+
+            default:
+              SET_ERRNO(HPE_CB_headers_complete);
+              RETURN(p - data); /* Error */
+          }
+        }
+
+        if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
+          RETURN(p - data);
+        }
+
+        REEXECUTE();
+      }
+
+      case s_headers_done:
+      {
+        int hasBody;
+        STRICT_CHECK(ch != LF);
+
+        parser->nread = 0;
+
+        hasBody = parser->flags & F_CHUNKED ||
+          (parser->content_length > 0 && parser->content_length != ULLONG_MAX);
+        if (parser->upgrade && (parser->method == HTTP_CONNECT ||
+                                (parser->flags & F_SKIPBODY) || !hasBody)) {
+          /* Exit, the rest of the message is in a different protocol. */
+          UPDATE_STATE(NEW_MESSAGE());
+          CALLBACK_NOTIFY(message_complete);
+          RETURN((p - data) + 1);
+        }
+
+        if (parser->flags & F_SKIPBODY) {
+          UPDATE_STATE(NEW_MESSAGE());
+          CALLBACK_NOTIFY(message_complete);
+        } else if (parser->flags & F_CHUNKED) {
+          /* chunked encoding - ignore Content-Length header */
+          UPDATE_STATE(s_chunk_size_start);
+        } else {
+          if (parser->content_length == 0) {
+            /* Content-Length header given but zero: Content-Length: 0\r\n */
+            UPDATE_STATE(NEW_MESSAGE());
+            CALLBACK_NOTIFY(message_complete);
+          } else if (parser->content_length != ULLONG_MAX) {
+            /* Content-Length header given and non-zero */
+            UPDATE_STATE(s_body_identity);
+          } else {
+            if (!http_message_needs_eof(parser)) {
+              /* Assume content-length 0 - read the next */
+              UPDATE_STATE(NEW_MESSAGE());
+              CALLBACK_NOTIFY(message_complete);
+            } else {
+              /* Read body until EOF */
+              UPDATE_STATE(s_body_identity_eof);
+            }
+          }
+        }
+
+        break;
+      }
+
+      case s_body_identity:
+      {
+        uint64_t to_read = MIN(parser->content_length,
+                               (uint64_t) ((data + len) - p));
+
+        assert(parser->content_length != 0
+            && parser->content_length != ULLONG_MAX);
+
+        /* The difference between advancing content_length and p is because
+         * the latter will automaticaly advance on the next loop iteration.
+         * Further, if content_length ends up at 0, we want to see the last
+         * byte again for our message complete callback.
+         */
+        MARK(body);
+        parser->content_length -= to_read;
+        p += to_read - 1;
+
+        if (parser->content_length == 0) {
+          UPDATE_STATE(s_message_done);
+
+          /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.
+           *
+           * The alternative to doing this is to wait for the next byte to
+           * trigger the data callback, just as in every other case. The
+           * problem with this is that this makes it difficult for the test
+           * harness to distinguish between complete-on-EOF and
+           * complete-on-length. It's not clear that this distinction is
+           * important for applications, but let's keep it for now.
+           */
+          CALLBACK_DATA_(body, p - body_mark + 1, p - data);
+          REEXECUTE();
+        }
+
+        break;
+      }
+
+      /* read until EOF */
+      case s_body_identity_eof:
+        MARK(body);
+        p = data + len - 1;
+
+        break;
+
+      case s_message_done:
+        UPDATE_STATE(NEW_MESSAGE());
+        CALLBACK_NOTIFY(message_complete);
+        if (parser->upgrade) {
+          /* Exit, the rest of the message is in a different protocol. */
+          RETURN((p - data) + 1);
+        }
+        break;
+
+      case s_chunk_size_start:
+      {
+        assert(parser->nread == 1);
+        assert(parser->flags & F_CHUNKED);
+
+        unhex_val = unhex[(unsigned char)ch];
+        if (UNLIKELY(unhex_val == -1)) {
+          SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
+          goto error;
+        }
+
+        parser->content_length = unhex_val;
+        UPDATE_STATE(s_chunk_size);
+        break;
+      }
+
+      case s_chunk_size:
+      {
+        uint64_t t;
+
+        assert(parser->flags & F_CHUNKED);
+
+        if (ch == CR) {
+          UPDATE_STATE(s_chunk_size_almost_done);
+          break;
+        }
+
+        unhex_val = unhex[(unsigned char)ch];
+
+        if (unhex_val == -1) {
+          if (ch == ';' || ch == ' ') {
+            UPDATE_STATE(s_chunk_parameters);
+            break;
+          }
+
+          SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
+          goto error;
+        }
+
+        t = parser->content_length;
+        t *= 16;
+        t += unhex_val;
+
+        /* Overflow? Test against a conservative limit for simplicity. */
+        if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {
+          SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+          goto error;
+        }
+
+        parser->content_length = t;
+        break;
+      }
+
+      case s_chunk_parameters:
+      {
+        assert(parser->flags & F_CHUNKED);
+        /* just ignore this shit. TODO check for overflow */
+        if (ch == CR) {
+          UPDATE_STATE(s_chunk_size_almost_done);
+          break;
+        }
+        break;
+      }
+
+      case s_chunk_size_almost_done:
+      {
+        assert(parser->flags & F_CHUNKED);
+        STRICT_CHECK(ch != LF);
+
+        parser->nread = 0;
+
+        if (parser->content_length == 0) {
+          parser->flags |= F_TRAILING;
+          UPDATE_STATE(s_header_field_start);
+        } else {
+          UPDATE_STATE(s_chunk_data);
+        }
+        CALLBACK_NOTIFY(chunk_header);
+        break;
+      }
+
+      case s_chunk_data:
+      {
+        uint64_t to_read = MIN(parser->content_length,
+                               (uint64_t) ((data + len) - p));
+
+        assert(parser->flags & F_CHUNKED);
+        assert(parser->content_length != 0
+            && parser->content_length != ULLONG_MAX);
+
+        /* See the explanation in s_body_identity for why the content
+         * length and data pointers are managed this way.
+         */
+        MARK(body);
+        parser->content_length -= to_read;
+        p += to_read - 1;
+
+        if (parser->content_length == 0) {
+          UPDATE_STATE(s_chunk_data_almost_done);
+        }
+
+        break;
+      }
+
+      case s_chunk_data_almost_done:
+        assert(parser->flags & F_CHUNKED);
+        assert(parser->content_length == 0);
+        STRICT_CHECK(ch != CR);
+        UPDATE_STATE(s_chunk_data_done);
+        CALLBACK_DATA(body);
+        break;
+
+      case s_chunk_data_done:
+        assert(parser->flags & F_CHUNKED);
+        STRICT_CHECK(ch != LF);
+        parser->nread = 0;
+        UPDATE_STATE(s_chunk_size_start);
+        CALLBACK_NOTIFY(chunk_complete);
+        break;
+
+      default:
+        assert(0 && "unhandled state");
+        SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
+        goto error;
+    }
+  }
+
+  /* Run callbacks for any marks that we have leftover after we ran our of
+   * bytes. There should be at most one of these set, so it's OK to invoke
+   * them in series (unset marks will not result in callbacks).
+   *
+   * We use the NOADVANCE() variety of callbacks here because 'p' has already
+   * overflowed 'data' and this allows us to correct for the off-by-one that
+   * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'
+   * value that's in-bounds).
+   */
+
+  assert(((header_field_mark ? 1 : 0) +
+          (header_value_mark ? 1 : 0) +
+          (url_mark ? 1 : 0)  +
+          (body_mark ? 1 : 0) +
+          (status_mark ? 1 : 0)) <= 1);
+
+  CALLBACK_DATA_NOADVANCE(header_field);
+  CALLBACK_DATA_NOADVANCE(header_value);
+  CALLBACK_DATA_NOADVANCE(url);
+  CALLBACK_DATA_NOADVANCE(body);
+  CALLBACK_DATA_NOADVANCE(status);
+
+  RETURN(len);
+
+error:
+  if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
+    SET_ERRNO(HPE_UNKNOWN);
+  }
+
+  RETURN(p - data);
+}
+
+
+/* Does the parser need to see an EOF to find the end of the message? */
+int
+http_message_needs_eof (const http_parser *parser)
+{
+  if (parser->type == HTTP_REQUEST) {
+    return 0;
+  }
+
+  /* See RFC 2616 section 4.4 */
+  if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
+      parser->status_code == 204 ||     /* No Content */
+      parser->status_code == 304 ||     /* Not Modified */
+      parser->flags & F_SKIPBODY) {     /* response to a HEAD request */
+    return 0;
+  }
+
+  if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
+    return 0;
+  }
+
+  return 1;
+}
+
+
+int
+http_should_keep_alive (const http_parser *parser)
+{
+  if (parser->http_major > 0 && parser->http_minor > 0) {
+    /* HTTP/1.1 */
+    if (parser->flags & F_CONNECTION_CLOSE) {
+      return 0;
+    }
+  } else {
+    /* HTTP/1.0 or earlier */
+    if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
+      return 0;
+    }
+  }
+
+  return !http_message_needs_eof(parser);
+}
+
+
+const char *
+http_method_str (enum http_method m)
+{
+  return ELEM_AT(method_strings, m, "<unknown>");
+}
+
+
+void
+http_parser_init (http_parser *parser, enum http_parser_type t)
+{
+  void *data = parser->data; /* preserve application data */
+  memset(parser, 0, sizeof(*parser));
+  parser->data = data;
+  parser->type = t;
+  parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
+  parser->http_errno = HPE_OK;
+}
+
+void
+http_parser_settings_init(http_parser_settings *settings)
+{
+  memset(settings, 0, sizeof(*settings));
+}
+
+const char *
+http_errno_name(enum http_errno err) {
+  assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
+  return http_strerror_tab[err].name;
+}
+
+const char *
+http_errno_description(enum http_errno err) {
+  assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
+  return http_strerror_tab[err].description;
+}
+
+static enum http_host_state
+http_parse_host_char(enum http_host_state s, const char ch) {
+  switch(s) {
+    case s_http_userinfo:
+    case s_http_userinfo_start:
+      if (ch == '@') {
+        return s_http_host_start;
+      }
+
+      if (IS_USERINFO_CHAR(ch)) {
+        return s_http_userinfo;
+      }
+      break;
+
+    case s_http_host_start:
+      if (ch == '[') {
+        return s_http_host_v6_start;
+      }
+
+      if (IS_HOST_CHAR(ch)) {
+        return s_http_host;
+      }
+
+      break;
+
+    case s_http_host:
+      if (IS_HOST_CHAR(ch)) {
+        return s_http_host;
+      }
+
+    /* FALLTHROUGH */
+    case s_http_host_v6_end:
+      if (ch == ':') {
+        return s_http_host_port_start;
+      }
+
+      break;
+
+    case s_http_host_v6:
+      if (ch == ']') {
+        return s_http_host_v6_end;
+      }
+
+    /* FALLTHROUGH */
+    case s_http_host_v6_start:
+      if (IS_HEX(ch) || ch == ':' || ch == '.') {
+        return s_http_host_v6;
+      }
+
+      if (s == s_http_host_v6 && ch == '%') {
+        return s_http_host_v6_zone_start;
+      }
+      break;
+
+    case s_http_host_v6_zone:
+      if (ch == ']') {
+        return s_http_host_v6_end;
+      }
+
+    /* FALLTHROUGH */
+    case s_http_host_v6_zone_start:
+      /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
+      if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
+          ch == '~') {
+        return s_http_host_v6_zone;
+      }
+      break;
+
+    case s_http_host_port:
+    case s_http_host_port_start:
+      if (IS_NUM(ch)) {
+        return s_http_host_port;
+      }
+
+      break;
+
+    default:
+      break;
+  }
+  return s_http_host_dead;
+}
+
+static int
+http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
+  enum http_host_state s;
+
+  const char *p;
+  size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
+
+  assert(u->field_set & (1 << UF_HOST));
+
+  u->field_data[UF_HOST].len = 0;
+
+  s = found_at ? s_http_userinfo_start : s_http_host_start;
+
+  for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
+    enum http_host_state new_s = http_parse_host_char(s, *p);
+
+    if (new_s == s_http_host_dead) {
+      return 1;
+    }
+
+    switch(new_s) {
+      case s_http_host:
+        if (s != s_http_host) {
+          u->field_data[UF_HOST].off = p - buf;
+        }
+        u->field_data[UF_HOST].len++;
+        break;
+
+      case s_http_host_v6:
+        if (s != s_http_host_v6) {
+          u->field_data[UF_HOST].off = p - buf;
+        }
+        u->field_data[UF_HOST].len++;
+        break;
+
+      case s_http_host_v6_zone_start:
+      case s_http_host_v6_zone:
+        u->field_data[UF_HOST].len++;
+        break;
+
+      case s_http_host_port:
+        if (s != s_http_host_port) {
+          u->field_data[UF_PORT].off = p - buf;
+          u->field_data[UF_PORT].len = 0;
+          u->field_set |= (1 << UF_PORT);
+        }
+        u->field_data[UF_PORT].len++;
+        break;
+
+      case s_http_userinfo:
+        if (s != s_http_userinfo) {
+          u->field_data[UF_USERINFO].off = p - buf ;
+          u->field_data[UF_USERINFO].len = 0;
+          u->field_set |= (1 << UF_USERINFO);
+        }
+        u->field_data[UF_USERINFO].len++;
+        break;
+
+      default:
+        break;
+    }
+    s = new_s;
+  }
+
+  /* Make sure we don't end somewhere unexpected */
+  switch (s) {
+    case s_http_host_start:
+    case s_http_host_v6_start:
+    case s_http_host_v6:
+    case s_http_host_v6_zone_start:
+    case s_http_host_v6_zone:
+    case s_http_host_port_start:
+    case s_http_userinfo:
+    case s_http_userinfo_start:
+      return 1;
+    default:
+      break;
+  }
+
+  return 0;
+}
+
+void
+http_parser_url_init(struct http_parser_url *u) {
+  memset(u, 0, sizeof(*u));
+}
+
+int
+http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
+                      struct http_parser_url *u)
+{
+  enum state s;
+  const char *p;
+  enum http_parser_url_fields uf, old_uf;
+  int found_at = 0;
+
+  u->port = u->field_set = 0;
+  s = is_connect ? s_req_server_start : s_req_spaces_before_url;
+  old_uf = UF_MAX;
+
+  for (p = buf; p < buf + buflen; p++) {
+    s = parse_url_char(s, *p);
+
+    /* Figure out the next field that we're operating on */
+    switch (s) {
+      case s_dead:
+        return 1;
+
+      /* Skip delimeters */
+      case s_req_schema_slash:
+      case s_req_schema_slash_slash:
+      case s_req_server_start:
+      case s_req_query_string_start:
+      case s_req_fragment_start:
+        continue;
+
+      case s_req_schema:
+        uf = UF_SCHEMA;
+        break;
+
+      case s_req_server_with_at:
+        found_at = 1;
+
+      /* FALLTROUGH */
+      case s_req_server:
+        uf = UF_HOST;
+        break;
+
+      case s_req_path:
+        uf = UF_PATH;
+        break;
+
+      case s_req_query_string:
+        uf = UF_QUERY;
+        break;
+
+      case s_req_fragment:
+        uf = UF_FRAGMENT;
+        break;
+
+      default:
+        assert(!"Unexpected state");
+        return 1;
+    }
+
+    /* Nothing's changed; soldier on */
+    if (uf == old_uf) {
+      u->field_data[uf].len++;
+      continue;
+    }
+
+    u->field_data[uf].off = p - buf;
+    u->field_data[uf].len = 1;
+
+    u->field_set |= (1 << uf);
+    old_uf = uf;
+  }
+
+  /* host must be present if there is a schema */
+  /* parsing http:///toto will fail */
+  if ((u->field_set & (1 << UF_SCHEMA)) &&
+      (u->field_set & (1 << UF_HOST)) == 0) {
+    return 1;
+  }
+
+  if (u->field_set & (1 << UF_HOST)) {
+    if (http_parse_host(buf, u, found_at) != 0) {
+      return 1;
+    }
+  }
+
+  /* CONNECT requests can only contain "hostname:port" */
+  if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
+    return 1;
+  }
+
+  if (u->field_set & (1 << UF_PORT)) {
+    /* Don't bother with endp; we've already validated the string */
+    unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
+
+    /* Ports have a max value of 2^16 */
+    if (v > 0xffff) {
+      return 1;
+    }
+
+    u->port = (uint16_t) v;
+  }
+
+  return 0;
+}
+
+void
+http_parser_pause(http_parser *parser, int paused) {
+  /* Users should only be pausing/unpausing a parser that is not in an error
+   * state. In non-debug builds, there's not much that we can do about this
+   * other than ignore it.
+   */
+  if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
+      HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
+    SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
+  } else {
+    assert(0 && "Attempting to pause parser in error state");
+  }
+}
+
+int
+http_body_is_final(const struct http_parser *parser) {
+    return parser->state == s_message_done;
+}
+
+unsigned long
+http_parser_version(void) {
+  return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
+         HTTP_PARSER_VERSION_MINOR * 0x00100 |
+         HTTP_PARSER_VERSION_PATCH * 0x00001;
+}
+
+#pragma warning(pop)

+ 448 - 0
source/hook/hp-src/http/http_parser.h

@@ -0,0 +1,448 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef http_parser_h
+#define http_parser_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma warning(push)
+#pragma warning(disable: 4005)
+
+/* Also update SONAME in the Makefile whenever you change these. */
+#define HTTP_PARSER_VERSION_MAJOR 2
+#define HTTP_PARSER_VERSION_MINOR 7
+#define HTTP_PARSER_VERSION_PATCH 1
+
+#include <sys/types.h>
+#if defined(_WIN32) && !defined(__MINGW32__) && \
+  (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
+#include <BaseTsd.h>
+#include <stddef.h>
+typedef __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+#include <stdint.h>
+#endif
+
+/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
+ * faster
+ */
+#ifndef HTTP_PARSER_STRICT
+# define HTTP_PARSER_STRICT 1
+#endif
+
+/* Maximium header size allowed. If the macro is not defined
+ * before including this header then the default is used. To
+ * change the maximum header size, define the macro in the build
+ * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
+ * the effective limit on the size of the header, define the macro
+ * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
+ */
+#ifndef HTTP_MAX_HEADER_SIZE
+# define HTTP_MAX_HEADER_SIZE (80*1024)
+#endif
+
+typedef struct http_parser http_parser;
+typedef struct http_parser_settings http_parser_settings;
+
+
+/* Callbacks should return non-zero to indicate an error. The parser will
+ * then halt execution.
+ *
+ * The one exception is on_headers_complete. In a HTTP_RESPONSE parser
+ * returning '1' from on_headers_complete will tell the parser that it
+ * should not expect a body. This is used when receiving a response to a
+ * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
+ * chunked' headers that indicate the presence of a body.
+ *
+ * Returning `2` from on_headers_complete will tell parser that it should not
+ * expect neither a body nor any futher responses on this connection. This is
+ * useful for handling responses to a CONNECT request which may not contain
+ * `Upgrade` or `Connection: upgrade` headers.
+ *
+ * http_data_cb does not return data chunks. It will be called arbitrarily
+ * many times for each string. E.G. you might get 10 callbacks for "on_url"
+ * each providing just a few characters more data.
+ */
+typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
+typedef int (*http_cb) (http_parser*);
+
+
+/* Request Methods */
+#define HTTP_METHOD_MAP(XX)         \
+  XX(0,  DELETE,      DELETE)       \
+  XX(1,  GET,         GET)          \
+  XX(2,  HEAD,        HEAD)         \
+  XX(3,  POST,        POST)         \
+  XX(4,  PUT,         PUT)          \
+  /* pathological */                \
+  XX(5,  CONNECT,     CONNECT)      \
+  XX(6,  OPTIONS,     OPTIONS)      \
+  XX(7,  TRACE,       TRACE)        \
+  /* WebDAV */                      \
+  XX(8,  COPY,        COPY)         \
+  XX(9,  LOCK,        LOCK)         \
+  XX(10, MKCOL,       MKCOL)        \
+  XX(11, MOVE,        MOVE)         \
+  XX(12, PROPFIND,    PROPFIND)     \
+  XX(13, PROPPATCH,   PROPPATCH)    \
+  XX(14, SEARCH,      SEARCH)       \
+  XX(15, UNLOCK,      UNLOCK)       \
+  XX(16, BIND,        BIND)         \
+  XX(17, REBIND,      REBIND)       \
+  XX(18, UNBIND,      UNBIND)       \
+  XX(19, ACL,         ACL)          \
+  /* subversion */                  \
+  XX(20, REPORT,      REPORT)       \
+  XX(21, MKACTIVITY,  MKACTIVITY)   \
+  XX(22, CHECKOUT,    CHECKOUT)     \
+  XX(23, MERGE,       MERGE)        \
+  /* upnp */                        \
+  XX(24, MSEARCH,     M-SEARCH)     \
+  XX(25, NOTIFY,      NOTIFY)       \
+  XX(26, SUBSCRIBE,   SUBSCRIBE)    \
+  XX(27, UNSUBSCRIBE, UNSUBSCRIBE)  \
+  /* RFC-5789 */                    \
+  XX(28, PATCH,       PATCH)        \
+  XX(29, PURGE,       PURGE)        \
+  /* CalDAV */                      \
+  XX(30, MKCALENDAR,  MKCALENDAR)   \
+  /* RFC-2068, section 19.6.1.2 */  \
+  XX(31, LINK,        LINK)         \
+  XX(32, UNLINK,      UNLINK)       \
+
+enum http_method
+  {
+#define XX(num, name, string) HTTP_##name = num,
+  HTTP_METHOD_MAP(XX)
+#undef XX
+  };
+
+
+enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
+
+
+enum state
+  { s_dead = 1 /* important that this is > 0 */
+
+  , s_start_req_or_res
+  , s_res_or_resp_H
+  , s_start_res
+  , s_res_H = 5
+  , s_res_HT
+  , s_res_HTT
+  , s_res_HTTP
+  , s_res_first_http_major
+  , s_res_http_major = 10
+  , s_res_first_http_minor
+  , s_res_http_minor
+  , s_res_first_status_code
+  , s_res_status_code
+  , s_res_status_start = 15
+  , s_res_status
+  , s_res_line_almost_done
+
+  , s_start_req
+
+  , s_req_method
+  , s_req_spaces_before_url = 20
+  , s_req_schema
+  , s_req_schema_slash
+  , s_req_schema_slash_slash
+  , s_req_server_start
+  , s_req_server = 25
+  , s_req_server_with_at
+  , s_req_path
+  , s_req_query_string_start
+  , s_req_query_string
+  , s_req_fragment_start = 30
+  , s_req_fragment
+  , s_req_http_start
+  , s_req_http_H
+  , s_req_http_HT
+  , s_req_http_HTT = 35
+  , s_req_http_HTTP
+  , s_req_first_http_major
+  , s_req_http_major
+  , s_req_first_http_minor
+  , s_req_http_minor = 40
+  , s_req_line_almost_done
+
+  , s_header_field_start
+  , s_header_field
+  , s_header_value_discard_ws
+  , s_header_value_discard_ws_almost_done = 45
+  , s_header_value_discard_lws
+  , s_header_value_start
+  , s_header_value
+  , s_header_value_lws
+
+  , s_header_almost_done = 50
+
+  , s_chunk_size_start
+  , s_chunk_size
+  , s_chunk_parameters
+  , s_chunk_size_almost_done
+
+  , s_headers_almost_done = 55
+  , s_headers_done
+
+  /* Important: 's_headers_done' must be the last 'header' state. All
+   * states beyond this must be 'body' states. It is used for overflow
+   * checking. See the PARSING_HEADER() macro.
+   */
+
+  , s_chunk_data
+  , s_chunk_data_almost_done
+  , s_chunk_data_done
+
+  , s_body_identity = 60
+  , s_body_identity_eof
+
+  , s_message_done
+  };
+
+
+/* Flag values for http_parser.flags field */
+enum flags
+  { F_CHUNKED               = 1 << 0
+  , F_CONNECTION_KEEP_ALIVE = 1 << 1
+  , F_CONNECTION_CLOSE      = 1 << 2
+  , F_CONNECTION_UPGRADE    = 1 << 3
+  , F_TRAILING              = 1 << 4
+  , F_UPGRADE               = 1 << 5
+  , F_SKIPBODY              = 1 << 6
+  , F_CONTENTLENGTH         = 1 << 7
+  };
+
+
+/* Map for errno-related constants
+ *
+ * The provided argument should be a macro that takes 2 arguments.
+ */
+#define HTTP_ERRNO_MAP(XX)                                           \
+  /* No error */                                                     \
+  XX(OK, "success")                                                  \
+                                                                     \
+  /* Callback-related errors */                                      \
+  XX(CB_message_begin, "the on_message_begin callback failed")       \
+  XX(CB_url, "the on_url callback failed")                           \
+  XX(CB_header_field, "the on_header_field callback failed")         \
+  XX(CB_header_value, "the on_header_value callback failed")         \
+  XX(CB_headers_complete, "the on_headers_complete callback failed") \
+  XX(CB_body, "the on_body callback failed")                         \
+  XX(CB_message_complete, "the on_message_complete callback failed") \
+  XX(CB_status, "the on_status callback failed")                     \
+  XX(CB_chunk_header, "the on_chunk_header callback failed")         \
+  XX(CB_chunk_complete, "the on_chunk_complete callback failed")     \
+                                                                     \
+  /* Parsing-related errors */                                       \
+  XX(INVALID_EOF_STATE, "stream ended at an unexpected time")        \
+  XX(HEADER_OVERFLOW,                                                \
+     "too many header bytes seen; overflow detected")                \
+  XX(CLOSED_CONNECTION,                                              \
+     "data received after completed connection: close message")      \
+  XX(INVALID_VERSION, "invalid HTTP version")                        \
+  XX(INVALID_STATUS, "invalid HTTP status code")                     \
+  XX(INVALID_METHOD, "invalid HTTP method")                          \
+  XX(INVALID_URL, "invalid URL")                                     \
+  XX(INVALID_HOST, "invalid host")                                   \
+  XX(INVALID_PORT, "invalid port")                                   \
+  XX(INVALID_PATH, "invalid path")                                   \
+  XX(INVALID_QUERY_STRING, "invalid query string")                   \
+  XX(INVALID_FRAGMENT, "invalid fragment")                           \
+  XX(LF_EXPECTED, "LF character expected")                           \
+  XX(INVALID_HEADER_TOKEN, "invalid character in header")            \
+  XX(INVALID_CONTENT_LENGTH,                                         \
+     "invalid character in content-length header")                   \
+  XX(UNEXPECTED_CONTENT_LENGTH,                                      \
+     "unexpected content-length header")                             \
+  XX(INVALID_CHUNK_SIZE,                                             \
+     "invalid character in chunk size header")                       \
+  XX(INVALID_CONSTANT, "invalid constant string")                    \
+  XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
+  XX(STRICT, "strict mode assertion failed")                         \
+  XX(PAUSED, "parser is paused")                                     \
+  XX(UNKNOWN, "an unknown error occurred")
+
+
+/* Define HPE_* values for each errno value above */
+#define HTTP_ERRNO_GEN(n, s) HPE_##n,
+enum http_errno {
+  HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
+};
+#undef HTTP_ERRNO_GEN
+
+
+/* Get an http_errno value from an http_parser */
+#define HTTP_PARSER_ERRNO(p)            ((enum http_errno) (p)->http_errno)
+
+
+struct http_parser {
+  /** PRIVATE **/
+  unsigned int type : 2;         /* enum http_parser_type */
+  unsigned int flags : 8;        /* F_* values from 'flags' enum; semi-public */
+  unsigned int state : 7;        /* enum state from http_parser.c */
+  unsigned int header_state : 7; /* enum header_state from http_parser.c */
+  unsigned int index : 7;        /* index into current matcher */
+  unsigned int lenient_http_headers : 1;
+
+  uint32_t nread;          /* # bytes read in various scenarios */
+  uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
+
+  /** READ-ONLY **/
+  unsigned short http_major;
+  unsigned short http_minor;
+  unsigned int status_code : 16; /* responses only */
+  unsigned int method : 8;       /* requests only */
+  unsigned int http_errno : 7;
+
+  /* 1 = Upgrade header was present and the parser has exited because of that.
+   * 0 = No upgrade header present.
+   * Should be checked when http_parser_execute() returns in addition to
+   * error checking.
+   */
+  unsigned int upgrade : 1;
+
+  /** PUBLIC **/
+  void *data; /* A pointer to get hook to the "connection" or "socket" object */
+};
+
+
+struct http_parser_settings {
+  http_cb      on_message_begin;
+  http_data_cb on_url;
+  http_data_cb on_status;
+  http_data_cb on_header_field;
+  http_data_cb on_header_value;
+  http_cb      on_headers_complete;
+  http_data_cb on_body;
+  http_cb      on_message_complete;
+  /* When on_chunk_header is called, the current chunk length is stored
+   * in parser->content_length.
+   */
+  http_cb      on_chunk_header;
+  http_cb      on_chunk_complete;
+};
+
+
+enum http_parser_url_fields
+  { UF_SCHEMA           = 0
+  , UF_HOST             = 1
+  , UF_PORT             = 2
+  , UF_PATH             = 3
+  , UF_QUERY            = 4
+  , UF_FRAGMENT         = 5
+  , UF_USERINFO         = 6
+  , UF_MAX              = 7
+  };
+
+
+/* Result structure for http_parser_parse_url().
+ *
+ * Callers should index into field_data[] with UF_* values iff field_set
+ * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
+ * because we probably have padding left over), we convert any port to
+ * a uint16_t.
+ */
+struct http_parser_url {
+  uint16_t field_set;           /* Bitmask of (1 << UF_*) values */
+  uint16_t port;                /* Converted UF_PORT string */
+
+  struct {
+    uint16_t off;               /* Offset into buffer in which field starts */
+    uint16_t len;               /* Length of run in buffer */
+  } field_data[UF_MAX];
+};
+
+
+/* Returns the library version. Bits 16-23 contain the major version number,
+ * bits 8-15 the minor version number and bits 0-7 the patch level.
+ * Usage example:
+ *
+ *   unsigned long version = http_parser_version();
+ *   unsigned major = (version >> 16) & 255;
+ *   unsigned minor = (version >> 8) & 255;
+ *   unsigned patch = version & 255;
+ *   printf("http_parser v%u.%u.%u\n", major, minor, patch);
+ */
+unsigned long http_parser_version(void);
+
+void http_parser_init(http_parser *parser, enum http_parser_type type);
+
+
+/* Initialize http_parser_settings members to 0
+ */
+void http_parser_settings_init(http_parser_settings *settings);
+
+
+/* Executes the parser. Returns number of parsed bytes. Sets
+ * `parser->http_errno` on error. */
+size_t http_parser_execute(http_parser *parser,
+                           const http_parser_settings *settings,
+                           const char *data,
+                           size_t len);
+
+
+/* If http_should_keep_alive() in the on_headers_complete or
+ * on_message_complete callback returns 0, then this should be
+ * the last message on the connection.
+ * If you are the server, respond with the "Connection: close" header.
+ * If you are the client, close the connection.
+ */
+int http_should_keep_alive(const http_parser *parser);
+
+/* Returns a string version of the HTTP method. */
+const char *http_method_str(enum http_method m);
+
+/* Return a string name of the given error */
+const char *http_errno_name(enum http_errno err);
+
+/* Return a string description of the given error */
+const char *http_errno_description(enum http_errno err);
+
+/* Initialize all http_parser_url members to 0 */
+void http_parser_url_init(struct http_parser_url *u);
+
+/* Parse a URL; return nonzero on failure */
+int http_parser_parse_url(const char *buf, size_t buflen,
+                          int is_connect,
+                          struct http_parser_url *u);
+
+/* Pause or un-pause the parser; a nonzero value pauses */
+void http_parser_pause(http_parser *parser, int paused);
+
+/* Checks if this is the final chunk of the body. */
+int http_body_is_final(const http_parser *parser);
+
+#pragma warning(pop)
+
+#ifdef __cplusplus
+}
+#endif
+#endif