Files
smartservice_native/hdssd/huslib/Socket.h
T
2026-05-20 03:08:08 +09:00

538 lines
12 KiB
C++

#ifndef SOCKET__H_
#define SOCKET__H_
#ifdef MASS_SERVICE_SERVER
#define FD_SETSIZE 2048
#endif
#ifdef _WIN32
#pragma once
//#pragma comment(lib, "wsock32.lib") // old ver
#pragma comment(lib, "ws2_32.lib")
#if _MSC_VER <= 1200
typedef int socklen_t;
#else
#include <ws2tcpip.h> // getaddrinfo
#endif
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> // sockaddr_in
#include <arpa/inet.h> // inet_ntoa()
#include <netdb.h> // gethostbyname()
#include <fcntl.h>
#include <errno.h>
typedef int SOCKET;
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
#define SD_BOTH SHUT_RDWR
#endif // _WIN32
extern inline int SockErrorNo()
{
#ifdef _WIN32
return WSAGetLastError();
#else
return errno;
#endif
}
extern inline int GetAddrByHostName(const char * pAddress, struct sockaddr_in * pSai) // blocking operation
{
struct hostent * pHe;
// resolve host address
if ((pHe = gethostbyname(pAddress)) == NULL)
{
#if defined(_WIN32) && _MSC_VER <= 1200
return WSAGetLastError();
#else
struct addrinfo aiHints;
struct addrinfo *aiList = NULL;
struct addrinfo *aiPtr = NULL;
int retVal;
memset(&aiHints, 0, sizeof(aiHints));
aiHints.ai_family = AF_INET;
aiHints.ai_socktype = SOCK_STREAM;
aiHints.ai_protocol = IPPROTO_TCP;
if ((retVal = getaddrinfo(pAddress, NULL, &aiHints, &aiList)))
return SockErrorNo();
for(aiPtr = aiList; aiPtr != NULL; aiPtr = aiPtr->ai_next)
{
if (aiPtr->ai_family == AF_INET)
{
memset(pSai, 0, sizeof(struct sockaddr_in));
memcpy(pSai, aiPtr->ai_addr, sizeof(struct sockaddr_in));
freeaddrinfo(aiList);
return 0; // success
}
}
freeaddrinfo(aiList);
return SOCKET_ERROR;
#endif
}
memset(pSai, 0, sizeof(struct sockaddr_in));
pSai->sin_addr.s_addr = *(u_long *)pHe->h_addr_list[0];
pSai->sin_family = AF_INET;
return 0; // success
}
extern inline void SetSockAddr(struct sockaddr_in * pSai, const char * pIp, u_short nPort)
{
memset(pSai, 0, sizeof(struct sockaddr_in));
pSai->sin_addr.s_addr = inet_addr(pIp);
pSai->sin_family = AF_INET;
pSai->sin_port = htons(nPort);
}
//////////////////////////////////////////////////////////////////////////////
class HSocket : public HObject
{
public:
enum
{
#ifdef _WIN32
ERR_TIMEOUT = WSAETIMEDOUT
#else
ERR_TIMEOUT = ETIMEDOUT
#endif
};
public:
HSocket()
{
m_fdSocket = INVALID_SOCKET;
}
virtual ~HSocket()
{
if (m_fdSocket != INVALID_SOCKET)
closesocket(m_fdSocket);
}
inline SOCKET GetSocket();
inline void SetSocket(SOCKET sock);
inline SOCKET Create(int nDomain, int nType, int nProtocol = 0);
inline int Close();
inline int Bind(u_short nPort);
inline int Bind(struct sockaddr_in * psaiLocal);
inline int Bind(const char * pAddress, u_short nPort);
inline int Listen(int nBackLog);
inline SOCKET Accept(HSocket & sockClient, char * pszPeerIp = NULL, u_short * pnPeerPort = NULL);
inline int Connect(struct sockaddr_in * psaiRemote);
inline int Connect(const char * pHostAddress, u_short nPort);
inline int Send(const char * pData, int nLen, int nFlags = 0);
inline int Receive(char * pBuf, int nLen, int nFlags = 0);
inline int SendTo(const char * pData, int nLen, int flags, struct sockaddr_in * pSaiRemote);
inline int ReceiveFrom(char * pBuf, int nLen, int nFlags = 0, struct sockaddr_in * pSaiRemote = NULL, socklen_t * pnSaiLen = NULL);
inline int GetLocalAddress(struct sockaddr_in * psai);
inline int GetLocalAddress(char * pBuf, u_short * pnPort);
inline int GetPeerAddress(struct sockaddr_in * psai);
inline int GetPeerAddress(char * pBuf, u_short * pnPort);
inline int SetSockOpt(int nLevel, int nOptname, const char * pOptval,
int nOptlen);
inline int GetSockOpt(int nLevel, int nOptname, char * pOptval,
int * pnOptlen);
inline int GetSockOptError();
inline int SetNonBlockMode(bool bNonBlock);
//
inline bool TimoutConnect(struct sockaddr_in * psaiRemote, unsigned long nTimeout, bool bRestoreSyncMode, int * pnError);
inline bool TimoutConnect(const char * pHostAddress, u_short nPort, unsigned long nTimeout, bool bRestoreSyncMode, int * pnError);
inline bool WaitForSending(unsigned long nTimeout, int * pnError); // for non-block mode, *pnError = errno or WSAGetLastError()
inline bool WaitForReceiving(unsigned long nTimeout, int * pnError); // for non-block mode, *pnError = errno or WSAGetLastError()
protected:
SOCKET m_fdSocket;
};
inline SOCKET HSocket::GetSocket()
{
return m_fdSocket;
}
inline void HSocket::SetSocket(SOCKET sock)
{
m_fdSocket = sock;
}
inline SOCKET HSocket::Create(int nDomain, int nType, int nProtocol)
{
return (m_fdSocket = socket(nDomain, nType, nProtocol));
}
inline int HSocket::Close()
{
int nResult = closesocket(m_fdSocket);
m_fdSocket = INVALID_SOCKET;
return nResult;
}
inline int HSocket::Bind(u_short nPort)
{
return Bind(NULL, nPort);
}
inline int HSocket::Bind(struct sockaddr_in * psaiLocal)
{
return bind(m_fdSocket, (struct sockaddr *)psaiLocal, sizeof(struct sockaddr));
}
inline int HSocket::Bind(const char * pAddress, u_short nPort)
{
struct sockaddr_in sai;
memset(&sai, 0, sizeof(struct sockaddr_in));
if (pAddress == NULL || pAddress[0] == '\0')
sai.sin_addr.s_addr = htonl(INADDR_ANY);
else
sai.sin_addr.s_addr = inet_addr(pAddress);
sai.sin_family = AF_INET;
sai.sin_port = htons(nPort);
return bind(m_fdSocket, (struct sockaddr *)&sai, sizeof(struct sockaddr));
}
inline int HSocket::Listen(int nBackLog)
{
return listen(m_fdSocket, nBackLog);
}
inline SOCKET HSocket::Accept(HSocket & sockClient, char * pszPeerIp, u_short * pnPeerPort)
{
if (pszPeerIp != NULL || pnPeerPort != NULL)
{
struct sockaddr_in sai;
socklen_t len = sizeof(struct sockaddr);
SOCKET sock = (sockClient.m_fdSocket = accept(m_fdSocket, (struct sockaddr *)&sai, &len));
if (pszPeerIp != NULL)
strcpy(pszPeerIp, inet_ntoa(sai.sin_addr));
if (pnPeerPort != NULL)
*pnPeerPort = ntohs(sai.sin_port);
return sock;
}
return (sockClient.m_fdSocket = accept(m_fdSocket, NULL, NULL));
}
inline int HSocket::Connect(struct sockaddr_in * psaiRemote)
{
return connect(m_fdSocket, (struct sockaddr *)psaiRemote, sizeof(struct sockaddr));
}
inline int HSocket::Connect(const char * pHostAddress, u_short nPort)
{
struct sockaddr_in sai;
memset(&sai, 0, sizeof(struct sockaddr_in));
sai.sin_addr.s_addr = inet_addr(pHostAddress);
sai.sin_family = AF_INET;
sai.sin_port = htons(nPort);
return connect(m_fdSocket, (struct sockaddr *)&sai, sizeof(struct sockaddr));
}
inline int HSocket::Send(const char * pData, int nLen, int nFlags)
{
return send(m_fdSocket, pData, nLen, nFlags);
}
inline int HSocket::Receive(char * pBuf, int nLen, int nFlags)
{
return recv(m_fdSocket, pBuf, nLen, nFlags);
}
inline int HSocket::SendTo(const char * pData, int nLen, int flags, struct sockaddr_in * pSaiRemote)
{
return sendto(m_fdSocket, pData, nLen, flags, (struct sockaddr *)pSaiRemote, sizeof(struct sockaddr));
}
inline int HSocket::ReceiveFrom(char * pBuf, int nLen, int nFlags, struct sockaddr_in * pSaiRemote, socklen_t * pnSaiLen)
{
return recvfrom(m_fdSocket, pBuf, nLen, nFlags, (struct sockaddr *)pSaiRemote, pnSaiLen);
}
inline int HSocket::GetLocalAddress(struct sockaddr_in * psai)
{
socklen_t len = sizeof(struct sockaddr);
return getsockname(m_fdSocket, (struct sockaddr *)psai, &len);
}
inline int HSocket::GetLocalAddress(char * pBuf, u_short * pnPort)
{
struct sockaddr_in sai;
socklen_t len = sizeof(struct sockaddr);
if (getsockname(m_fdSocket, (struct sockaddr *)&sai, &len) < 0)
return SockErrorNo();
if (pBuf)
strcpy(pBuf, inet_ntoa(sai.sin_addr));
if (pnPort)
*pnPort = ntohs(sai.sin_port);
return 0;
}
inline int HSocket::GetPeerAddress(struct sockaddr_in * psai)
{
socklen_t len = sizeof(struct sockaddr);
return getpeername(m_fdSocket, (struct sockaddr *)psai, &len);
}
inline int HSocket::GetPeerAddress(char * pBuf, u_short * pnPort)
{
struct sockaddr_in sai;
socklen_t len = sizeof(struct sockaddr);
if (getpeername(m_fdSocket, (struct sockaddr *)&sai, &len) < 0)
return SockErrorNo();
if (pBuf)
strcpy(pBuf, inet_ntoa(sai.sin_addr));
if (pnPort)
*pnPort = ntohs(sai.sin_port);
return 0;
}
inline int HSocket::SetSockOpt(int nLevel, int nOptname, const char * pOptval, int nOptlen)
{
return setsockopt(m_fdSocket, nLevel, nOptname, pOptval, nOptlen);
}
inline int HSocket::GetSockOpt(int nLevel, int nOptname, char * pOptval, int * pnOptlen)
{
return getsockopt(m_fdSocket, nLevel, nOptname, pOptval, (socklen_t *)pnOptlen);
}
inline int HSocket::GetSockOptError()
{
int nOptVal;
int nOptLen = sizeof(int);
if (getsockopt(m_fdSocket, SOL_SOCKET, SO_ERROR, (char *)(&nOptVal), (socklen_t *)&nOptLen) < 0)
return SockErrorNo();
return nOptVal;
}
inline int HSocket::SetNonBlockMode(bool bNonBlock)
{
#ifdef _WIN32
ULONG nFlags = bNonBlock;
return ioctlsocket(m_fdSocket, FIONBIO, &nFlags);
#else
int nFlags = fcntl(m_fdSocket, F_GETFL, 0);
return fcntl(m_fdSocket, F_SETFL, (bNonBlock ? nFlags | O_NONBLOCK : nFlags & ~O_NONBLOCK));
#endif
}
inline bool HSocket::TimoutConnect(struct sockaddr_in * psaiRemote,
unsigned long nTimeout, bool bRestoreSyncMode, int * pnError)
{
#ifdef _WIN32
ULONG nFlags = 1;
if (ioctlsocket(m_fdSocket, FIONBIO, &nFlags) < 0)
#else
int nFlags = fcntl(m_fdSocket, F_GETFL, 0);
if (fcntl(m_fdSocket, F_SETFL, nFlags | O_NONBLOCK) < 0)
#endif
{
*pnError = SockErrorNo();
return false;
}
socklen_t len = sizeof(struct sockaddr);
int nResult;
if ((nResult = connect(m_fdSocket, (struct sockaddr *)psaiRemote, len)) < 0)
{
*pnError = SockErrorNo();
#ifdef _WIN32
if (*pnError != WSAEINPROGRESS && *pnError != WSAEWOULDBLOCK)
#else
if (*pnError != EINPROGRESS)
#endif
return false;
}
fd_set fsRead, fsWrite;
struct timeval tv;
FD_ZERO(&fsRead);
FD_SET(m_fdSocket, &fsRead);
fsWrite = fsRead;
tv.tv_sec = nTimeout / 1000;
tv.tv_usec = (nTimeout % 1000) * 1000;
if ((nResult = select((int)(m_fdSocket + 1), &fsRead, &fsWrite, NULL, &tv)) == 0)
{
*pnError = ERR_TIMEOUT;
return false;
}
if (FD_ISSET(m_fdSocket, &fsRead) || FD_ISSET(m_fdSocket, &fsWrite))
{
len = sizeof(nResult);
if (getsockopt(m_fdSocket, SOL_SOCKET, SO_ERROR, (char *)&nResult, &len) < 0)
{
*pnError = SOCKET_ERROR;
return false; // Solaris pending error
}
}
else
{
*pnError = SOCKET_ERROR; // select error: m_fdSocket not set
return false;
}
if (bRestoreSyncMode)
{
#ifdef _WIN32
nFlags = 0;
if (ioctlsocket(m_fdSocket, FIONBIO, &nFlags) < 0)
#else
if (fcntl(m_fdSocket, F_SETFL, nFlags) < 0)
#endif
{
*pnError = SockErrorNo();
return false;
}
}
*pnError = 0;
return true;
}
inline bool HSocket::TimoutConnect(const char * pHostAddress, u_short nPort, unsigned long nTimeout, bool bRestoreSyncMode, int * pnError)
{
struct sockaddr_in sai;
memset(&sai, 0, sizeof(struct sockaddr_in));
sai.sin_addr.s_addr = inet_addr(pHostAddress);
sai.sin_family = AF_INET;
sai.sin_port = htons(nPort);
return TimoutConnect(&sai, nTimeout, bRestoreSyncMode, pnError);
}
inline bool HSocket::WaitForSending(unsigned long nTimeout, int * pnError)
{
fd_set fsWrite;
struct timeval tv;
FD_ZERO(&fsWrite);
FD_SET(m_fdSocket, &fsWrite);
tv.tv_sec = nTimeout / 1000;
tv.tv_usec = (nTimeout % 1000) * 1000;
int nResult = select((int)m_fdSocket + 1, NULL, &fsWrite, NULL, nTimeout ? &tv : NULL);
if (nResult < 0)
{
*pnError = SockErrorNo();
return false;
}
if (nResult == 0 || FD_ISSET(m_fdSocket, &fsWrite) == 0)
{
*pnError = ERR_TIMEOUT;
return false;
}
*pnError = 0;
return true;
}
inline bool HSocket::WaitForReceiving(unsigned long nTimeout, int * pnError)
{
fd_set fsRead;
struct timeval tv;
FD_ZERO(&fsRead);
FD_SET(m_fdSocket, &fsRead);
tv.tv_sec = nTimeout / 1000;
tv.tv_usec = (nTimeout % 1000) * 1000;
int nResult = select((int)m_fdSocket + 1, &fsRead, NULL, NULL, nTimeout ? &tv : NULL);
if (nResult < 0)
{
*pnError = SockErrorNo();
return false;
}
if (nResult == 0 || FD_ISSET(m_fdSocket, &fsRead) == 0)
{
*pnError = ERR_TIMEOUT;
return false;
}
*pnError = 0;
return true;
}
//////////////////////////////////////////////////////////////////////////////
extern inline int TcpCompleteSend(SOCKET sock, const char * pszPacket, int nPacketSize)
{
int nSentSize;
const char * pszPacketOffset = pszPacket;
while (nPacketSize > 0)
{
nSentSize = send(sock, pszPacketOffset, nPacketSize, 0);
if (nSentSize <= 0)
{
//HLOG(HLOG_ERROR, "[ERROR], EmailSender, Failed to send.\n");
return -1;
}
nPacketSize -= nSentSize;
pszPacketOffset += nSentSize;
}
return 1;
}
#endif // SOCKET__H_