teleport/client/tp_assist_win/msocketx.cpp

363 lines
7.1 KiB
C++

#include "stdafx.h"
#include "msocketx.h"
#ifdef _WIN32
#pragma warning(disable:4244)
#endif
msocketx::msocketx()
{
m_sock = INVALID_SOCKET;
}
msocketx::~msocketx()
{
close();
}
int msocketx::getsockname(unsigned int& uiip, unsigned short& usport)
{
sockaddr_in addr;
socklen_t ilen = sizeof(addr);
int nret = ::getsockname(m_sock, (sockaddr*)&addr, &ilen);
if (nret != SOCKET_ERROR)
{
uiip = addr.sin_addr.s_addr;
usport = ntohs(addr.sin_port);
}
return nret;
}
int msocketx::shutdown(int ihow)
{
return ::shutdown(m_sock, ihow);
}
int msocketx::closesocket()
{
#ifdef _WIN32
return ::closesocket(m_sock);
#else
return ::close(m_sock);
#endif
}
void msocketx::close()
{
if (isvalid())
{
shutdown(0);
closesocket();
m_sock = INVALID_SOCKET;
}
}
bool msocketx::startup()
{
#ifdef _WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return false;
#endif
return true;
}
bool msocketx::clearup()
{
#ifdef _WIN32
return WSACleanup() == 0;
#endif
return true;
}
int msocketx::getlasterror()
{
#ifdef _WIN32
return WSAGetLastError();
#else
return errno;
#endif
}
void msocketx::attach(SOCKET sock)
{
if (sock == INVALID_SOCKET)
return;
m_sock = sock;
}
bool msocketx::isvalid()
{
return m_sock != INVALID_SOCKET;
}
bool msocketx::setsockbuff(unsigned int uirecvlen /* = 4 * 1024 * 1024 */,
unsigned int uisendlen /* = 4 * 1024 * 1024 */)
{
return (setsockopt(m_sock, SOL_SOCKET, SO_SNDBUF, (char*)&uisendlen, sizeof(uisendlen)) == 0) &&
(setsockopt(m_sock, SOL_SOCKET, SO_RCVBUF, (char*)&uirecvlen, sizeof(uirecvlen)) == 0);
}
bool msocketx::setsocknagle(bool benable /* = true */)
{
socklen_t iflag = (benable ? 0 : 1);
return setsockopt(m_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&iflag, sizeof(iflag)) == 0;
}
bool msocketx::setsocktime(unsigned int uimillisecond /* = 500 */)
{
#ifdef _WIN32
return (setsockopt(m_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&uimillisecond, sizeof(uimillisecond)) == 0) &&
(setsockopt(m_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&uimillisecond, sizeof(uimillisecond)) == 0);
#else
struct timeval timeout;
timeout.tv_sec = uimillisecond / 1000;
timeout.tv_usec = (uimillisecond % 1000) * 1000;
return (setsockopt(m_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)) == 0) &&
(setsockopt(m_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) == 0);
#endif
}
bool msocketx::setsock()
{
return setsockbuff() && setsocktime();
}
bool msocketx::setblock(bool bblock /* = false */)
{
#ifdef _WIN32
u_long b = bblock ? 0 : 1;
return ioctlsocket(m_sock, FIONBIO, &b) == 0;
#else
int flags = fcntl(m_sock, F_GETFL, 0);
if (bblock)
flags |= O_NONBLOCK;
else
flags &= (~O_NONBLOCK);
return fcntl(m_sock, F_SETFL, flags) != -1;
#endif
}
bool msocketx::create(int itype, int iprotocol)
{
if (isvalid())
return true;
m_sock = socket(AF_INET, itype, iprotocol);
return isvalid();
}
bool msocketx::bind(unsigned short usport, const char* pstrip /* = NULL */)
{
sockaddr_in addr = { 0 };
unsigned long nResult = 0;
addr.sin_family = AF_INET;
if (pstrip == NULL)
addr.sin_addr.s_addr = htonl(INADDR_ANY);
else
{
nResult = inet_addr(pstrip);
if (nResult == INADDR_NONE)
return false;
addr.sin_addr.s_addr = nResult;
}
addr.sin_port = htons(usport);
return ::bind(m_sock, (sockaddr*)&addr, sizeof(addr)) == 0;
}
int msocketx::sendto(const void* pbuf, unsigned int ilen, unsigned int uiip, unsigned short usport, int iflags)
{
if (pbuf == NULL)
return -1;
sockaddr_in addr = { 0 };
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = uiip;
addr.sin_port = htons(usport);
return ::sendto(m_sock, (char*)pbuf, ilen, iflags, (sockaddr*)&addr, sizeof(addr));
}
int msocketx::sendto(const void* pbuf, unsigned int ilen, const char* pszip, unsigned short usport, int iflags)
{
if (pbuf == NULL)
return -1;
return sendto(pbuf, ilen, inet_addr(pszip), usport, iflags);
}
int msocketx::recvfrom(void* pbuf, unsigned int ilen, unsigned int& uiip, unsigned short& usport, int iflags)
{
if (pbuf == NULL)
return -1;
sockaddr_in srcaddr = { 0 };
socklen_t iaddrlen = sizeof(srcaddr);
int nret = ::recvfrom(m_sock, (char*)pbuf, ilen, iflags, (sockaddr*)&srcaddr, &iaddrlen);
if (nret != SOCKET_ERROR)
{
usport = htons(srcaddr.sin_port);
uiip = srcaddr.sin_addr.s_addr;
}
return nret;
}
int msocketx::send(const void* pbuf, unsigned int ilen, int iflags)
{
if (pbuf == NULL)
return -1;
return ::send(m_sock, (char*)pbuf, ilen, iflags);
}
int msocketx::recv(void* pbuf, unsigned int ilen, int iflags)
{
if (pbuf == NULL)
return -1;
return ::recv(m_sock, (char*)pbuf, ilen, iflags);
}
bool msocketx::listen(int ibacklog)
{
return ::listen(m_sock, ibacklog) == 0;
}
bool msocketx::accept(SOCKET& sock, sockaddr* peeraddr, socklen_t* addrlen)
{
sock = ::accept(m_sock, peeraddr, addrlen);
return sock != INVALID_SOCKET;
}
bool msocketx::accept(msocketx& sock, sockaddr* peeraddr, socklen_t* addrlen)
{
SOCKET socktmp = ::accept(m_sock, peeraddr, addrlen);
sock.m_sock = socktmp;
return socktmp != INVALID_SOCKET;
}
int msocketx::connect(const char* pszip, unsigned short usport, bool bblock)
{
if (pszip == NULL)
return -1;
if (!isvalid())
{
if (!create(SOCK_STREAM, 0))
return -1;
}
setblock(bblock);
sockaddr_in addr = { 0 };
addr.sin_port = htons(usport);
addr.sin_addr.s_addr = inet_addr(pszip);
addr.sin_family = AF_INET;
return ::connect(m_sock, (sockaddr*)&addr, sizeof(addr));
}
int msocketx::wait(unsigned int uimilli, int iflagx)
{
timeval timeout;
timeout.tv_sec = uimilli / 1000;
timeout.tv_usec = (uimilli % 1000) * 1000;
fd_set *prfds = NULL, *pwfds = NULL, *pefds = NULL;
int iret = 0;
if ((iflagx & CAN_CONNECTX) == CAN_CONNECTX)
{
pwfds = new(std::nothrow) fd_set;
if (pwfds == NULL)
return -1;
pefds = new(std::nothrow) fd_set;
if (pefds == NULL)
{
if (pwfds)
delete pwfds;
return -1;
}
FD_ZERO(pwfds);
FD_ZERO(pefds);
FD_SET(m_sock, pwfds);
FD_SET(m_sock, pefds);
iret = ::select(m_sock + 1, NULL, pwfds, pefds, &timeout);
if (iret > 0)
{
if (FD_ISSET(m_sock, pwfds) || FD_ISSET(m_sock, pefds))
{
int iopt = 0;
socklen_t ioptlen = sizeof(iopt);
if (getsockopt(m_sock, SOL_SOCKET, SO_ERROR, (char*)&iopt, &ioptlen) == 0)
{
if (iopt == 0)
iret = CAN_CONNECTX;
else
iret = SOCKET_ERROR;
}
else
iret = SOCKET_ERROR;
}
}
if (pwfds)
delete pwfds;
if (pefds)
delete pefds;
return iret;
}
if ((iflagx & CAN_READX) == CAN_READX || (iflagx & CAN_ACCEPTX) == CAN_ACCEPTX)
{
prfds = new(std::nothrow) fd_set;
if (prfds == NULL)
return -1;
FD_ZERO(prfds);
FD_SET(m_sock, prfds);
}
if ((iflagx & CAN_WRITEX) == CAN_WRITEX)
{
pwfds = new(std::nothrow) fd_set;
if (pwfds == NULL)
{
if (prfds)
delete prfds;
return -1;
}
FD_ZERO(pwfds);
FD_SET(m_sock, pwfds);
}
iret = ::select(m_sock + 1, prfds, pwfds, NULL, &timeout);
if (iret > 0)
{
int itmp = 0;
if (prfds)
if (FD_ISSET(m_sock, prfds))
itmp |= CAN_READX;
if (pwfds)
if (FD_ISSET(m_sock, pwfds))
itmp |= CAN_WRITEX;
iret = itmp;
}
if (pwfds)
delete pwfds;
if (prfds)
delete prfds;
return iret;
}