2017-07-27 19:52:58 +08:00
|
|
|
/** General Socket Wrapper
|
|
|
|
* Created By Kiritow. (https://github.com/kiritow)
|
|
|
|
* Licensed under MIT
|
|
|
|
*/
|
|
|
|
|
2018-04-23 15:56:05 +08:00
|
|
|
/** See VERSION for version information */
|
2017-07-27 19:52:58 +08:00
|
|
|
|
|
|
|
#include "gsock.h"
|
|
|
|
|
2017-08-15 09:54:10 +08:00
|
|
|
#ifdef GSOCK_DEBUG
|
|
|
|
#pragma message("GSock Debug mode compiled in")
|
|
|
|
#include <cstdio>
|
2018-04-23 15:56:05 +08:00
|
|
|
#define myliblog(fmt,...) printf("GSock: " fmt,__VA_ARGS__)
|
2017-08-15 09:54:10 +08:00
|
|
|
#else
|
2018-04-23 15:56:05 +08:00
|
|
|
#define myliblog(fmt,...)
|
2017-08-15 09:54:10 +08:00
|
|
|
#endif
|
2017-07-27 19:52:58 +08:00
|
|
|
|
2018-04-23 15:56:05 +08:00
|
|
|
#ifdef _WIN32
|
2017-08-15 09:54:10 +08:00
|
|
|
/// Using Win8.1
|
|
|
|
#define _WIN32_WINNT 0x0603
|
|
|
|
|
2017-07-27 19:52:58 +08:00
|
|
|
#include <winsock2.h>
|
|
|
|
#include <ws2tcpip.h>
|
|
|
|
#else
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/epoll.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#define closesocket close
|
|
|
|
using BYTE = unsigned char;
|
|
|
|
#endif
|
|
|
|
|
2018-02-10 13:06:45 +08:00
|
|
|
#include <cstring> /// memset
|
2017-07-27 19:52:58 +08:00
|
|
|
#include <string>
|
|
|
|
#include <stdexcept>
|
2018-05-29 13:36:38 +08:00
|
|
|
#include <vector>
|
2017-07-27 19:52:58 +08:00
|
|
|
|
|
|
|
class _init_winsock2_2_class
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
_init_winsock2_2_class()
|
|
|
|
{
|
|
|
|
/// Windows Platform need WinSock2.DLL initialization.
|
2018-04-23 15:56:05 +08:00
|
|
|
#ifdef _WIN32
|
2017-07-27 19:52:58 +08:00
|
|
|
WORD wd;
|
|
|
|
WSAData wdt;
|
|
|
|
wd=MAKEWORD(2,2);
|
|
|
|
int ret=WSAStartup(wd,&wdt);
|
2017-08-15 09:54:10 +08:00
|
|
|
|
|
|
|
myliblog("WSAStartup() Returns: %d\n",ret);
|
|
|
|
|
2017-07-27 19:52:58 +08:00
|
|
|
if(ret<0)
|
|
|
|
{
|
2017-08-15 09:54:10 +08:00
|
|
|
myliblog("WSAGetLastError: %d\n",WSAGetLastError());
|
2017-07-27 19:52:58 +08:00
|
|
|
throw std::runtime_error("Unable to load winsock2.dll. ");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
~_init_winsock2_2_class()
|
|
|
|
{
|
|
|
|
/// Windows Platform need WinSock2.DLL clean up.
|
2018-04-23 15:56:05 +08:00
|
|
|
#ifdef _WIN32
|
2017-07-27 19:52:58 +08:00
|
|
|
WSACleanup();
|
2017-08-15 09:54:10 +08:00
|
|
|
myliblog("WSACleanup() called.");
|
2017-07-27 19:52:58 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
} _init_winsock2_2_obj;
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
struct vsock::_impl
|
2017-07-27 19:52:58 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
int sfd;
|
|
|
|
bool created;
|
2017-07-27 19:52:58 +08:00
|
|
|
};
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
vsock::vsock() : _vp(new _impl)
|
2017-07-27 19:52:58 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
_vp->created=false;
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
vsock::vsock(vsock&& v)
|
2017-07-27 19:52:58 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
_vp=v._vp;
|
|
|
|
v._vp=nullptr;
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
vsock& vsock::operator = (vsock&& v)
|
2017-07-27 19:52:58 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
this->~vsock();
|
|
|
|
_vp=v._vp;
|
|
|
|
v._vp=nullptr;
|
|
|
|
return *this;
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
vsock::~vsock()
|
2017-07-27 19:52:58 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
if(_vp)
|
|
|
|
{
|
|
|
|
if(_vp->created)
|
|
|
|
{
|
|
|
|
myliblog("Socket closed: [%d] in %p\n",_vp->sfd,this);
|
|
|
|
closesocket(_vp->sfd);
|
|
|
|
|
|
|
|
_vp->created=false;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete _vp;
|
|
|
|
_vp=nullptr;
|
|
|
|
}
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int sock::connect(const std::string& IPStr,int Port)
|
|
|
|
{
|
2017-08-15 09:54:10 +08:00
|
|
|
myliblog("sock::connect() %p\n",this);
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
if(_vp->created)
|
2017-08-15 09:54:10 +08:00
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
2018-05-05 15:37:50 +08:00
|
|
|
_vp->sfd=socket(AF_INET,SOCK_STREAM,0);
|
|
|
|
if(_vp->sfd<0)
|
2017-08-15 09:54:10 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
myliblog("socket() returns %d. WSAGetLastError: %d\n",_vp->sfd,WSAGetLastError());
|
2017-08-15 09:54:10 +08:00
|
|
|
return -3;
|
|
|
|
}
|
|
|
|
myliblog("Socket created: [%d] in %p\n",_pp->sfd,this);
|
2018-05-05 15:37:50 +08:00
|
|
|
_vp->created=true;
|
|
|
|
|
|
|
|
struct sockaddr_in saddr;
|
2017-07-27 19:52:58 +08:00
|
|
|
|
|
|
|
memset(&saddr,0,sizeof(saddr));
|
|
|
|
saddr.sin_addr.s_addr=inet_addr(IPStr.c_str());
|
|
|
|
saddr.sin_port=htons(Port);
|
|
|
|
saddr.sin_family=AF_INET;
|
2017-08-15 09:54:10 +08:00
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
return ::connect(_vp->sfd,(sockaddr*)&saddr,sizeof(saddr));
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
2018-02-11 15:41:52 +08:00
|
|
|
int sock::send(const void* Buffer,int Length)
|
2017-07-27 19:52:58 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
return ::send(_vp->sfd,(const char*)Buffer,Length,0);
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
2018-02-11 15:41:52 +08:00
|
|
|
int sock::recv(void* Buffer,int MaxToRecv)
|
2017-07-27 19:52:58 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
return ::recv(_vp->sfd,(char*)Buffer,MaxToRecv,0);
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int sock::getsendtime(int& _out_Second, int& _out_uSecond)
|
|
|
|
{
|
|
|
|
struct timeval outtime;
|
2018-02-10 13:06:45 +08:00
|
|
|
socklen_t _not_used_t;
|
2018-05-05 15:37:50 +08:00
|
|
|
int ret=getsockopt(_vp->sfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&outtime,&_not_used_t);
|
2017-07-27 19:52:58 +08:00
|
|
|
if(ret<0) return ret;
|
|
|
|
/// We don't know why, but on Windows, 1 Second means 1000.
|
2018-04-23 15:56:05 +08:00
|
|
|
#ifdef _WIN32
|
2017-07-27 19:52:58 +08:00
|
|
|
_out_Second=outtime.tv_sec/1000;
|
|
|
|
_out_uSecond=outtime.tv_usec;
|
|
|
|
#else
|
|
|
|
_out_Second=outtime.tv_sec;
|
|
|
|
_out_uSecond=outtime.tv_usec;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sock::getrecvtime(int& _out_Second, int& _out_uSecond)
|
|
|
|
{
|
|
|
|
struct timeval outtime;
|
2018-02-10 13:06:45 +08:00
|
|
|
socklen_t _not_used_t;
|
2018-05-05 15:37:50 +08:00
|
|
|
int ret=getsockopt(_vp->sfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&outtime,&_not_used_t);
|
2017-07-27 19:52:58 +08:00
|
|
|
if(ret<0) return ret;
|
|
|
|
/// We don't know why, but on Windows, 1 Second means 1000.
|
2018-04-23 15:56:05 +08:00
|
|
|
#ifdef _WIN32
|
2017-07-27 19:52:58 +08:00
|
|
|
_out_Second=outtime.tv_sec/1000;
|
|
|
|
_out_uSecond=outtime.tv_usec;
|
|
|
|
#else
|
|
|
|
_out_Second=outtime.tv_sec;
|
|
|
|
_out_uSecond=outtime.tv_usec;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sock::setsendtime(int Second)
|
|
|
|
{
|
|
|
|
struct timeval outtime;
|
|
|
|
/// We don't know why, but on Windows, 1 Second means 1000.
|
2018-04-23 15:56:05 +08:00
|
|
|
#ifdef _WIN32
|
2017-07-27 19:52:58 +08:00
|
|
|
outtime.tv_sec=Second*1000;
|
|
|
|
outtime.tv_usec=0;
|
|
|
|
#else
|
|
|
|
outtime.tv_sec=Second;
|
|
|
|
outtime.tv_usec=0;
|
|
|
|
#endif
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
return setsockopt(_vp->sfd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&outtime,sizeof(outtime));
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int sock::setrecvtime(int Second)
|
|
|
|
{
|
|
|
|
struct timeval outtime;
|
|
|
|
/// We don't know why, but on Windows, 1 Second means 1000.
|
2018-04-23 15:56:05 +08:00
|
|
|
#ifdef _WIN32
|
2017-07-27 19:52:58 +08:00
|
|
|
outtime.tv_sec=Second*1000;
|
|
|
|
outtime.tv_usec=0;
|
|
|
|
#else
|
|
|
|
outtime.tv_sec=Second;
|
|
|
|
outtime.tv_usec=0;
|
|
|
|
#endif
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
return setsockopt(_vp->sfd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&outtime,sizeof(outtime));
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
2018-05-04 17:44:39 +08:00
|
|
|
//forgive me, but writing code in hospital is really not a good experience.
|
2018-05-09 21:30:34 +08:00
|
|
|
using _sock_getname_callback_t = decltype(getsockname);
|
2018-05-04 18:04:29 +08:00
|
|
|
|
|
|
|
static int _sock_getname_call(int sfd,std::string& ip,int& port,_sock_getname_callback_t fn)
|
2018-05-04 17:44:39 +08:00
|
|
|
{
|
|
|
|
struct sockaddr_in saddr;
|
|
|
|
socklen_t saddrlen=sizeof(saddr);
|
|
|
|
memset(&saddr,0,saddrlen);
|
2018-05-04 18:04:29 +08:00
|
|
|
int ret=fn(sfd,(sockaddr*)&saddr,&saddrlen);
|
|
|
|
if(ret<0) return ret; //don't bother errno. stop here.
|
|
|
|
ip=inet_ntoa(saddr.sin_addr);
|
|
|
|
port=ntohs(saddr.sin_port);
|
2018-05-04 17:44:39 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2017-07-27 19:52:58 +08:00
|
|
|
|
2018-05-04 18:04:29 +08:00
|
|
|
int sock::getlocal(std::string& IPStr,int& Port)
|
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
if(!(_vp->created))
|
2018-05-04 18:04:29 +08:00
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
2018-05-05 15:37:50 +08:00
|
|
|
return _sock_getname_call(_vp->sfd,IPStr,Port,getsockname);
|
2018-05-04 18:04:29 +08:00
|
|
|
}
|
|
|
|
|
2018-05-04 17:44:39 +08:00
|
|
|
int sock::getpeer(std::string& IPStr,int& Port)
|
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
if(!(_vp->created))
|
2018-05-04 18:04:29 +08:00
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
2018-05-05 15:37:50 +08:00
|
|
|
return _sock_getname_call(_vp->sfd,IPStr,Port,getpeername);
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
2018-05-17 19:38:40 +08:00
|
|
|
struct serversock::_impl
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static int create_socket(vsock::_impl* _vp)
|
|
|
|
{
|
|
|
|
if (_vp->created)
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
_vp->sfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
if (_vp->sfd<0)
|
|
|
|
{
|
|
|
|
myliblog("socket() returns %d. WSAGetLastError: %d\n", _vp->sfd, WSAGetLastError());
|
|
|
|
return -3;
|
|
|
|
}
|
|
|
|
myliblog("Socket created: [%d] in %p\n", _vp->sfd, this);
|
|
|
|
_vp->created = true;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-07-27 19:52:58 +08:00
|
|
|
int serversock::bind(int Port)
|
|
|
|
{
|
2017-08-15 09:54:10 +08:00
|
|
|
myliblog("serversock::bind() %p\n",this);
|
|
|
|
|
2018-05-17 19:38:40 +08:00
|
|
|
if (!_vp->created)
|
|
|
|
{
|
|
|
|
int ret = _impl::create_socket(_vp);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
}
|
2018-05-05 15:37:50 +08:00
|
|
|
|
|
|
|
sockaddr_in saddr;
|
2017-07-27 19:52:58 +08:00
|
|
|
|
|
|
|
memset(&saddr,0,sizeof(saddr));
|
|
|
|
saddr.sin_addr.s_addr=INADDR_ANY;
|
|
|
|
saddr.sin_port=htons(Port);
|
|
|
|
saddr.sin_family=AF_INET;
|
2018-05-05 15:37:50 +08:00
|
|
|
return ::bind(_vp->sfd,(sockaddr*)&saddr,sizeof(saddr));
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int serversock::set_reuse()
|
|
|
|
{
|
2018-05-17 19:38:40 +08:00
|
|
|
if (!_vp->created)
|
|
|
|
{
|
|
|
|
int ret = _impl::create_socket(_vp);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
}
|
2018-05-05 15:37:50 +08:00
|
|
|
socklen_t opt=1;
|
|
|
|
return setsockopt(_vp->sfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&opt,sizeof(opt));
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int serversock::listen(int MaxCount)
|
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
return ::listen(_vp->sfd,MaxCount);
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
2017-08-15 09:54:10 +08:00
|
|
|
int serversock::accept(sock& _out_s)
|
2017-07-27 19:52:58 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
if(_out_s._vp->created)
|
2017-08-15 09:54:10 +08:00
|
|
|
{
|
|
|
|
/// _out_s has been connected.
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
sock s; /// empty socket.
|
|
|
|
sockaddr_in saddr;
|
|
|
|
socklen_t saddrsz=sizeof(saddr);
|
|
|
|
|
|
|
|
int ret=::accept(_vp->sfd,(sockaddr*)&(saddr),&saddrsz);
|
2017-07-27 19:52:58 +08:00
|
|
|
if(ret<0)
|
|
|
|
{
|
2017-08-15 09:54:10 +08:00
|
|
|
/// accept() call failed.
|
|
|
|
myliblog("accept() returns %d. WSAGetLastError: %d\n",ret,WSAGetLastError());
|
|
|
|
return -1;
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
s._vp->sfd=ret;
|
|
|
|
s._vp->created=true;
|
2017-07-27 19:52:58 +08:00
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
myliblog("Socket opened: [%d] in %p by serversock %p\n",s._vp->sfd,&s,this);
|
2017-07-27 19:52:58 +08:00
|
|
|
|
2017-08-15 09:54:10 +08:00
|
|
|
/// Move resource.
|
|
|
|
_out_s=std::move(s);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2017-07-27 19:52:58 +08:00
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
udpsock::udpsock()
|
2018-04-23 15:56:05 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
_vp->sfd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
_vp->created = true;
|
2018-04-23 15:56:05 +08:00
|
|
|
}
|
2017-07-27 19:52:58 +08:00
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
int udpsock::connect(const std::string& IPStr,int Port)
|
2018-04-23 15:56:05 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
sockaddr_in saddr;
|
|
|
|
memset(&saddr, 0, sizeof(saddr));
|
|
|
|
saddr.sin_family = AF_INET;
|
|
|
|
saddr.sin_port = htons(Port);
|
|
|
|
saddr.sin_addr.s_addr = inet_addr(IPStr.c_str());
|
|
|
|
|
|
|
|
return ::connect(_vp->sfd,(const sockaddr*)&saddr,sizeof(saddr));
|
2018-04-23 15:56:05 +08:00
|
|
|
}
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
int udpsock::broadcast_at(int Port)
|
2018-04-23 15:56:05 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
sockaddr_in saddr;
|
|
|
|
memset(&saddr, 0, sizeof(saddr));
|
|
|
|
saddr.sin_family = AF_INET;
|
|
|
|
saddr.sin_port = htons(Port);
|
|
|
|
saddr.sin_addr.s_addr = INADDR_BROADCAST;
|
|
|
|
|
|
|
|
return ::connect(_vp->sfd,(const sockaddr*)&saddr,sizeof(saddr));
|
2017-07-27 19:52:58 +08:00
|
|
|
}
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
int udpsock::set_broadcast()
|
2018-04-23 15:56:05 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
socklen_t opt=1;
|
|
|
|
return ::setsockopt(_vp->sfd,SOL_SOCKET,SO_BROADCAST,(const char*)&opt,sizeof(opt));
|
2018-04-23 15:56:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int udpsock::bind(int Port)
|
|
|
|
{
|
|
|
|
sockaddr_in saddr;
|
|
|
|
memset(&saddr, 0, sizeof(saddr));
|
|
|
|
saddr.sin_family = AF_INET;
|
|
|
|
saddr.sin_port = htons(Port);
|
|
|
|
saddr.sin_addr.s_addr = INADDR_ANY;
|
2018-05-05 15:37:50 +08:00
|
|
|
return ::bind(_vp->sfd, (const sockaddr*)&saddr, sizeof(saddr));
|
2018-04-23 15:56:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int udpsock::sendto(const std::string& IPStr, int Port, const void* buffer, int length)
|
|
|
|
{
|
|
|
|
sockaddr_in saddr;
|
|
|
|
memset(&saddr, 0, sizeof(saddr));
|
|
|
|
saddr.sin_family = AF_INET;
|
|
|
|
saddr.sin_port = htons(Port);
|
|
|
|
saddr.sin_addr.s_addr = inet_addr(IPStr.c_str());
|
2018-05-05 15:37:50 +08:00
|
|
|
return ::sendto(_vp->sfd, (const char*)buffer, length, 0, (const sockaddr*)&saddr, sizeof(saddr));
|
|
|
|
}
|
|
|
|
|
|
|
|
int udpsock::broadcast(int Port,const void* buffer,int length)
|
|
|
|
{
|
|
|
|
sockaddr_in saddr;
|
|
|
|
memset(&saddr, 0, sizeof(saddr));
|
|
|
|
saddr.sin_family = AF_INET;
|
|
|
|
saddr.sin_port = htons(Port);
|
|
|
|
saddr.sin_addr.s_addr = INADDR_BROADCAST;
|
|
|
|
return ::sendto(_vp->sfd, (const char*)buffer, length, 0, (const sockaddr*)&saddr, sizeof(saddr));
|
2018-04-23 15:56:05 +08:00
|
|
|
}
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
int udpsock::recvfrom(std::string& fromIP, int& fromPort, void* buffer, int bufferLength)
|
2018-04-23 15:56:05 +08:00
|
|
|
{
|
|
|
|
sockaddr_in saddr;
|
2018-05-04 07:15:30 +08:00
|
|
|
socklen_t saddrlen = sizeof(saddr);
|
2018-05-05 15:37:50 +08:00
|
|
|
int ret = ::recvfrom(_vp->sfd, (char*)buffer, bufferLength, 0, (sockaddr*)&saddr, &saddrlen);
|
2018-04-23 15:56:05 +08:00
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
return ret; /// don't bother errno.
|
2018-04-23 15:56:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fromIP = inet_ntoa(saddr.sin_addr);
|
2018-05-05 15:37:50 +08:00
|
|
|
fromPort = ntohs(saddr.sin_port);
|
2018-04-23 15:56:05 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-05-05 15:37:50 +08:00
|
|
|
int udpsock::send(const void* buffer,int length)
|
|
|
|
{
|
|
|
|
return ::send(_vp->sfd,(const char*)buffer,length,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int udpsock::recv(void* buffer,int bufferLength)
|
2018-04-23 15:56:05 +08:00
|
|
|
{
|
2018-05-05 15:37:50 +08:00
|
|
|
return ::recv(_vp->sfd,(char*)buffer,bufferLength,0);
|
2018-04-23 15:56:05 +08:00
|
|
|
}
|
|
|
|
|
2018-05-29 13:36:38 +08:00
|
|
|
// Select
|
|
|
|
struct selector::_impl
|
|
|
|
{
|
|
|
|
fd_set readset, writeset, errorset;
|
|
|
|
int readsz, writesz, errorsz;
|
|
|
|
};
|
|
|
|
|
|
|
|
selector::selector() : _pp(new _impl)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
selector::~selector()
|
|
|
|
{
|
|
|
|
if (_pp)
|
|
|
|
{
|
|
|
|
delete _pp;
|
|
|
|
_pp = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void selector::clear()
|
|
|
|
{
|
|
|
|
FD_ZERO(&_pp->readset);
|
|
|
|
FD_ZERO(&_pp->writeset);
|
|
|
|
FD_ZERO(&_pp->errorset);
|
|
|
|
_pp->readsz = _pp->writesz = _pp->errorsz = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void selector::add_read(const vsock& v)
|
|
|
|
{
|
|
|
|
if (v._vp->created)
|
|
|
|
{
|
|
|
|
FD_SET(v._vp->sfd, &_pp->readset);
|
|
|
|
++_pp->readsz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void selector::add_write(const vsock& v)
|
|
|
|
{
|
|
|
|
if (v._vp->created)
|
|
|
|
{
|
|
|
|
FD_SET(v._vp->sfd, &_pp->writeset);
|
|
|
|
++_pp->writesz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void selector::add_error(const vsock& v)
|
|
|
|
{
|
|
|
|
if (v._vp->created)
|
|
|
|
{
|
|
|
|
FD_SET(v._vp->sfd, &_pp->errorset);
|
|
|
|
++_pp->errorsz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int selector::wait_for(int second, int ms)
|
|
|
|
{
|
|
|
|
fd_set* pread = (_pp->readsz) ? (&_pp->readset) : NULL;
|
|
|
|
fd_set* pwrite = (_pp->writesz) ? (&_pp->writeset) : NULL;
|
|
|
|
fd_set* perr = (_pp->errorsz) ? (&_pp->errorset) : NULL;
|
|
|
|
|
|
|
|
if (!(pread || pwrite || perr))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct timeval tval;
|
|
|
|
tval.tv_sec = second;
|
|
|
|
tval.tv_usec = ms;
|
|
|
|
|
|
|
|
int ndfs = 0;
|
|
|
|
return ::select(ndfs, pread, pwrite, perr, &tval);
|
|
|
|
}
|
|
|
|
|
|
|
|
int selector::wait()
|
|
|
|
{
|
|
|
|
fd_set* pread = (_pp->readsz) ? (&_pp->readset) : NULL;
|
|
|
|
fd_set* pwrite = (_pp->writesz) ? (&_pp->writeset) : NULL;
|
|
|
|
fd_set* perr = (_pp->errorsz) ? (&_pp->errorset) : NULL;
|
|
|
|
|
|
|
|
if (!(pread || pwrite || perr))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ndfs = 0;
|
|
|
|
return ::select(ndfs, pread, pwrite, perr, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool selector::can_read(const vsock& v)
|
|
|
|
{
|
|
|
|
return FD_ISSET(v._vp->sfd, &_pp->readset);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool selector::can_write(const vsock& v)
|
|
|
|
{
|
|
|
|
return FD_ISSET(v._vp->sfd, &_pp->writeset);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool selector::is_error(const vsock& v)
|
|
|
|
{
|
|
|
|
return FD_ISSET(v._vp->sfd, &_pp->errorset);
|
|
|
|
}
|
|
|
|
|
2018-04-23 15:56:05 +08:00
|
|
|
int DNSResolve(const std::string& HostName, std::string& _out_IPStr)
|
|
|
|
{
|
|
|
|
/// Use getaddrinfo instead
|
|
|
|
struct addrinfo hints;
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = AF_UNSPEC;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
hints.ai_protocol = IPPROTO_TCP;
|
|
|
|
|
|
|
|
struct addrinfo* result = nullptr;
|
|
|
|
|
|
|
|
int ret = getaddrinfo(HostName.c_str(), NULL, &hints, &result);
|
|
|
|
if (ret != 0)
|
|
|
|
{
|
|
|
|
return -1;/// API Call Failed.
|
|
|
|
}
|
|
|
|
for (struct addrinfo* ptr = result; ptr != nullptr; ptr = ptr->ai_next)
|
|
|
|
{
|
|
|
|
switch (ptr->ai_family)
|
|
|
|
{
|
|
|
|
case AF_INET:
|
|
|
|
sockaddr_in * addr = (struct sockaddr_in*) (ptr->ai_addr);
|
|
|
|
_out_IPStr = inet_ntoa(addr->sin_addr);
|
2018-04-27 13:25:32 +08:00
|
|
|
freeaddrinfo(result);
|
2018-04-23 15:56:05 +08:00
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Unknown error.
|
2018-04-27 13:25:32 +08:00
|
|
|
freeaddrinfo(result);
|
2018-04-23 15:56:05 +08:00
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-08-15 09:54:10 +08:00
|
|
|
/// Undefine marcos
|
2018-05-29 13:36:38 +08:00
|
|
|
#undef myliblog
|
|
|
|
|