Serversock supports ipv6

This commit is contained in:
Kirigaya Kazuto 2018-06-03 10:28:04 +08:00
parent 581ee7ea23
commit fc9e9578d9
2 changed files with 96 additions and 13 deletions

100
gsock.cpp
View File

@ -345,13 +345,16 @@ int sock::getpeer(std::string& IPStr,int& Port)
struct serversock::_impl struct serversock::_impl
{ {
public: public:
static int create_socket(vsock::_impl* _vp) int protocol;
bool is_protocol_decided;
int create_socket(vsock::_impl* _vp)
{ {
if (_vp->created) if (_vp->created)
{ {
return GSOCK_INVALID_SOCKET; return GSOCK_INVALID_SOCKET;
} }
_vp->sfd = socket(AF_INET, SOCK_STREAM, 0); _vp->sfd = socket(protocol, SOCK_STREAM, 0);
if (_vp->sfd<0) if (_vp->sfd<0)
{ {
myliblog("socket() returns %d. WSAGetLastError: %d\n", _vp->sfd, WSAGetLastError()); myliblog("socket() returns %d. WSAGetLastError: %d\n", _vp->sfd, WSAGetLastError());
@ -363,31 +366,77 @@ public:
} }
}; };
serversock::serversock(int use_family) :_pp(new _impl)
{
if (use_family==1)
{
_pp->protocol = AF_INET;
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in serversock %p\n", get_family_name(_pp->protocol), this);
}
else if (use_family == 2)
{
_pp->protocol = AF_INET6;
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in serversock %p\n", get_family_name(_pp->protocol), this);
}
else
{
_pp->is_protocol_decided = false;
}
}
int serversock::bind(int Port) int serversock::bind(int Port)
{ {
myliblog("serversock::bind() %p\n",this); myliblog("serversock::bind() %p\n",this);
if (!_vp->created) if (!_vp->created)
{ {
int ret = _impl::create_socket(_vp); if (!_pp->is_protocol_decided)
{
_pp->protocol = AF_INET;
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in serversock %p\n", get_family_name(_pp->protocol), this);
}
int ret = _pp->create_socket(_vp);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
sockaddr_in saddr; if (_pp->protocol == AF_INET)
{
sockaddr_in saddr;
memset(&saddr,0,sizeof(saddr)); memset(&saddr, 0, sizeof(saddr));
saddr.sin_addr.s_addr=INADDR_ANY; saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port=htons(Port); saddr.sin_port = htons(Port);
saddr.sin_family=AF_INET; saddr.sin_family = AF_INET;
return ::bind(_vp->sfd,(sockaddr*)&saddr,sizeof(saddr)); return ::bind(_vp->sfd, (sockaddr*)&saddr, sizeof(saddr));
}
else
{
sockaddr_in6 saddr;
memset(&saddr, 0, sizeof(saddr));
saddr.sin6_addr = in6addr_any;
saddr.sin6_port = htons(Port);
saddr.sin6_family = AF_INET6;
return ::bind(_vp->sfd, (sockaddr*)&saddr, sizeof(saddr));
}
} }
int serversock::set_reuse() int serversock::set_reuse()
{ {
if (!_vp->created) if (!_vp->created)
{ {
int ret = _impl::create_socket(_vp); if (!_pp->is_protocol_decided)
{
_pp->protocol = AF_INET;
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in serversock %p\n", get_family_name(_pp->protocol), this);
}
int ret = _pp->create_socket(_vp);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
@ -397,22 +446,38 @@ int serversock::set_reuse()
int serversock::listen(int MaxCount) int serversock::listen(int MaxCount)
{ {
if (!_vp->created)
{
// Socket is not created. Call bind() first.
return GSOCK_INVALID_SOCKET;
}
return ::listen(_vp->sfd,MaxCount); return ::listen(_vp->sfd,MaxCount);
} }
int serversock::accept(sock& _out_s) int serversock::accept(sock& _out_s)
{ {
if(_out_s._vp->created) if( (!_vp->created) || (_out_s._vp->created) )
{ {
/// _out_s has been connected. /// _out_s has been connected.
return GSOCK_INVALID_SOCKET; return GSOCK_INVALID_SOCKET;
} }
sock s; /// empty socket. sock s; /// empty socket.
sockaddr_in saddr; sockaddr_in saddr;
socklen_t saddrsz=sizeof(saddr); sockaddr_in6 saddr6;
socklen_t saddrsz = (_pp->protocol == AF_INET) ? sizeof(saddr) : sizeof(saddr6);
int ret=::accept(_vp->sfd,(sockaddr*)&(saddr),&saddrsz); int ret;
if (_pp->protocol == AF_INET)
{
ret= ::accept(_vp->sfd, (sockaddr*)&(saddr), &saddrsz);
}
else
{
ret = ::accept(_vp->sfd, (sockaddr*)&(saddr6), &saddrsz);
}
if(ret<0) if(ret<0)
{ {
/// accept() call failed. /// accept() call failed.
@ -492,6 +557,15 @@ udpsock::udpsock(int use_family) : _pp(new _impl)
} }
} }
udpsock::~udpsock()
{
if (_pp)
{
delete _pp;
_pp = nullptr;
}
}
// Convert from IPStr to sockaddr // Convert from IPStr to sockaddr
// Parameters: // Parameters:
// flag_ipv46: // flag_ipv46:

View File

@ -76,6 +76,13 @@ private:
class serversock : public vsock class serversock : public vsock
{ {
public: public:
// use_family:
// 0: Auto (Undecided now) (default)
// 1: IPv4 (If family cannot be automatically decided, then IPv4 will be the default option)
// 2: IPv6
serversock(int use_family=0);
~serversock();
/// Return: /// Return:
/// 0: Bind Succeed. No Error. /// 0: Bind Succeed. No Error.
/// -1: bind() call error. See errno. /// -1: bind() call error. See errno.
@ -96,6 +103,7 @@ public:
int accept(sock& _out_s); int accept(sock& _out_s);
private: private:
struct _impl; struct _impl;
_impl* _pp;
}; };
class udpsock : public vsock class udpsock : public vsock
@ -106,6 +114,7 @@ public:
// 1: IPv4 (If family cannot be automatically decided, then IPv4 will be the default option) // 1: IPv4 (If family cannot be automatically decided, then IPv4 will be the default option)
// 2: IPv6 // 2: IPv6
udpsock(int use_family=0); udpsock(int use_family=0);
~udpsock();
/// Use udp socket as tcp socket. (but of course it is not). /// Use udp socket as tcp socket. (but of course it is not).
/// connect call just copy the target socket data to kernel. See connect() for more info. /// connect call just copy the target socket data to kernel. See connect() for more info.