Files
hpsocket-linux/SocketHelper.h
2025-04-18 13:39:34 +08:00

1009 lines
30 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Copyright: JessMA Open Source (ldcsaa@gmail.com)
*
* Author : Bruce Liang
* Website : https://github.com/ldcsaa
* Project : https://github.com/ldcsaa/HP-Socket
* Blog : http://www.cnblogs.com/ldcsaa
* Wiki : http://www.oschina.net/p/hp-socket
* QQ Group : 44636872, 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 "hpsocket/HPTypeDef.h"
#include "hpsocket/SocketInterface.h"
#include "common/StringT.h"
#include "common/SysHelper.h"
#include "common/BufferPtr.h"
#include "common/BufferPool.h"
#include "common/RingBuffer.h"
#include "common/FileHelper.h"
#include "InternalDef.h"
#include <netdb.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#ifdef _ZLIB_SUPPORT
#include <zlib.h>
#endif
#ifdef _BROTLI_SUPPORT
#include <brotli/decode.h>
#include <brotli/encode.h>
#endif
using ADDRESS_FAMILY = sa_family_t;
using IN_ADDR = in_addr;
using IN6_ADDR = in6_addr;
using SOCKADDR = sockaddr;
using SOCKADDR_IN = sockaddr_in;
using SOCKADDR_IN6 = sockaddr_in6;
typedef struct hp_addr
{
ADDRESS_FAMILY family;
union
{
ULONG_PTR addr;
IN_ADDR addr4;
IN6_ADDR addr6;
};
static const hp_addr ANY_ADDR4;
static const hp_addr ANY_ADDR6;
inline int AddrSize() const
{
return AddrSize(family);
}
inline static int AddrSize(ADDRESS_FAMILY f)
{
if(f == AF_INET)
return sizeof(IN_ADDR);
return sizeof(IN6_ADDR);
}
inline static const hp_addr& AnyAddr(ADDRESS_FAMILY f)
{
if(f == AF_INET)
return ANY_ADDR4;
return ANY_ADDR6;
}
inline const ULONG_PTR* Addr() const {return &addr;}
inline ULONG_PTR* Addr() {return &addr;}
inline BOOL IsIPv4() const {return family == AF_INET;}
inline BOOL IsIPv6() const {return family == AF_INET6;}
inline BOOL IsSpecified() const {return IsIPv4() || IsIPv6();}
inline void ZeroAddr() {::ZeroMemory(&addr6, sizeof(addr6));}
inline void Reset() {::ZeroMemory(this, sizeof(*this));}
inline hp_addr& Copy(hp_addr& other) const
{
if(this != &other)
memcpy(&other, this, offsetof(hp_addr, addr) + AddrSize());
return other;
}
hp_addr(ADDRESS_FAMILY f = AF_UNSPEC, BOOL bZeroAddr = FALSE)
{
family = f;
if(bZeroAddr) ZeroAddr();
}
} HP_ADDR, *HP_PADDR;
typedef struct hp_sockaddr
{
union
{
ADDRESS_FAMILY family;
SOCKADDR addr;
SOCKADDR_IN addr4;
SOCKADDR_IN6 addr6;
};
inline int AddrSize() const
{
return AddrSize(family);
}
inline static int AddrSize(ADDRESS_FAMILY f)
{
if(f == AF_INET)
return sizeof(SOCKADDR_IN);
return sizeof(SOCKADDR_IN6);
}
inline int EffectAddrSize() const
{
return EffectAddrSize(family);
}
inline static int EffectAddrSize(ADDRESS_FAMILY f)
{
return (f == AF_INET) ? offsetof(SOCKADDR_IN, sin_zero) : sizeof(SOCKADDR_IN6);
}
inline static const hp_sockaddr& AnyAddr(ADDRESS_FAMILY f)
{
static const hp_sockaddr s_any_addr4(AF_INET, TRUE);
static const hp_sockaddr s_any_addr6(AF_INET6, TRUE);
if(f == AF_INET)
return s_any_addr4;
return s_any_addr6;
}
inline static int AddrMinStrLength(ADDRESS_FAMILY f)
{
if(f == AF_INET)
return INET_ADDRSTRLEN;
return INET6_ADDRSTRLEN;
}
inline BOOL IsIPv4() const {return family == AF_INET;}
inline BOOL IsIPv6() const {return family == AF_INET6;}
inline BOOL IsSpecified() const {return IsIPv4() || IsIPv6();}
inline USHORT Port() const {return ntohs(addr4.sin_port);}
inline void SetPort(USHORT usPort) {addr4.sin_port = htons(usPort);}
inline void* SinAddr() const {return IsIPv4() ? (void*)&addr4.sin_addr : (void*)&addr6.sin6_addr;}
inline void* SinAddr() {return IsIPv4() ? (void*)&addr4.sin_addr : (void*)&addr6.sin6_addr;}
inline const SOCKADDR* Addr() const {return &addr;}
inline SOCKADDR* Addr() {return &addr;}
inline void ZeroAddr() {::ZeroMemory(((char*)this) + sizeof(family), sizeof(*this) - sizeof(family));}
inline void Reset() {::ZeroMemory(this, sizeof(*this));}
inline hp_sockaddr& Copy(hp_sockaddr& other) const
{
if(this != &other)
memcpy(&other, this, AddrSize());
return other;
}
size_t Hash() const
{
ASSERT(IsSpecified());
size_t _Val = 2166136261U;
const int size = EffectAddrSize();
const BYTE* pAddr = (const BYTE*)Addr();
for(int i = 0; i < size; i++)
_Val = 16777619U * _Val ^ (size_t)pAddr[i];
return (_Val);
}
bool EqualTo(const hp_sockaddr& other) const
{
ASSERT(IsSpecified() && other.IsSpecified());
return EqualMemory(this, &other, EffectAddrSize());
}
hp_sockaddr(ADDRESS_FAMILY f = AF_UNSPEC, BOOL bZeroAddr = FALSE)
{
family = f;
if(bZeroAddr) ZeroAddr();
}
} HP_SOCKADDR, *HP_PSOCKADDR;
typedef struct hp_scope_host
{
LPCTSTR addr;
LPCTSTR name;
BOOL bNeedFree;
hp_scope_host(LPCTSTR lpszOriginAddress)
{
ASSERT(lpszOriginAddress != nullptr);
LPCTSTR lpszFind = ::StrChr(lpszOriginAddress, HOST_SEPARATOR_CHAR);
if(lpszFind == nullptr)
{
addr = lpszOriginAddress;
name = lpszOriginAddress;
bNeedFree = FALSE;
}
else
{
int i = (int)(lpszFind - lpszOriginAddress);
int iSize = (int)lstrlen(lpszOriginAddress) + 1;
LPTSTR lpszCopy = new TCHAR[iSize];
::memcpy((PVOID)lpszCopy, (PVOID)lpszOriginAddress, iSize * sizeof(TCHAR));
lpszCopy[i] = 0;
addr = lpszCopy;
name = lpszCopy + i + 1;
bNeedFree = TRUE;
if(::IsStrEmpty(name))
name = addr;
}
}
~hp_scope_host()
{
if(bNeedFree)
delete[] addr;
}
} HP_SCOPE_HOST, *HP_PSCOPE_HOST;
struct TNodeBufferObj : public TItem
{
using __super = TItem;
HP_SOCKADDR remoteAddr;
public:
void Reset(int first = 0, int last = 0)
{
__super::Reset(first, last);
remoteAddr.Reset();
}
public:
static TNodeBufferObj* Construct(CPrivateHeap& heap,
int capacity = DEFAULT_ITEM_CAPACITY,
BYTE* pData = nullptr,
int length = 0)
{
return ::ConstructItemT((TNodeBufferObj*)(nullptr), heap, capacity, pData, length);
}
static void Destruct(TNodeBufferObj* pBufferObj)
{
::DestructItemT(pBufferObj);
}
TNodeBufferObj(CPrivateHeap& hp, BYTE* pHead, int cap = DEFAULT_ITEM_CAPACITY, BYTE* pData = nullptr, int length = 0)
: TItem(hp, pHead, cap, pData, length)
{
}
~TNodeBufferObj()
{
}
DECLARE_NO_COPY_CLASS(TNodeBufferObj)
};
typedef CCASQueue<TNodeBufferObj> CNodeRecvQueue;
typedef TItemPtrT<TNodeBufferObj> TNodeBufferObjPtr;
typedef CNodePoolT<TNodeBufferObj> CNodeBufferObjPool;
typedef TItemListExT<TNodeBufferObj, volatile int> TNodeBufferObjList;
/* Server 组件和 Agent 组件内部使用的事件处理结果常量 */
// 连接已关闭
#define HR_CLOSED 0xFF
/* 命令类型 */
enum EnDispCmdType
{
DISP_CMD_SEND = 0x01, // 发送数据
DISP_CMD_RECEIVE = 0x02, // 接收数据
DISP_CMD_UNPAUSE = 0x03, // 恢复接收数据
DISP_CMD_DISCONNECT = 0x04, // 断开连接
DISP_CMD_TIMEOUT = 0x05 // 保活超时
};
/* 关闭连接标识 */
enum EnSocketCloseFlag
{
SCF_NONE = 0, // 不触发事件
SCF_CLOSE = 1, // 触发 正常关闭 OnClose 事件
SCF_ERROR = 2 // 触发 异常关闭 OnClose 事件
};
/* 数据缓冲节点 */
typedef TItem TBufferObj;
/* 数据缓冲节点智能指针 */
typedef TItemPtr TBufferObjPtr;
/* 数据缓冲区对象池 */
typedef CItemPool CBufferObjPool;
/* 数据缓冲区链表模板 */
typedef TItemListExV TBufferObjList;
/* 线程 ID - 接收缓冲区哈希表 */
typedef unordered_map<THR_ID, CBufferPtr*> TReceiveBufferMap;
/* 线程 ID - 接收缓冲区哈希表迭代器 */
typedef TReceiveBufferMap::iterator TReceiveBufferMapI;
/* 线程 ID - 接收缓冲区哈希表 const 迭代器 */
typedef TReceiveBufferMap::const_iterator TReceiveBufferMapCI;
/* Socket 缓冲区基础结构 */
struct TSocketObjBase : public CSafeCounter
{
CPrivateHeap& heap;
CONNID connID;
HP_SOCKADDR remoteAddr;
PVOID extra;
PVOID reserved;
PVOID reserved2;
DWORD activeTime;
union
{
DWORD freeTime;
DWORD connTime;
};
volatile BOOL valid;
volatile BOOL connected;
volatile BOOL paused;
TSocketObjBase(CPrivateHeap& hp) : heap(hp) {}
static BOOL IsExist(TSocketObjBase* pSocketObj)
{return pSocketObj != nullptr;}
static BOOL IsValid(TSocketObjBase* pSocketObj)
{return (IsExist(pSocketObj) && pSocketObj->valid == TRUE);}
static void Invalid(TSocketObjBase* pSocketObj)
{ASSERT(IsExist(pSocketObj)); pSocketObj->valid = FALSE;}
static void Release(TSocketObjBase* pSocketObj)
{ASSERT(IsExist(pSocketObj)); pSocketObj->freeTime = ::TimeGetTime();}
DWORD GetConnTime () const {return connTime;}
DWORD GetFreeTime () const {return freeTime;}
DWORD GetActiveTime () const {return activeTime;}
BOOL IsPaused () const {return paused;}
BOOL HasConnected() {return connected == TRUE;}
BOOL IsConnecting() {return connected == CST_CONNECTING;}
void SetConnected(BOOL bConnected = TRUE) {connected = bConnected;}
void Reset(CONNID dwConnID)
{
ResetCount();
connID = dwConnID;
connected = FALSE;
valid = TRUE;
paused = FALSE;
extra = nullptr;
reserved = nullptr;
reserved2 = nullptr;
}
};
/* 数据缓冲区结构 */
struct TSocketObj : public TSocketObjBase
{
using __super = TSocketObjBase;
CReentrantCriSec csIo;
CReentrantCriSec csSend;
SOCKET socket;
TBufferObjList sndBuff;
static TSocketObj* Construct(CPrivateHeap& hp, CBufferObjPool& bfPool)
{
TSocketObj* pSocketObj = (TSocketObj*)hp.Alloc(sizeof(TSocketObj));
ASSERT(pSocketObj);
return new (pSocketObj) TSocketObj(hp, bfPool);
}
static void Destruct(TSocketObj* pSocketObj)
{
ASSERT(pSocketObj);
CPrivateHeap& heap = pSocketObj->heap;
pSocketObj->TSocketObj::~TSocketObj();
heap.Free(pSocketObj);
}
TSocketObj(CPrivateHeap& hp, CBufferObjPool& bfPool)
: __super(hp), sndBuff(bfPool)
{
}
static void Release(TSocketObj* pSocketObj)
{
__super::Release(pSocketObj);
pSocketObj->sndBuff.Release();
}
int Pending() {return sndBuff.Length();}
BOOL IsPending() {return Pending() > 0;}
static BOOL InvalidSocketObj(TSocketObj* pSocketObj)
{
BOOL bDone = FALSE;
if(TSocketObjBase::IsValid(pSocketObj))
{
pSocketObj->SetConnected(FALSE);
CReentrantCriSecLock locallock(pSocketObj->csIo);
CReentrantCriSecLock locallock2(pSocketObj->csSend);
if(TSocketObjBase::IsValid(pSocketObj))
{
TSocketObjBase::Invalid(pSocketObj);
bDone = TRUE;
}
}
return bDone;
}
void Reset(CONNID dwConnID, SOCKET soClient)
{
__super::Reset(dwConnID);
socket = soClient;
}
};
/* Agent 数据缓冲区结构 */
struct TAgentSocketObj : public TSocketObj
{
using __super = TSocketObj;
CStringA host;
static TAgentSocketObj* Construct(CPrivateHeap& hp, CBufferObjPool& bfPool)
{
TAgentSocketObj* pSocketObj = (TAgentSocketObj*)hp.Alloc(sizeof(TAgentSocketObj));
ASSERT(pSocketObj);
return new (pSocketObj) TAgentSocketObj(hp, bfPool);
}
static void Destruct(TAgentSocketObj* pSocketObj)
{
ASSERT(pSocketObj);
CPrivateHeap& heap = pSocketObj->heap;
pSocketObj->TAgentSocketObj::~TAgentSocketObj();
heap.Free(pSocketObj);
}
TAgentSocketObj(CPrivateHeap& hp, CBufferObjPool& bfPool)
: __super(hp, bfPool)
{
}
void Reset(CONNID dwConnID, SOCKET soClient)
{
__super::Reset(dwConnID, soClient);
host.Empty();
}
BOOL GetRemoteHost(LPCSTR* lpszHost, USHORT* pusPort = nullptr)
{
*lpszHost = host;
if(pusPort)
*pusPort = remoteAddr.Port();
return (!host.IsEmpty());
}
};
/* UDP 数据缓冲区结构 */
struct TUdpSocketObj : public TSocketObjBase
{
using __super = TSocketObjBase;
using CRecvQueue = CCASQueue<TItem>;
PVOID pHolder;
FD fdTimer;
CBufferObjPool& itPool;
CRWLock lcIo;
CRWLock lcSend;
CCriSec csSend;
TBufferObjList sndBuff;
CRecvQueue recvQueue;
volatile DWORD detectFails;
static TUdpSocketObj* Construct(CPrivateHeap& hp, CBufferObjPool& bfPool)
{
TUdpSocketObj* pSocketObj = (TUdpSocketObj*)hp.Alloc(sizeof(TUdpSocketObj));
ASSERT(pSocketObj);
return new (pSocketObj) TUdpSocketObj(hp, bfPool);
}
static void Destruct(TUdpSocketObj* pSocketObj)
{
ASSERT(pSocketObj);
CPrivateHeap& heap = pSocketObj->heap;
pSocketObj->TUdpSocketObj::~TUdpSocketObj();
heap.Free(pSocketObj);
}
TUdpSocketObj(CPrivateHeap& hp, CBufferObjPool& bfPool)
: __super(hp), sndBuff(bfPool), itPool(bfPool)
{
}
~TUdpSocketObj()
{
ClearRecvQueue();
}
static void Release(TUdpSocketObj* pSocketObj)
{
__super::Release(pSocketObj);
pSocketObj->ClearRecvQueue();
pSocketObj->sndBuff.Release();
}
int Pending() {return sndBuff.Length();}
BOOL IsPending() {return Pending() > 0;}
BOOL HasRecvData() {return !recvQueue.IsEmpty();}
static BOOL InvalidSocketObj(TUdpSocketObj* pSocketObj)
{
BOOL bDone = FALSE;
if(TSocketObjBase::IsValid(pSocketObj))
{
pSocketObj->SetConnected(FALSE);
CReentrantWriteLock locallock(pSocketObj->lcIo);
CReentrantWriteLock locallock2(pSocketObj->lcSend);
CCriSecLock locallock3(pSocketObj->csSend);
if(TSocketObjBase::IsValid(pSocketObj))
{
TSocketObjBase::Invalid(pSocketObj);
bDone = TRUE;
}
}
return bDone;
}
void Reset(CONNID dwConnID)
{
__super::Reset(dwConnID);
pHolder = nullptr;
fdTimer = INVALID_FD;
detectFails = 0;
}
void ClearRecvQueue()
{
TItem* pItem = nullptr;
while(recvQueue.PopFront(&pItem))
itPool.PutFreeItem(pItem);
VERIFY(recvQueue.IsEmpty());
}
};
/* 有效 TSocketObj 缓存 */
typedef CRingCache2<TSocketObj, CONNID, true> TSocketObjPtrPool;
/* 失效 TSocketObj 缓存 */
typedef CRingPool<TSocketObj> TSocketObjPtrList;
/* 失效 TSocketObj 垃圾回收结构链表 */
typedef CCASQueue<TSocketObj> TSocketObjPtrQueue;
/* 有效 TSocketObj 缓存 */
typedef CRingCache2<TAgentSocketObj, CONNID, true> TAgentSocketObjPtrPool;
/* 失效 TSocketObj 缓存 */
typedef CRingPool<TAgentSocketObj> TAgentSocketObjPtrList;
/* 失效 TSocketObj 垃圾回收结构链表 */
typedef CCASQueue<TAgentSocketObj> TAgentSocketObjPtrQueue;
/* 有效 TUdpSocketObj 缓存 */
typedef CRingCache2<TUdpSocketObj, CONNID, true> TUdpSocketObjPtrPool;
/* 失效 TUdpSocketObj 缓存 */
typedef CRingPool<TUdpSocketObj> TUdpSocketObjPtrList;
/* 失效 TUdpSocketObj 垃圾回收结构链表 */
typedef CCASQueue<TUdpSocketObj> TUdpSocketObjPtrQueue;
/* HP_SOCKADDR 比较器 */
struct hp_sockaddr_func
{
struct hash
{
size_t operator() (const HP_SOCKADDR* pA) const
{
return pA->Hash();
}
};
struct equal_to
{
bool operator () (const HP_SOCKADDR* pA, const HP_SOCKADDR* pB) const
{
return pA->EqualTo(*pB);
}
};
};
/* 地址-连接 ID 哈希表 */
typedef unordered_map<const HP_SOCKADDR*, CONNID, hp_sockaddr_func::hash, hp_sockaddr_func::equal_to>
TSockAddrMap;
/* 地址-连接 ID 哈希表迭代器 */
typedef TSockAddrMap::iterator TSockAddrMapI;
/* 地址-连接 ID 哈希表 const 迭代器 */
typedef TSockAddrMap::const_iterator TSockAddrMapCI;
/* IClient 组件关闭上下文 */
struct TClientCloseContext
{
BOOL bFireOnClose;
EnSocketOperation enOperation;
int iErrorCode;
BOOL bNotify;
TClientCloseContext(BOOL bFire = TRUE, EnSocketOperation enOp = SO_CLOSE, int iCode = SE_OK, BOOL bNtf = TRUE)
{
Reset(bFire, enOp, iCode, bNtf);
}
void Reset(BOOL bFire = TRUE, EnSocketOperation enOp = SO_CLOSE, int iCode = SE_OK, BOOL bNtf = TRUE)
{
bFireOnClose = bFire;
enOperation = enOp;
iErrorCode = iCode;
bNotify = bNtf;
}
};
/*****************************************************************************************************/
/******************************************** 公共帮助方法 ********************************************/
/*****************************************************************************************************/
/* 默认工作线程前缀 */
#define DEFAULT_WORKER_THREAD_PREFIX "hp-worker-"
/* 设置当前工作线程名称 */
BOOL SetCurrentWorkerThreadName();
/* 设置工作线程默认名称 */
BOOL SetWorkerThreadDefaultName(THR_ID tid);
/* 获取错误描述文本 */
LPCTSTR GetSocketErrorDesc(EnSocketError enCode);
/* 确定地址簇 */
ADDRESS_FAMILY DetermineAddrFamily(LPCTSTR lpszAddress);
/* 地址字符串地址转换为 HP_ADDR */
BOOL GetInAddr(LPCTSTR lpszAddress, HP_ADDR& addr);
/* 地址字符串地址转换为 HP_SOCKADDR */
BOOL GetSockAddr(LPCTSTR lpszAddress, USHORT usPort, HP_SOCKADDR& addr);
/* 检查字符串是否符合 IP 地址格式 */
BOOL IsIPAddress(LPCTSTR lpszAddress, EnIPAddrType* penType = nullptr);
/* 通过主机名获取 IP 地址 */
BOOL GetIPAddress(LPCTSTR lpszHost, LPTSTR lpszIP, int& iIPLenth, EnIPAddrType& enType);
/* 通过主机名获取 HP_SOCKADDR */
BOOL GetSockAddrByHostName(LPCTSTR lpszHost, USHORT usPort, HP_SOCKADDR& addr);
/* 通过主机名获取 HP_SOCKADDR */
BOOL GetSockAddrByHostNameDirectly(LPCTSTR lpszHost, USHORT usPort, HP_SOCKADDR &addr);
/* 枚举主机 IP 地址 */
BOOL EnumHostIPAddresses(LPCTSTR lpszHost, EnIPAddrType enType, LPTIPAddr** lpppIPAddr, int& iIPAddrCount);
/* 填充 LPTIPAddr* */
BOOL RetrieveSockAddrIPAddresses(const vector<HP_PSOCKADDR>& vt, LPTIPAddr** lpppIPAddr, int& iIPAddrCount);
/* 释放 LPTIPAddr* */
BOOL FreeHostIPAddresses(LPTIPAddr* lppIPAddr);
/* 把 HP_SOCKADDR 结构转换为地址字符串 */
BOOL sockaddr_IN_2_A(const HP_SOCKADDR& addr, ADDRESS_FAMILY& usFamily, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort);
/* 把地址字符串转换为 HP_SOCKADDR 结构 */
BOOL sockaddr_A_2_IN(LPCTSTR lpszAddress, USHORT usPort, HP_SOCKADDR& addr);
/* 获取 Socket 的本地或远程地址信息 */
BOOL GetSocketAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort, BOOL bLocal = TRUE);
/* 获取 Socket 的本地地址信息 */
BOOL GetSocketLocalAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort);
/* 获取 Socket 的远程地址信息 */
BOOL GetSocketRemoteAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort);
/* 设置组播选项 */
BOOL SetMultiCastSocketOptions(SOCKET sock, const HP_SOCKADDR& bindAddr, const HP_SOCKADDR& castAddr, int iMCTtl, BOOL bMCLoop);
/* 64 位网络字节序转主机字节序 */
ULONGLONG NToH64(ULONGLONG value);
/* 64 位主机字节序转网络字节序 */
ULONGLONG HToN64(ULONGLONG value);
/* 短整型高低字节交换 */
#define ENDIAN_SWAP_16(A) ((USHORT)((((USHORT)(A) & 0xff00) >> 8) | (((USHORT)(A) & 0x00ff) << 8)))
/* 长整型高低字节交换 */
#define ENDIAN_SWAP_32(A) ((((DWORD)(A) & 0xff000000) >> 24) | \
(((DWORD)(A) & 0x00ff0000) >> 8) | \
(((DWORD)(A) & 0x0000ff00) << 8) | \
(((DWORD)(A) & 0x000000ff) << 24) )
/* 检查是否小端字节序 */
BOOL IsLittleEndian();
/* 短整型主机字节序转小端字节序 */
USHORT HToLE16(USHORT value);
/* 短整型主机字节序转大端字节序 */
USHORT HToBE16(USHORT value);
/* 长整型主机字节序转小端字节序 */
DWORD HToLE32(DWORD value);
/* 长整型主机字节序转大端字节序 */
DWORD HToBE32(DWORD value);
HRESULT ReadSmallFile(LPCTSTR lpszFileName, CFile& file, CFileMapping& fmap, DWORD dwMaxFileSize = MAX_SMALL_FILE_SIZE);
HRESULT MakeSmallFilePackage(LPCTSTR lpszFileName, CFile& file, CFileMapping& fmap, WSABUF szBuf[3], const LPWSABUF pHead = nullptr, const LPWSABUF pTail = nullptr);
/************************************************************************
名称setsockopt() 帮助方法
描述:简化常用的 setsockopt() 调用
************************************************************************/
int SSO_SetSocketOption (SOCKET sock, int level, int name, LPVOID val, int len);
int SSO_GetSocketOption (SOCKET sock, int level, int name, LPVOID val, int* len);
int SSO_IoctlSocket (SOCKET sock, long cmd, PVOID arg);
int SSO_NoBlock (SOCKET sock, BOOL bNoBlock = TRUE);
int SSO_NoDelay (SOCKET sock, BOOL bNoDelay = TRUE);
int SSO_DontLinger (SOCKET sock, BOOL bDont = TRUE);
int SSO_Linger (SOCKET sock, int l_onoff, int l_linger);
int SSO_KeepAlive (SOCKET sock, BOOL bKeepAlive = TRUE);
int SSO_KeepAliveVals (SOCKET sock, BOOL bOnOff, DWORD dwIdle, DWORD dwInterval, DWORD dwCount = 5);
int SSO_ReuseAddress (SOCKET sock, EnReuseAddressPolicy opt);
int SSO_RecvBuffSize (SOCKET sock, int size);
int SSO_SendBuffSize (SOCKET sock, int size);
int SSO_RecvTimeOut (SOCKET sock, int ms);
int SSO_SendTimeOut (SOCKET sock, int ms);
int SSO_GetError (SOCKET sock);
/* 生成 Connection ID */
CONNID GenerateConnectionID();
/* 检测 UDP 连接关闭通知 */
int IsUdpCloseNotify(const BYTE* pData, int iLength);
/* 发送 UDP 连接关闭通知 */
int SendUdpCloseNotify(SOCKET sock);
/* 发送 UDP 连接关闭通知 */
int SendUdpCloseNotify(SOCKET sock, const HP_SOCKADDR& remoteAddr);
/* 关闭 Socket */
int ManualCloseSocket(SOCKET sock, int iShutdownFlag = 0xFF, BOOL bGraceful = TRUE);
#ifdef _ICONV_SUPPORT
#define CHARSET_GBK "GBK"
#define CHARSET_UTF_8 "UTF-8"
#define CHARSET_UTF_16LE "UTF-16LE"
#define CHARSET_UTF_32LE "UTF-32LE"
#define CHARSET_UTF_16BE "UTF-16BE"
#define CHARSET_UTF_32BE "UTF-32BE"
// 系统 UNICODE 字符集
#define SYSTEM_CHARSET_UNICODE ( (sizeof(WCHAR) == 4) \
? (IsLittleEndian() ? CHARSET_UTF_32LE : CHARSET_UTF_32BE) \
: (IsLittleEndian() ? CHARSET_UTF_16LE : CHARSET_UTF_16BE) )
// Charset A -> Charset B
BOOL CharsetConvert(LPCSTR lpszFromCharset, LPCSTR lpszToCharset, LPCSTR lpszInBuf, int iInBufLen, LPSTR lpszOutBuf, int& iOutBufLen);
// GBK -> UNICODE
BOOL GbkToUnicodeEx(const char szSrc[], int iSrcLength, WCHAR szDest[], int& iDestLength);
// UNICODE -> GBK
BOOL UnicodeToGbkEx(const WCHAR szSrc[], int iSrcLength, char szDest[], int& iDestLength);
// UTF8 -> UNICODE
BOOL Utf8ToUnicodeEx(const char szSrc[], int iSrcLength, WCHAR szDest[], int& iDestLength);
// UNICODE -> UTF8
BOOL UnicodeToUtf8Ex(const WCHAR szSrc[], int iSrcLength, char szDest[], int& iDestLength);
// GBK -> UTF8
BOOL GbkToUtf8Ex(const char szSrc[], int iSrcLength, char szDest[], int& iDestLength);
// UTF8 -> GBK
BOOL Utf8ToGbkEx(const char szSrc[], int iSrcLength, char szDest[], int& iDestLength);
// GBK -> UNICODE
BOOL GbkToUnicode(const char szSrc[], WCHAR szDest[], int& iDestLength);
// UNICODE -> GBK
BOOL UnicodeToGbk(const WCHAR szSrc[], char szDest[], int& iDestLength);
// UTF8 -> UNICODE
BOOL Utf8ToUnicode(const char szSrc[], WCHAR szDest[], int& iDestLength);
// UNICODE -> UTF8
BOOL UnicodeToUtf8(const WCHAR szSrc[], char szDest[], int& iDestLength);
// GBK -> UTF8
BOOL GbkToUtf8(const char szSrc[], char szDest[], int& iDestLength);
// UTF8 -> GBK
BOOL Utf8ToGbk(const char szSrc[], char szDest[], int& iDestLength);
#endif
// 计算 Base64 编码后长度
DWORD GuessBase64EncodeBound(DWORD dwSrcLen);
// 计算 Base64 解码后长度
DWORD GuessBase64DecodeBound(const BYTE* lpszSrc, DWORD dwSrcLen);
// Base64 编码返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int Base64Encode(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// Base64 解码返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int Base64Decode(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// 计算 URL 编码后长度
DWORD GuessUrlEncodeBound(const BYTE* lpszSrc, DWORD dwSrcLen);
// 计算 URL 解码后长度
DWORD GuessUrlDecodeBound(const BYTE* lpszSrc, DWORD dwSrcLen);
// URL 编码返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int UrlEncode(BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// URL 解码返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int UrlDecode(BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
/* 销毁压缩器对象 */
void DestroyCompressor(IHPCompressor* pCompressor);
/* 销毁解压器对象 */
void DestroyDecompressor(IHPDecompressor* pDecompressor);
#ifdef _ZLIB_SUPPORT
/* ZLib 压缩器 */
class CHPZLibCompressor : public IHPCompressor
{
public:
virtual BOOL Process(const BYTE* pData, int iLength, BOOL bLast, PVOID pContext = nullptr);
virtual BOOL ProcessEx(const BYTE* pData, int iLength, BOOL bLast, BOOL bFlush = FALSE, PVOID pContext = nullptr);
virtual BOOL IsValid() {return m_bValid;}
virtual BOOL Reset();
public:
CHPZLibCompressor(Fn_CompressDataCallback fnCallback, int iWindowBits = MAX_WBITS, int iLevel = Z_DEFAULT_COMPRESSION, int iMethod = Z_DEFLATED, int iMemLevel = MAX_MEM_LEVEL, int iStrategy = Z_DEFAULT_STRATEGY, DWORD dwBuffSize = DEFAULT_COMPRESS_BUFFER_SIZE);
virtual ~CHPZLibCompressor();
private:
Fn_CompressDataCallback m_fnCallback;
z_stream m_Stream;
BOOL m_bValid;
DWORD m_dwBuffSize;
};
/* ZLib 解压器 */
class CHPZLibDecompressor : public IHPDecompressor
{
public:
virtual BOOL Process(const BYTE* pData, int iLength, PVOID pContext = nullptr);
virtual BOOL IsValid() {return m_bValid;}
virtual BOOL Reset();
public:
CHPZLibDecompressor(Fn_DecompressDataCallback fnCallback, int iWindowBits = MAX_WBITS, DWORD dwBuffSize = DEFAULT_COMPRESS_BUFFER_SIZE);
virtual ~CHPZLibDecompressor();
private:
Fn_DecompressDataCallback m_fnCallback;
z_stream m_Stream;
BOOL m_bValid;
DWORD m_dwBuffSize;
};
/* 创建 ZLib 压缩器对象 */
IHPCompressor* CreateZLibCompressor(Fn_CompressDataCallback fnCallback, int iWindowBits = MAX_WBITS, int iLevel = Z_DEFAULT_COMPRESSION, int iMethod = Z_DEFLATED, int iMemLevel = MAX_MEM_LEVEL, int iStrategy = Z_DEFAULT_STRATEGY, DWORD dwBuffSize = DEFAULT_COMPRESS_BUFFER_SIZE);
/* 创建 GZip 压缩器对象 */
IHPCompressor* CreateGZipCompressor(Fn_CompressDataCallback fnCallback, int iLevel = Z_DEFAULT_COMPRESSION, int iMethod = Z_DEFLATED, int iMemLevel = MAX_MEM_LEVEL, int iStrategy = Z_DEFAULT_STRATEGY, DWORD dwBuffSize = DEFAULT_COMPRESS_BUFFER_SIZE);
/* 创建 ZLib 解压器对象 */
IHPDecompressor* CreateZLibDecompressor(Fn_DecompressDataCallback fnCallback, int iWindowBits = MAX_WBITS, DWORD dwBuffSize = DEFAULT_COMPRESS_BUFFER_SIZE);
/* 创建 GZip 解压器对象 */
IHPDecompressor* CreateGZipDecompressor(Fn_DecompressDataCallback fnCallback, DWORD dwBuffSize = DEFAULT_COMPRESS_BUFFER_SIZE);
// 普通压缩返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int Compress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// 高级压缩返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int CompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iLevel = Z_DEFAULT_COMPRESSION, int iMethod = Z_DEFLATED, int iWindowBits = MAX_WBITS, int iMemLevel = MAX_MEM_LEVEL, int iStrategy = Z_DEFAULT_STRATEGY);
// 普通解压返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int Uncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// 高级解压返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int UncompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iWindowBits = MAX_WBITS);
// 推测压缩结果长度
DWORD GuessCompressBound(DWORD dwSrcLen, BOOL bGZip = FALSE);
// Gzip 压缩返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int GZipCompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// Gzip 解压返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int GZipUncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// 推测 Gzip 解压结果长度(如果返回 0 或不合理值则说明输入内容并非有效的 Gzip 格式)
DWORD GZipGuessUncompressBound(const BYTE* lpszSrc, DWORD dwSrcLen);
#endif
#ifdef _BROTLI_SUPPORT
/* Brotli 压缩器 */
class CHPBrotliCompressor : public IHPCompressor
{
public:
virtual BOOL Process(const BYTE* pData, int iLength, BOOL bLast, PVOID pContext = nullptr);
virtual BOOL ProcessEx(const BYTE* pData, int iLength, BOOL bLast, BOOL bFlush = FALSE, PVOID pContext = nullptr);
virtual BOOL IsValid() {return m_bValid;}
virtual BOOL Reset();
public:
CHPBrotliCompressor(Fn_CompressDataCallback fnCallback, int iQuality = BROTLI_DEFAULT_QUALITY, int iWindow = BROTLI_DEFAULT_WINDOW, int iMode = BROTLI_DEFAULT_MODE, DWORD dwBuffSize = DEFAULT_COMPRESS_BUFFER_SIZE);
virtual ~CHPBrotliCompressor();
private:
Fn_CompressDataCallback m_fnCallback;
BrotliEncoderState* m_pState;
BOOL m_bValid;
int m_iQuality;
int m_iWindow;
int m_iMode;
DWORD m_dwBuffSize;
};
/* Brotli 解压器 */
class CHPBrotliDecompressor : public IHPDecompressor
{
public:
virtual BOOL Process(const BYTE* pData, int iLength, PVOID pContext = nullptr);
virtual BOOL IsValid() {return m_bValid;}
virtual BOOL Reset();
public:
CHPBrotliDecompressor(Fn_DecompressDataCallback fnCallback, DWORD dwBuffSize = DEFAULT_COMPRESS_BUFFER_SIZE);
virtual ~CHPBrotliDecompressor();
private:
Fn_DecompressDataCallback m_fnCallback;
BrotliDecoderState* m_pState;
BOOL m_bValid;
DWORD m_dwBuffSize;
};
/* 创建 Brotli 压缩器对象 */
IHPCompressor* CreateBrotliCompressor(Fn_CompressDataCallback fnCallback, int iQuality = BROTLI_DEFAULT_QUALITY, int iWindow = BROTLI_DEFAULT_WINDOW, int iMode = BROTLI_DEFAULT_MODE, DWORD dwBuffSize = DEFAULT_COMPRESS_BUFFER_SIZE);
/* 创建 Brotli 解压器对象 */
IHPDecompressor* CreateBrotliDecompressor(Fn_DecompressDataCallback fnCallback, DWORD dwBuffSize = DEFAULT_COMPRESS_BUFFER_SIZE);
// Brotli 压缩返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int BrotliCompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// Brotli 高级压缩返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int BrotliCompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iQuality = BROTLI_DEFAULT_QUALITY, int iWindow = BROTLI_DEFAULT_WINDOW, int iMode = BROTLI_DEFAULT_MODE);
// Brotli 解压返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
int BrotliUncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// Brotli 推测压缩结果长度
DWORD BrotliGuessCompressBound(DWORD dwSrcLen);
#endif