同步操作将从 伤神小怪兽/HP-Socket 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
/** 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.*/#include "SocketHelper.h"#include <sys/ioctl.h>#include <arpa/inet.h>#include <netinet/tcp.h>#include <netinet/udp.h>#ifdef _ICONV_SUPPORT#include <iconv.h>#endif#ifndef SO_REUSEPORT#define SO_REUSEPORT 15#endif//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////static const BYTE s_szUdpCloseNotify[] = {0xBE, 0xB6, 0x1F, 0xEB, 0xDA, 0x52, 0x46, 0xBA, 0x92, 0x33, 0x59, 0xDB, 0xBF, 0xE6, 0xC8, 0xE4};static const int s_iUdpCloseNotifySize = ARRAY_SIZE(s_szUdpCloseNotify);const hp_addr hp_addr::ANY_ADDR4(AF_INET, TRUE);const hp_addr hp_addr::ANY_ADDR6(AF_INET6, TRUE);BOOL SetCurrentWorkerThreadName(){return SetWorkerThreadDefaultName(0);}BOOL SetWorkerThreadDefaultName(THR_ID tid){static volatile UINT _s_uiSeq = MAXUINT;return ::SetSequenceThreadName(tid, DEFAULT_WORKER_THREAD_PREFIX, _s_uiSeq);}LPCTSTR GetSocketErrorDesc(EnSocketError enCode){switch(enCode){case SE_OK: return _T("SUCCESS");case SE_ILLEGAL_STATE: return _T("Illegal State");case SE_INVALID_PARAM: return _T("Invalid Parameter");case SE_SOCKET_CREATE: return _T("Create SOCKET Fail");case SE_SOCKET_BIND: return _T("Bind SOCKET Fail");case SE_SOCKET_PREPARE: return _T("Prepare SOCKET Fail");case SE_SOCKET_LISTEN: return _T("Listen SOCKET Fail");case SE_CP_CREATE: return _T("Create IOCP Fail");case SE_WORKER_THREAD_CREATE: return _T("Create Worker Thread Fail");case SE_DETECT_THREAD_CREATE: return _T("Create Detector Thread Fail");case SE_SOCKE_ATTACH_TO_CP: return _T("Attach SOCKET to IOCP Fail");case SE_CONNECT_SERVER: return _T("Connect to Server Fail");case SE_NETWORK: return _T("Network Error");case SE_DATA_PROC: return _T("Process Data Error");case SE_DATA_SEND: return _T("Send Data Fail");case SE_SSL_ENV_NOT_READY: return _T("SSL environment not ready");default: ASSERT(FALSE); return _T("UNKNOWN ERROR");}}ADDRESS_FAMILY DetermineAddrFamily(LPCTSTR lpszAddress){if (!lpszAddress || lpszAddress[0] == 0)return AF_UNSPEC;if(::StrChr(lpszAddress, IPV6_ADDR_SEPARATOR_CHAR))return AF_INET6;TCHAR c;int arr[4];if(stscanf(lpszAddress, _T("%d.%d.%d.%d%c"), &arr[0], &arr[1], &arr[2], &arr[3], &c) != 4)return AF_UNSPEC;for(int i = 0; i < 4; i++){if(arr[i] < 0 || arr[i] > 255)return AF_UNSPEC;}return AF_INET;}BOOL GetInAddr(LPCTSTR lpszAddress, HP_ADDR& addr){addr.family = DetermineAddrFamily(lpszAddress);if (addr.family == AF_UNSPEC)return FALSE;return (::InetPton(addr.family, lpszAddress, addr.Addr()) == TRUE);}BOOL GetSockAddr(LPCTSTR lpszAddress, USHORT usPort, HP_SOCKADDR& addr){if(addr.family != AF_INET && addr.family != AF_INET6){::WSASetLastError(ERROR_ADDRNOTAVAIL);return FALSE;}if(addr.family == AF_INET6 && StrChr(lpszAddress, IPV6_ZONE_INDEX_CHAR))return GetSockAddrByHostNameDirectly(lpszAddress, usPort, addr);addr.ZeroAddr();int rs = ::InetPton(addr.family, lpszAddress, addr.SinAddr());if(rs != 1){if(rs == 0) ::WSASetLastError(ERROR_INVALID_PARAMETER);return FALSE;}if(usPort != 0)addr.SetPort(usPort);return TRUE;}BOOL IsIPAddress(LPCTSTR lpszAddress, EnIPAddrType* penType){HP_ADDR addr;BOOL isOK = GetInAddr(lpszAddress, addr);if(isOK && penType)*penType = addr.IsIPv4() ? IPT_IPV4 : IPT_IPV6;return isOK;}BOOL GetIPAddress(LPCTSTR lpszHost, LPTSTR lpszIP, int& iIPLen, EnIPAddrType& enType){HP_SOCKADDR addr;if(!GetSockAddrByHostName(lpszHost, 0, addr))return FALSE;enType = addr.IsIPv4() ? IPT_IPV4 : IPT_IPV6;USHORT usPort;ADDRESS_FAMILY usFamily;return sockaddr_IN_2_A(addr, usFamily, lpszIP, iIPLen, usPort);}BOOL GetSockAddrByHostName(LPCTSTR lpszHost, USHORT usPort, HP_SOCKADDR& addr){addr.family = DetermineAddrFamily(lpszHost);if(addr.family != AF_UNSPEC)return GetSockAddr(lpszHost, usPort, addr);return GetSockAddrByHostNameDirectly(lpszHost, usPort, addr);}BOOL GetSockAddrByHostNameDirectly(LPCTSTR lpszHost, USHORT usPort, HP_SOCKADDR& addr){addr.ZeroAddr();addrinfo* pInfo = nullptr;addrinfo hints = {0};#if defined(__ANDROID__)hints.ai_flags = 0;#elsehints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);#endifhints.ai_family = addr.family;hints.ai_socktype = SOCK_STREAM;int rs = ::getaddrinfo(CT2A(lpszHost), nullptr, &hints, &pInfo);if(!IS_NO_ERROR(rs)){::WSASetLastError(ERROR_HOSTUNREACH);return FALSE;}BOOL isOK = FALSE;for(addrinfo* pCur = pInfo; pCur != nullptr; pCur = pCur->ai_next){if(pCur->ai_family == AF_INET || pCur->ai_family == AF_INET6){memcpy(addr.Addr(), pCur->ai_addr, pCur->ai_addrlen);isOK = TRUE;break;}}EXECUTE_RESTORE_ERROR(::freeaddrinfo(pInfo));if(isOK)addr.SetPort(usPort);else::WSASetLastError(ERROR_HOSTUNREACH);return isOK;}BOOL EnumHostIPAddresses(LPCTSTR lpszHost, EnIPAddrType enType, LPTIPAddr** lpppIPAddr, int& iIPAddrCount){*lpppIPAddr = nullptr;iIPAddrCount = 0;ADDRESS_FAMILY usFamily = (enType == IPT_ALL ?AF_UNSPEC : (enType == IPT_IPV4 ?AF_INET : (enType == IPT_IPV6 ?AF_INET6 : 0xFF)));if(usFamily == 0xFF){::WSASetLastError(ERROR_AFNOSUPPORT);return FALSE;}vector<HP_PSOCKADDR> vt;ADDRESS_FAMILY usFamily2 = DetermineAddrFamily(lpszHost);if(usFamily2 != AF_UNSPEC){if(usFamily != AF_UNSPEC && usFamily != usFamily2){::WSASetLastError(ERROR_HOSTUNREACH);return FALSE;}HP_SOCKADDR addr(usFamily2);if(!GetSockAddr(lpszHost, 0, addr))return FALSE;vt.emplace_back(&addr);return RetrieveSockAddrIPAddresses(vt, lpppIPAddr, iIPAddrCount);}addrinfo* pInfo = nullptr;addrinfo hints = {0};#if defined(__ANDROID__)hints.ai_flags = 0;#elsehints.ai_flags = AI_ALL;#endifhints.ai_family = usFamily;hints.ai_socktype = SOCK_STREAM;int rs = ::getaddrinfo(CT2A(lpszHost), nullptr, &hints, &pInfo);if(rs != NO_ERROR){::WSASetLastError(rs);return FALSE;}for(addrinfo* pCur = pInfo; pCur != nullptr; pCur = pCur->ai_next){if(pCur->ai_family == AF_INET || pCur->ai_family == AF_INET6)vt.emplace_back((HP_PSOCKADDR)pCur->ai_addr);}BOOL isOK = RetrieveSockAddrIPAddresses(vt, lpppIPAddr, iIPAddrCount);::freeaddrinfo(pInfo);if(!isOK) ::WSASetLastError(EHOSTUNREACH);return isOK;}BOOL RetrieveSockAddrIPAddresses(const vector<HP_PSOCKADDR>& vt, LPTIPAddr** lpppIPAddr, int& iIPAddrCount){iIPAddrCount = (int)vt.size();if(iIPAddrCount == 0) return FALSE;HP_PSOCKADDR pSockAddr;ADDRESS_FAMILY usFamily;USHORT usPort;int iAddrLength;LPTSTR lpszAddr;LPTIPAddr lpItem;(*lpppIPAddr) = new LPTIPAddr[iIPAddrCount + 1];(*lpppIPAddr)[iIPAddrCount] = nullptr;for(int i = 0; i < iIPAddrCount; i++){pSockAddr = vt[i];iAddrLength = HP_SOCKADDR::AddrMinStrLength(pSockAddr->family);lpszAddr = new TCHAR[iAddrLength];VERIFY(sockaddr_IN_2_A(*vt[i], usFamily, lpszAddr, iAddrLength, usPort));lpItem = new TIPAddr;lpItem->type = pSockAddr->IsIPv4() ? IPT_IPV4 : IPT_IPV6;lpItem->address = lpszAddr;(*lpppIPAddr)[i] = lpItem;}return TRUE;}BOOL FreeHostIPAddresses(LPTIPAddr* lppIPAddr){if(!lppIPAddr) return FALSE;LPTIPAddr p;LPTIPAddr* lppCur = lppIPAddr;while((p = *lppCur++) != nullptr){delete[] p->address;delete p;}delete[] lppIPAddr;return TRUE;}BOOL sockaddr_IN_2_A(const HP_SOCKADDR& addr, ADDRESS_FAMILY& usFamily, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort){BOOL isOK = FALSE;usFamily = addr.family;usPort = addr.Port();if(::InetNtop(addr.family, addr.SinAddr(), lpszAddress, iAddressLen)){iAddressLen = (int)lstrlen(lpszAddress) + 1;isOK = TRUE;}else{if(::WSAGetLastError() == ENOSPC)iAddressLen = HP_SOCKADDR::AddrMinStrLength(usFamily);}return isOK;}BOOL sockaddr_A_2_IN(LPCTSTR lpszAddress, USHORT usPort, HP_SOCKADDR& addr){addr.family = DetermineAddrFamily(lpszAddress);return GetSockAddr(lpszAddress, usPort, addr);}BOOL GetSocketAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort, BOOL bLocal){HP_SOCKADDR addr;int addr_len = addr.AddrSize();int result = bLocal ? getsockname(socket, addr.Addr(), (socklen_t*)&addr_len) : getpeername(socket, addr.Addr(), (socklen_t*)&addr_len);if(result != NO_ERROR)return FALSE;ADDRESS_FAMILY usFamily;return sockaddr_IN_2_A(addr, usFamily, lpszAddress, iAddressLen, usPort);}BOOL GetSocketLocalAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort){return GetSocketAddress(socket, lpszAddress, iAddressLen, usPort, TRUE);}BOOL GetSocketRemoteAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort){return GetSocketAddress(socket, lpszAddress, iAddressLen, usPort, FALSE);}BOOL SetMultiCastSocketOptions(SOCKET sock, const HP_SOCKADDR& bindAddr, const HP_SOCKADDR& castAddr, int iMCTtl, BOOL bMCLoop){if(castAddr.IsIPv4()){BYTE ttl = (BYTE)iMCTtl;BYTE loop = (BYTE)bMCLoop;VERIFY(::SSO_SetSocketOption(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) != SOCKET_ERROR);VERIFY(::SSO_SetSocketOption(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) != SOCKET_ERROR);ip_mreq mcast;::ZeroMemory(&mcast, sizeof(mcast));mcast.imr_multiaddr = castAddr.addr4.sin_addr;mcast.imr_interface = bindAddr.addr4.sin_addr;if(::SSO_SetSocketOption(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast)) == SOCKET_ERROR)return FALSE;if(::SSO_SetSocketOption(sock, IPPROTO_IP, IP_MULTICAST_IF, bindAddr.SinAddr(), sizeof(IN_ADDR)) == SOCKET_ERROR)return FALSE;}else{INT ttl = (INT)iMCTtl;UINT loop = (UINT)bMCLoop;VERIFY(::SSO_SetSocketOption(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) != SOCKET_ERROR);VERIFY(::SSO_SetSocketOption(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)) != SOCKET_ERROR);ipv6_mreq mcast;::ZeroMemory(&mcast, sizeof(mcast));mcast.ipv6mr_multiaddr = castAddr.addr6.sin6_addr;mcast.ipv6mr_interface = bindAddr.addr6.sin6_scope_id;if(::SSO_SetSocketOption(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mcast, sizeof(mcast)) == SOCKET_ERROR)return FALSE;if(::SSO_SetSocketOption(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (PVOID)(&bindAddr.addr6.sin6_scope_id), sizeof(UINT)) == SOCKET_ERROR)return FALSE;}return TRUE;}int WaitForSocketWrite(SOCKET sock, DWORD dwTimeout){timeval tv = {(__time_t)(dwTimeout / 1000), (__suseconds_t)((dwTimeout % 1000) * 1000)};fd_set wfds, efds;FD_ZERO(&wfds);FD_ZERO(&efds);FD_SET(sock, &wfds);FD_SET(sock, &efds);int rs = NO_EINTR_INT(select(sock + 1, nullptr, &wfds, &efds, &tv));if(rs <= 0) return ((rs == 0) ? ERROR_TIMEOUT : ENSURE_ERROR(ERROR_CANT_WAIT));if(FD_ISSET(sock, &efds)){rs = SSO_GetError(sock);return ((rs != NO_ERROR && rs != SOCKET_ERROR) ? rs : ENSURE_ERROR(ERROR_CANT_WAIT));}VERIFY(FD_ISSET(sock, &wfds));rs = SSO_GetError(sock);if(!IS_NO_ERROR(rs))return ((rs != SOCKET_ERROR) ? rs : ENSURE_ERROR(ERROR_CANT_WAIT));return NO_ERROR;}ULONGLONG NToH64(ULONGLONG value){return (((ULONGLONG)ntohl((UINT)((value << 32) >> 32))) << 32) | ntohl((UINT)(value >> 32));}ULONGLONG HToN64(ULONGLONG value){return (((ULONGLONG)htonl((UINT)((value << 32) >> 32))) << 32) | htonl((UINT)(value >> 32));}BOOL IsLittleEndian(){static const USHORT _s_endian_test_value = 0x0102;static const BOOL _s_bLE = (*((BYTE*)&_s_endian_test_value) == 0x02);return _s_bLE;}USHORT HToLE16(USHORT value){return IsLittleEndian() ? value : ENDIAN_SWAP_16(value);}USHORT HToBE16(USHORT value){return IsLittleEndian() ? ENDIAN_SWAP_16(value) : value;}DWORD HToLE32(DWORD value){return IsLittleEndian() ? value : ENDIAN_SWAP_32(value);}DWORD HToBE32(DWORD value){return IsLittleEndian() ? ENDIAN_SWAP_32(value) : value;}HRESULT ReadSmallFile(LPCTSTR lpszFileName, CFile& file, CFileMapping& fmap, DWORD dwMaxFileSize){ASSERT(lpszFileName != nullptr);if(file.Open(lpszFileName, O_RDONLY)){SIZE_T dwSize;if(file.GetSize(dwSize)){if(dwSize > 0 && dwSize <= dwMaxFileSize){if(fmap.Map(file, dwSize))return NO_ERROR;}else if(dwSize == 0)::SetLastError(ERROR_EMPTY);else::SetLastError(ERROR_FILE_TOO_LARGE);}}HRESULT rs = ::GetLastError();return (!IS_NO_ERROR(rs) ? rs : ERROR_UNKNOWN);}HRESULT MakeSmallFilePackage(LPCTSTR lpszFileName, CFile& file, CFileMapping& fmap, WSABUF szBuf[3], const LPWSABUF pHead, const LPWSABUF pTail){DWORD dwMaxFileSize = MAX_SMALL_FILE_SIZE - (pHead ? pHead->len : 0) - (pTail ? pTail->len : 0);ASSERT(dwMaxFileSize <= MAX_SMALL_FILE_SIZE);HRESULT hr = ReadSmallFile(lpszFileName, file, fmap, dwMaxFileSize);if(IS_NO_ERROR(hr)){szBuf[1].len = (UINT)fmap.Size();szBuf[1].buf = fmap;if(pHead) memcpy(&szBuf[0], pHead, sizeof(WSABUF));else memset(&szBuf[0], 0, sizeof(WSABUF));if(pTail) memcpy(&szBuf[2], pTail, sizeof(WSABUF));else memset(&szBuf[2], 0, sizeof(WSABUF));}return hr;}///////////////////////////////////////////////////////////////////////////////////////////////////////int SSO_SetSocketOption(SOCKET sock, int level, int name, LPVOID val, int len){return setsockopt(sock, level, name, val, (socklen_t)len);}int SSO_GetSocketOption(SOCKET sock, int level, int name, LPVOID val, int* len){return getsockopt(sock, level, name, val, (socklen_t*)len);}int SSO_IoctlSocket(SOCKET sock, long cmd, PVOID arg){return ioctl(sock, cmd, arg);}int SSO_NoBlock(SOCKET sock, BOOL bNoBlock){return fcntl_SETFL(sock, O_NONBLOCK, bNoBlock) ? NO_ERROR : SOCKET_ERROR;}int SSO_NoDelay(SOCKET sock, BOOL bNoDelay){int val = bNoDelay ? 1 : 0;return setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));}int SSO_DontLinger(SOCKET sock, BOOL bDont){return SSO_Linger(sock, 0, 0);}int SSO_Linger(SOCKET sock, int l_onoff, int l_linger){linger ln = {l_onoff, l_linger};return setsockopt(sock, SOL_SOCKET, SO_LINGER, &ln, sizeof(linger));}int SSO_KeepAlive(SOCKET sock, BOOL bKeepAlive){int val = bKeepAlive ? 1 : 0;return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(int));}int SSO_KeepAliveVals(SOCKET sock, BOOL bOnOff, DWORD dwIdle, DWORD dwInterval, DWORD dwCount){if(bOnOff){dwIdle /= 1000;dwInterval /= 1000;if(dwIdle == 0 || dwInterval == 0 || dwCount == 0){::WSASetLastError(ERROR_INVALID_PARAMETER);return SOCKET_ERROR;}}BOOL isOK = IS_NO_ERROR(SSO_KeepAlive(sock, bOnOff));if(isOK && bOnOff){isOK &= IS_NO_ERROR(setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &dwIdle, sizeof(DWORD)));isOK &= IS_NO_ERROR(setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &dwInterval, sizeof(DWORD)));isOK &= IS_NO_ERROR(setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &dwCount, sizeof(DWORD)));}return isOK ? NO_ERROR : SOCKET_ERROR;}int SSO_ReuseAddress(SOCKET sock, EnReuseAddressPolicy opt){int iSet = 1;int iUnSet = 0;int rs = NO_ERROR;BOOL bReusePortSupported =#if defined(__linux) || defined(__linux__)::IsKernelVersionAbove(2, 6, 32);#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__) || defined(__MACH__)TRUE;#elseFALSE;#endifif(opt == RAP_NONE){rs = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &iUnSet, sizeof(int));if(bReusePortSupported)rs |= setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &iUnSet, sizeof(int));}else if(opt == RAP_ADDR_ONLY){rs = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &iSet, sizeof(int));if(bReusePortSupported)rs |= setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &iUnSet, sizeof(int));}else if(opt == RAP_ADDR_AND_PORT){rs = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &iSet, sizeof(int));if(bReusePortSupported)rs |= setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &iSet, sizeof(int));}else{::SetLastError(ERROR_INVALID_PARAMETER);rs = -1;}return rs;}int SSO_RecvBuffSize(SOCKET sock, int size){return setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(int));}int SSO_SendBuffSize(SOCKET sock, int size){return setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(int));}int SSO_RecvTimeOut(SOCKET sock, int ms){timeval tv;::MillisecondToTimeval(ms, tv);return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(timeval));}int SSO_SendTimeOut(SOCKET sock, int ms){timeval tv;::MillisecondToTimeval(ms, tv);return setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(timeval));}int SSO_GetError(SOCKET sock){int e;socklen_t len = sizeof(e);if(IS_NO_ERROR(getsockopt(sock, SOL_SOCKET, SO_ERROR, &e, &len)))return e;return SOCKET_ERROR;}///////////////////////////////////////////////////////////////////////////////////////////////////////CONNID GenerateConnectionID(){static volatile CONNID s_dwConnID = 0;CONNID dwConnID = ::InterlockedIncrement(&s_dwConnID);if(dwConnID == 0)dwConnID = ::InterlockedIncrement(&s_dwConnID);return dwConnID;}int IsUdpCloseNotify(const BYTE* pData, int iLength){return (iLength == s_iUdpCloseNotifySize &&memcmp(pData, s_szUdpCloseNotify, s_iUdpCloseNotifySize) == 0) ;}int SendUdpCloseNotify(SOCKET sock){return (int)send(sock, (LPCSTR)s_szUdpCloseNotify, s_iUdpCloseNotifySize, 0);}int SendUdpCloseNotify(SOCKET sock, const HP_SOCKADDR& remoteAddr){return (int)sendto(sock, (LPCSTR)s_szUdpCloseNotify, s_iUdpCloseNotifySize, 0, remoteAddr.Addr(), remoteAddr.AddrSize());}int ManualCloseSocket(SOCKET sock, int iShutdownFlag, BOOL bGraceful){if(!bGraceful)SSO_Linger(sock, 1, 0);if(iShutdownFlag != 0xFF)shutdown(sock, iShutdownFlag);return closesocket(sock);}DWORD GuessBase64EncodeBound(DWORD dwSrcLen){return 4 * ((dwSrcLen + 2) / 3);}DWORD GuessBase64DecodeBound(const BYTE* lpszSrc, DWORD dwSrcLen){if(dwSrcLen < 2)return 0;if(lpszSrc[dwSrcLen - 2] == '=')dwSrcLen -= 2;else if(lpszSrc[dwSrcLen - 1] == '=')--dwSrcLen;DWORD dwMod = dwSrcLen % 4;DWORD dwAdd = dwMod == 2 ? 1 : (dwMod == 3 ? 2 : 0);return 3 * (dwSrcLen / 4) + dwAdd;}int Base64Encode(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen){static const BYTE CODES[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";DWORD dwRealLen = GuessBase64EncodeBound(dwSrcLen);if(lpszDest == nullptr || dwDestLen < dwRealLen){dwDestLen = dwRealLen;return -5;}BYTE* p = lpszDest;DWORD leven = 3 * (dwSrcLen / 3);DWORD i = 0;for (; i < leven; i += 3){*p++ = CODES[lpszSrc[0] >> 2];*p++ = CODES[((lpszSrc[0] & 3) << 4) + (lpszSrc[1] >> 4)];*p++ = CODES[((lpszSrc[1] & 0xf) << 2) + (lpszSrc[2] >> 6)];*p++ = CODES[lpszSrc[2] & 0x3f];lpszSrc += 3;}if(i < dwSrcLen){BYTE a = lpszSrc[0];BYTE b = (i + 1 < dwSrcLen) ? lpszSrc[1] : 0;*p++ = CODES[a >> 2];*p++ = CODES[((a & 3) << 4) + (b >> 4)];*p++ = (i + 1 < dwSrcLen) ? CODES[((b & 0xf) << 2)] : '=';*p++ = '=';}ASSERT(dwRealLen == (DWORD)(p - lpszDest));if(dwDestLen > dwRealLen){*p = 0;dwDestLen = dwRealLen;}return 0;}int Base64Decode(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen){static const BYTE MAP[256] ={255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255,255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255};DWORD dwRealLen = GuessBase64DecodeBound(lpszSrc, dwSrcLen);if(lpszDest == nullptr || dwDestLen < dwRealLen){dwDestLen = dwRealLen;return -5;}BYTE c;int g = 3;DWORD i, x, y, z;for(i = x = y = z = 0; i < dwSrcLen || x != 0;){c = i < dwSrcLen ? MAP[lpszSrc[i++]] : 254;if(c == 255) {dwDestLen = 0; return -3;}else if(c == 254) {c = 0; g--;}else if(c == 253) continue;z = (z << 6) | c;if(++x == 4){lpszDest[y++] = (BYTE)((z >> 16) & 255);if (g > 1) lpszDest[y++] = (BYTE)((z >> 8) & 255);if (g > 2) lpszDest[y++] = (BYTE)(z & 255);x = z = 0;}}BOOL isOK = (y == dwRealLen);if(!isOK)dwDestLen = 0;else{if(dwDestLen > dwRealLen){lpszDest[dwRealLen] = 0;dwDestLen = dwRealLen;}}return isOK ? 0 : -3;}DWORD GuessUrlEncodeBound(const BYTE* lpszSrc, DWORD dwSrcLen){DWORD dwAdd = 0;for(DWORD i = 0; i < dwSrcLen; i++){BYTE c = lpszSrc[i];if(!(isalnum(c) || c == ' ' || c == '.' || c == '-' || c == '_' || c == '*'))dwAdd += 2;}return dwSrcLen + dwAdd;}DWORD GuessUrlDecodeBound(const BYTE* lpszSrc, DWORD dwSrcLen){DWORD dwPercent = 0;for(DWORD i = 0; i < dwSrcLen; i++){if(lpszSrc[i] == '%'){++dwPercent;i += 2;}}DWORD dwSub = dwPercent * 2;if(dwSrcLen < dwSub)return 0;return dwSrcLen - dwSub;}int UrlEncode(BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen){BYTE c;DWORD j = 0;if(lpszDest == nullptr || dwDestLen == 0)goto ERROR_DEST_LEN;for(DWORD i = 0; i < dwSrcLen; i++){if(j >= dwDestLen)goto ERROR_DEST_LEN;c = lpszSrc[i];if (isalnum(c) || c == '.' || c == '-' || c == '_' || c == '*')lpszDest[j++] = c;else if(c == ' ')lpszDest[j++] = '+';else{if(j + 3 >= dwDestLen)goto ERROR_DEST_LEN;lpszDest[j++] = '%';HEX_VALUE_TO_DOUBLE_CHAR(lpszDest + j, c);j += 2;}}if(dwDestLen > j){lpszDest[j] = 0;dwDestLen = j;}return 0;ERROR_DEST_LEN:dwDestLen = GuessUrlEncodeBound(lpszSrc, dwSrcLen);return -5;}int UrlDecode(BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen){char c;DWORD j = 0;if(lpszDest == nullptr || dwDestLen == 0)goto ERROR_DEST_LEN;for(DWORD i = 0; i < dwSrcLen; i++){if(j >= dwDestLen)goto ERROR_DEST_LEN;c = lpszSrc[i];if(c == '+')lpszDest[j++] = ' ';else if(c != '%')lpszDest[j++] = c;else{if(i + 2 >= dwSrcLen)goto ERROR_SRC_DATA;lpszDest[j++] = HEX_DOUBLE_CHAR_TO_VALUE(lpszSrc + i + 1);i += 2;}}if(dwDestLen > j){lpszDest[j] = 0;dwDestLen = j;}return 0;ERROR_SRC_DATA:dwDestLen = 0;return -3;ERROR_DEST_LEN:dwDestLen = GuessUrlDecodeBound(lpszSrc, dwSrcLen);return -5;}void DestroyCompressor(IHPCompressor* pCompressor){delete pCompressor;}void DestroyDecompressor(IHPDecompressor* pDecompressor){delete pDecompressor;}#ifdef _ZLIB_SUPPORTCHPZLibCompressor::CHPZLibCompressor(Fn_CompressDataCallback fnCallback, int iWindowBits, int iLevel, int iMethod, int iMemLevel, int iStrategy, DWORD dwBuffSize): m_fnCallback (fnCallback), m_dwBuffSize (dwBuffSize), m_bValid (FALSE){ASSERT(m_fnCallback != nullptr);::ZeroObject(m_Stream);m_bValid = (::deflateInit2(&m_Stream, iLevel, iMethod, iWindowBits, iMemLevel, iStrategy) == Z_OK);}CHPZLibCompressor::~CHPZLibCompressor(){if(m_bValid) ::deflateEnd(&m_Stream);}BOOL CHPZLibCompressor::Reset(){return (m_bValid = (::deflateReset(&m_Stream) == Z_OK));}BOOL CHPZLibCompressor::Process(const BYTE* pData, int iLength, BOOL bLast, PVOID pContext){return ProcessEx(pData, iLength, bLast, FALSE, pContext);}BOOL CHPZLibCompressor::ProcessEx(const BYTE* pData, int iLength, BOOL bLast, BOOL bFlush, PVOID pContext){ASSERT(IsValid() && iLength > 0);if(!IsValid()){::SetLastError(ERROR_INVALID_STATE);return FALSE;}unique_ptr<BYTE[]> szBuff = make_unique<BYTE[]>(m_dwBuffSize);m_Stream.next_in = (z_const Bytef*)pData;m_Stream.avail_in = iLength;BOOL isOK = TRUE;int rs = Z_OK;int flush = bLast ? Z_FINISH : (bFlush ? Z_SYNC_FLUSH : Z_NO_FLUSH);while(m_Stream.avail_in > 0){do{m_Stream.next_out = szBuff.get();m_Stream.avail_out = m_dwBuffSize;rs = ::deflate(&m_Stream, flush);if(rs == Z_STREAM_ERROR){::SetLastError(ERROR_INVALID_DATA);isOK = FALSE;goto ZLIB_COMPRESS_END;}int iRead = (int)(m_dwBuffSize - m_Stream.avail_out);if(iRead == 0)break;if(!m_fnCallback(szBuff.get(), iRead, pContext)){::SetLastError(ERROR_CANCELLED);isOK = FALSE;goto ZLIB_COMPRESS_END;}} while(m_Stream.avail_out == 0);}ZLIB_COMPRESS_END:ASSERT(!isOK || (rs == Z_OK && !bLast) || (rs == Z_STREAM_END && bLast));if(!isOK || bLast) Reset();return isOK;}CHPZLibDecompressor::CHPZLibDecompressor(Fn_DecompressDataCallback fnCallback, int iWindowBits, DWORD dwBuffSize): m_fnCallback (fnCallback), m_dwBuffSize (dwBuffSize), m_bValid (FALSE){ASSERT(m_fnCallback != nullptr);::ZeroObject(m_Stream);m_bValid = (::inflateInit2(&m_Stream, iWindowBits) == Z_OK);}CHPZLibDecompressor::~CHPZLibDecompressor(){if(m_bValid) ::inflateEnd(&m_Stream);}BOOL CHPZLibDecompressor::Reset(){return (m_bValid = (::inflateReset(&m_Stream) == Z_OK));}BOOL CHPZLibDecompressor::Process(const BYTE* pData, int iLength, PVOID pContext){ASSERT(IsValid() && iLength > 0);if(!IsValid()){::SetLastError(ERROR_INVALID_STATE);return FALSE;}unique_ptr<BYTE[]> szBuff = make_unique<BYTE[]>(m_dwBuffSize);m_Stream.next_in = (z_const Bytef*)pData;m_Stream.avail_in = iLength;BOOL isOK = TRUE;int rs = Z_OK;while(m_Stream.avail_in > 0){do{m_Stream.next_out = szBuff.get();m_Stream.avail_out = m_dwBuffSize;rs = ::inflate(&m_Stream, Z_NO_FLUSH);if(rs != Z_OK && rs != Z_STREAM_END){::SetLastError(ERROR_INVALID_DATA);isOK = FALSE;goto ZLIB_DECOMPRESS_END;}int iRead = (int)(m_dwBuffSize - m_Stream.avail_out);if(iRead == 0)break;if(!m_fnCallback(szBuff.get(), iRead, pContext)){::SetLastError(ERROR_CANCELLED);isOK = FALSE;goto ZLIB_DECOMPRESS_END;}} while(m_Stream.avail_out == 0);if(rs == Z_STREAM_END)break;}ZLIB_DECOMPRESS_END:ASSERT(!isOK || rs == Z_OK || rs == Z_STREAM_END);if(!isOK || rs == Z_STREAM_END) Reset();return isOK;}IHPCompressor* CreateZLibCompressor(Fn_CompressDataCallback fnCallback, int iWindowBits, int iLevel, int iMethod, int iMemLevel, int iStrategy, DWORD dwBuffSize){return new CHPZLibCompressor(fnCallback, iWindowBits, iLevel, iMethod, iMemLevel, iStrategy, dwBuffSize);}IHPCompressor* CreateGZipCompressor(Fn_CompressDataCallback fnCallback, int iLevel, int iMethod, int iMemLevel, int iStrategy, DWORD dwBuffSize){return new CHPZLibCompressor(fnCallback, MAX_WBITS + 16, iLevel, iMethod, iMemLevel, iStrategy, dwBuffSize);}IHPDecompressor* CreateZLibDecompressor(Fn_DecompressDataCallback fnCallback, int iWindowBits, DWORD dwBuffSize){return new CHPZLibDecompressor(fnCallback, iWindowBits, dwBuffSize);}IHPDecompressor* CreateGZipDecompressor(Fn_DecompressDataCallback fnCallback, DWORD dwBuffSize){return new CHPZLibDecompressor(fnCallback, MAX_WBITS + 32, dwBuffSize);}int Compress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen){return CompressEx(lpszSrc, dwSrcLen, lpszDest, dwDestLen);}int CompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iLevel, int iMethod, int iWindowBits, int iMemLevel, int iStrategy){z_stream stream;stream.next_in = (z_const Bytef*)lpszSrc;stream.avail_in = dwSrcLen;stream.next_out = lpszDest;stream.avail_out = dwDestLen;stream.zalloc = nullptr;stream.zfree = nullptr;stream.opaque = nullptr;int err = ::deflateInit2(&stream, iLevel, iMethod, iWindowBits, iMemLevel, iStrategy);if(err != Z_OK) return err;err = ::deflate(&stream, Z_FINISH);if(err != Z_STREAM_END){::deflateEnd(&stream);return err == Z_OK ? Z_BUF_ERROR : err;}if(dwDestLen > stream.total_out){lpszDest[stream.total_out] = 0;dwDestLen = (DWORD)stream.total_out;}return ::deflateEnd(&stream);}int Uncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen){return UncompressEx(lpszSrc, dwSrcLen, lpszDest, dwDestLen);}int UncompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iWindowBits){z_stream stream;stream.next_in = (z_const Bytef*)lpszSrc;stream.avail_in = (uInt)dwSrcLen;stream.next_out = lpszDest;stream.avail_out = dwDestLen;stream.zalloc = nullptr;stream.zfree = nullptr;int err = ::inflateInit2(&stream, iWindowBits);if(err != Z_OK) return err;err = ::inflate(&stream, Z_FINISH);if(err != Z_STREAM_END){::inflateEnd(&stream);return (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) ? Z_DATA_ERROR : err;}if(dwDestLen > stream.total_out){lpszDest[stream.total_out] = 0;dwDestLen = (DWORD)stream.total_out;}return inflateEnd(&stream);}DWORD GuessCompressBound(DWORD dwSrcLen, BOOL bGZip){DWORD dwBound = (DWORD)::compressBound(dwSrcLen);if(bGZip) dwBound += 16;return dwBound;}int GZipCompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen){return CompressEx(lpszSrc, dwSrcLen, lpszDest, dwDestLen, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16);}int GZipUncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen){return UncompressEx(lpszSrc, dwSrcLen, lpszDest, dwDestLen, MAX_WBITS + 32);}DWORD GZipGuessUncompressBound(const BYTE* lpszSrc, DWORD dwSrcLen){if(dwSrcLen < 20 || *(USHORT*)lpszSrc != 0x8B1F)return 0;return *(DWORD*)(lpszSrc + dwSrcLen - 4);}#endif#ifdef _BROTLI_SUPPORTCHPBrotliCompressor::CHPBrotliCompressor(Fn_CompressDataCallback fnCallback, int iQuality, int iWindow, int iMode, DWORD dwBuffSize): m_fnCallback (fnCallback), m_iQuality (iQuality), m_iWindow (iWindow), m_iMode (iMode), m_dwBuffSize (dwBuffSize), m_bValid (FALSE){ASSERT(m_fnCallback != nullptr);Reset();}CHPBrotliCompressor::~CHPBrotliCompressor(){if(m_bValid) ::BrotliEncoderDestroyInstance(m_pState);}BOOL CHPBrotliCompressor::Reset(){if(m_bValid) ::BrotliEncoderDestroyInstance(m_pState);m_pState = ::BrotliEncoderCreateInstance(nullptr, nullptr, nullptr);if(m_pState != nullptr){::BrotliEncoderSetParameter(m_pState, BROTLI_PARAM_QUALITY , (UINT)m_iQuality);::BrotliEncoderSetParameter(m_pState, BROTLI_PARAM_LGWIN , (UINT)m_iWindow);::BrotliEncoderSetParameter(m_pState, BROTLI_PARAM_MODE , (UINT)m_iMode);if (m_iWindow > BROTLI_MAX_WINDOW_BITS)::BrotliEncoderSetParameter(m_pState, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE);}return (m_bValid = (m_pState != nullptr));}BOOL CHPBrotliCompressor::Process(const BYTE* pData, int iLength, BOOL bLast, PVOID pContext){return ProcessEx(pData, iLength, bLast, FALSE, pContext);}BOOL CHPBrotliCompressor::ProcessEx(const BYTE* pData, int iLength, BOOL bLast, BOOL bFlush, PVOID pContext){ASSERT(IsValid() && iLength > 0);if(!IsValid()){::SetLastError(ERROR_INVALID_STATE);return FALSE;}unique_ptr<BYTE[]> szBuff = make_unique<BYTE[]>(m_dwBuffSize);const BYTE* pNextInData = pData;size_t iAvlInLen = (SIZE_T)iLength;BYTE* pNextOutData = nullptr;size_t iAvlOutLen = 0;BOOL isOK = TRUE;BrotliEncoderOperation op = bLast ? BROTLI_OPERATION_FINISH : (bFlush ? BROTLI_OPERATION_FLUSH : BROTLI_OPERATION_PROCESS);while(iAvlInLen > 0){do{pNextOutData = szBuff.get();iAvlOutLen = m_dwBuffSize;if(!::BrotliEncoderCompressStream(m_pState, op, &iAvlInLen, &pNextInData, &iAvlOutLen, &pNextOutData, nullptr)){::SetLastError(ERROR_INVALID_DATA);isOK = FALSE;goto BROTLI_COMPRESS_END;}int iRead = (int)(m_dwBuffSize - iAvlOutLen);if(iRead == 0)break;if(!m_fnCallback(szBuff.get(), iRead, pContext)){::SetLastError(ERROR_CANCELLED);isOK = FALSE;goto BROTLI_COMPRESS_END;}} while (iAvlOutLen == 0);}BROTLI_COMPRESS_END:if(!isOK || bLast) Reset();return isOK;}CHPBrotliDecompressor::CHPBrotliDecompressor(Fn_DecompressDataCallback fnCallback, DWORD dwBuffSize): m_fnCallback (fnCallback), m_dwBuffSize (dwBuffSize), m_bValid (FALSE){ASSERT(m_fnCallback != nullptr);Reset();}CHPBrotliDecompressor::~CHPBrotliDecompressor(){if(m_bValid) ::BrotliDecoderDestroyInstance(m_pState);}BOOL CHPBrotliDecompressor::Reset(){if(m_bValid) ::BrotliDecoderDestroyInstance(m_pState);m_pState = ::BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);return (m_bValid = (m_pState != nullptr));}BOOL CHPBrotliDecompressor::Process(const BYTE* pData, int iLength, PVOID pContext){ASSERT(IsValid() && iLength > 0);if(!IsValid()){::SetLastError(ERROR_INVALID_STATE);return FALSE;}unique_ptr<BYTE[]> szBuff = make_unique<BYTE[]>(m_dwBuffSize);const BYTE* pNextInData = pData;size_t iAvlInLen = (SIZE_T)iLength;BYTE* pNextOutData = nullptr;size_t iAvlOutLen = 0;BOOL isOK = TRUE;BrotliDecoderResult rs = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;do{do{pNextOutData = szBuff.get();iAvlOutLen = m_dwBuffSize;rs = ::BrotliDecoderDecompressStream(m_pState, &iAvlInLen, &pNextInData, &iAvlOutLen, &pNextOutData, nullptr);if(rs == BROTLI_DECODER_RESULT_ERROR){::SetLastError(ERROR_INVALID_DATA);isOK = FALSE;goto BROTLI_DECOMPRESS_END;}int iRead = (int)(m_dwBuffSize - iAvlOutLen);if(iRead == 0)break;if(!m_fnCallback(szBuff.get(), iRead, pContext)){::SetLastError(ERROR_CANCELLED);isOK = FALSE;goto BROTLI_DECOMPRESS_END;}} while (iAvlOutLen == 0);if(rs == BROTLI_DECODER_RESULT_SUCCESS)break;} while(rs == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT);BROTLI_DECOMPRESS_END:if(!isOK || rs == BROTLI_DECODER_RESULT_SUCCESS) Reset();return isOK;}IHPCompressor* CreateBrotliCompressor(Fn_CompressDataCallback fnCallback, int iQuality, int iWindow, int iMode, DWORD dwBuffSize){return new CHPBrotliCompressor(fnCallback, iQuality, iWindow, iMode, dwBuffSize);}IHPDecompressor* CreateBrotliDecompressor(Fn_DecompressDataCallback fnCallback, DWORD dwBuffSize){return new CHPBrotliDecompressor(fnCallback, dwBuffSize);}int BrotliCompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen){return BrotliCompressEx(lpszSrc, dwSrcLen, lpszDest, dwDestLen, BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE);}int BrotliCompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iQuality, int iWindow, int iMode){size_t stDestLen = (size_t)dwDestLen;int rs = ::BrotliEncoderCompress(iQuality, iWindow, (BrotliEncoderMode)iMode, (size_t)dwSrcLen, lpszSrc, &stDestLen, lpszDest);dwDestLen = (DWORD)stDestLen;return (rs == 1) ? 0 : ((rs == 3) ? -5 : -3);}int BrotliUncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen){size_t stDestLen = (size_t)dwDestLen;BrotliDecoderResult rs = ::BrotliDecoderDecompress((size_t)dwSrcLen, lpszSrc, &stDestLen, lpszDest);dwDestLen = (DWORD)stDestLen;return (rs == BROTLI_DECODER_RESULT_SUCCESS) ? 0 : ((rs == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) ? -5 : -3);}DWORD BrotliGuessCompressBound(DWORD dwSrcLen){return (DWORD)::BrotliEncoderMaxCompressedSize((size_t)dwSrcLen);}#endif#ifdef _ICONV_SUPPORTBOOL CharsetConvert(LPCSTR lpszFromCharset, LPCSTR lpszToCharset, LPCSTR lpszInBuf, int iInBufLen, LPSTR lpszOutBuf, int& iOutBufLen){ASSERT(lpszInBuf != nullptr);SIZE_T nInBufLeft = iInBufLen;SIZE_T nOutBufLeft = iOutBufLen;int iOutBufSize = iOutBufLen;iOutBufLen = 0;if(lpszInBuf == nullptr){SetLastError(ERROR_INVALID_PARAMETER);return FALSE;}iconv_t ic = iconv_open(lpszToCharset, lpszFromCharset);if(IS_INVALID_PVOID(ic))return FALSE;SIZE_T rs = iconv(ic, (LPSTR*)&lpszInBuf, &nInBufLeft, &lpszOutBuf, &nOutBufLeft);iOutBufLen = iOutBufSize - (int)nOutBufLeft;EXECUTE_RESTORE_ERROR(iconv_close(ic));return !IS_HAS_ERROR(rs);}BOOL GbkToUnicodeEx(const char szSrc[], int iSrcLength, WCHAR szDest[], int& iDestLength){int iInBufLen = (int)((iSrcLength > 0) ? iSrcLength : ((szSrc != nullptr) ? strlen(szSrc) + 1 : 0));int iOutBufLen = (int)(iDestLength * sizeof(WCHAR));BOOL isOK = CharsetConvert(CHARSET_GBK, SYSTEM_CHARSET_UNICODE, szSrc, iInBufLen, (char*)szDest, iOutBufLen);iDestLength = (int)(iOutBufLen / sizeof(WCHAR));return isOK;}BOOL UnicodeToGbkEx(const WCHAR szSrc[], int iSrcLength, char szDest[], int& iDestLength){int iInBufLen = (int)(((iSrcLength > 0) ? iSrcLength : ((szSrc != nullptr) ? wcslen(szSrc) + 1 : 0)) * sizeof(WCHAR));return CharsetConvert(SYSTEM_CHARSET_UNICODE, CHARSET_GBK, (LPCSTR)szSrc, iInBufLen, szDest, iDestLength);}BOOL Utf8ToUnicodeEx(const char szSrc[], int iSrcLength, WCHAR szDest[], int& iDestLength){int iInBufLen = (int)((iSrcLength > 0) ? iSrcLength : ((szSrc != nullptr) ? strlen(szSrc) + 1 : 0));int iOutBufLen = (int)(iDestLength * sizeof(WCHAR));BOOL isOK = CharsetConvert(CHARSET_UTF_8, SYSTEM_CHARSET_UNICODE, szSrc, iInBufLen, (char*)szDest, iOutBufLen);iDestLength = (int)(iOutBufLen / sizeof(WCHAR));return isOK;}BOOL UnicodeToUtf8Ex(const WCHAR szSrc[], int iSrcLength, char szDest[], int& iDestLength){int iInBufLen = (int)(((iSrcLength > 0) ? iSrcLength : ((szSrc != nullptr) ? wcslen(szSrc) + 1 : 0)) * sizeof(WCHAR));return CharsetConvert(SYSTEM_CHARSET_UNICODE, CHARSET_UTF_8, (LPCSTR)szSrc, iInBufLen, szDest, iDestLength);}BOOL GbkToUtf8Ex(const char szSrc[], int iSrcLength, char szDest[], int& iDestLength){int iInBufLen = (int)((iSrcLength > 0) ? iSrcLength : ((szSrc != nullptr) ? strlen(szSrc) + 1 : 0));return CharsetConvert(CHARSET_GBK, CHARSET_UTF_8, szSrc, iInBufLen, szDest, iDestLength);}BOOL Utf8ToGbkEx(const char szSrc[], int iSrcLength, char szDest[], int& iDestLength){int iInBufLen = (int)((iSrcLength > 0) ? iSrcLength : ((szSrc != nullptr) ? strlen(szSrc) + 1 : 0));return CharsetConvert(CHARSET_UTF_8, CHARSET_GBK, szSrc, iInBufLen, szDest, iDestLength);}BOOL GbkToUnicode(const char szSrc[], WCHAR szDest[], int& iDestLength){return GbkToUnicodeEx(szSrc, -1, szDest, iDestLength);}BOOL UnicodeToGbk(const WCHAR szSrc[], char szDest[], int& iDestLength){return UnicodeToGbkEx(szSrc, -1, szDest, iDestLength);}BOOL Utf8ToUnicode(const char szSrc[], WCHAR szDest[], int& iDestLength){return Utf8ToUnicodeEx(szSrc, -1, szDest, iDestLength);}BOOL UnicodeToUtf8(const WCHAR szSrc[], char szDest[], int& iDestLength){return UnicodeToUtf8Ex(szSrc, -1, szDest, iDestLength);}BOOL GbkToUtf8(const char szSrc[], char szDest[], int& iDestLength){return GbkToUtf8Ex(szSrc, -1, szDest, iDestLength);}BOOL Utf8ToGbk(const char szSrc[], char szDest[], int& iDestLength){return Utf8ToGbkEx(szSrc, -1, szDest, iDestLength);}#endif
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。