Fix bug in udpsock::_impl::make_decided

This commit is contained in:
Kirigaya Kazuto 2018-06-06 00:34:22 +08:00
parent 8c449dc774
commit bb97f75944
2 changed files with 77 additions and 70 deletions

View File

@ -522,7 +522,13 @@ struct udpsock::_impl
int protocol; int protocol;
bool is_protocol_decided; bool is_protocol_decided;
int make_decided(vsock::_impl* _vp) _impl()
{
is_protocol_decided = false;
}
// This function is now an internal function and should not be called outside _impl.
int _make_decided(vsock::_impl* _vp)
{ {
if (_vp->created) if (_vp->created)
{ {
@ -539,24 +545,45 @@ struct udpsock::_impl
return GSOCK_OK; return GSOCK_OK;
} }
} }
int try_decide(vsock::_impl* _vp, int in_protocol)
{
if (is_protocol_decided)
{
if (in_protocol == protocol)
{
return GSOCK_OK;
}
else
{
return GSOCK_MISMATCH_PROTOCOL;
}
}
protocol = in_protocol;
// Try it
int ret = _make_decided(_vp);
if (ret == GSOCK_OK)
{
is_protocol_decided = true;
myliblog("Protocol decided to %s in udpsock with _vp %p \n", get_family_name(protocol), _vp);
}
return ret;
}
}; };
udpsock::udpsock(int use_family) : _pp(new _impl) udpsock::udpsock(int use_family) : _pp(new _impl)
{ {
if (use_family == 1) if (use_family == 1)
{ {
_pp->protocol = AF_INET; _pp->try_decide(_vp, AF_INET);
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in udpsock %p\n", get_family_name(_pp->protocol), this); myliblog("Protocol decided to %s in udpsock %p\n", get_family_name(_pp->protocol), this);
_pp->make_decided(_vp);
} }
else if (use_family == 2) else if (use_family == 2)
{ {
_pp->protocol = AF_INET6; _pp->try_decide(_vp, AF_INET6);
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in udpsock %p\n", get_family_name(_pp->protocol), this);
_pp->make_decided(_vp);
} }
else else
{ {
@ -665,17 +692,12 @@ int udpsock::connect(const std::string& IPStr,int Port)
{ {
return GSOCK_INVALID_IP; return GSOCK_INVALID_IP;
} }
else
{ int cret = _pp->try_decide(_vp, (ret == 0) ? (AF_INET) : (AF_INET6));
_pp->protocol = (ret == 0) ? (AF_INET) : (AF_INET6); if (cret < 0)
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in udpsock %p\n", get_family_name(_pp->protocol), this);
int cret = _pp->make_decided(_vp);
if (cret == GSOCK_ERROR_CREAT)
{ {
return cret; return cret;
} }
}
return ::connect(_vp->sfd, (const sockaddr*)paddr, addrsz); return ::connect(_vp->sfd, (const sockaddr*)paddr, addrsz);
} }
@ -702,14 +724,12 @@ int udpsock::broadcast_at(int Port)
} }
else else
{ {
_pp->protocol = AF_INET; int cret = _pp->try_decide(_vp, AF_INET);
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in udpsock %p\n", get_family_name(_pp->protocol), this);
int cret = _pp->make_decided(_vp);
if (cret < 0) if (cret < 0)
{ {
return cret; return cret;
} }
return broadcast_at(Port); return broadcast_at(Port);
} }
} }
@ -723,14 +743,12 @@ int udpsock::set_broadcast()
} }
else else
{ {
_pp->protocol = AF_INET; int cret = _pp->try_decide(_vp, AF_INET);
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in udpsock %p\n", get_family_name(_pp->protocol), this);
int cret = _pp->make_decided(_vp);
if (cret < 0) if (cret < 0)
{ {
return cret; return cret;
} }
return set_broadcast(); return set_broadcast();
} }
} }
@ -762,14 +780,12 @@ int udpsock::bind(int Port)
} }
else else
{ {
_pp->protocol = AF_INET; int cret = _pp->try_decide(_vp, AF_INET);
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in udpsock %p\n", get_family_name(_pp->protocol), this);
int cret = _pp->make_decided(_vp);
if (cret < 0) if (cret < 0)
{ {
return cret; return cret;
} }
return bind(Port); return bind(Port);
} }
} }
@ -785,19 +801,14 @@ int udpsock::sendto(const std::string& IPStr, int Port, const void* buffer, int
(_pp->is_protocol_decided) ? ((_pp->protocol == AF_INET) ? 0 : 1) : -1); (_pp->is_protocol_decided) ? ((_pp->protocol == AF_INET) ? 0 : 1) : -1);
if (ret < 0) if (ret < 0)
{ {
return -4; return GSOCK_INVALID_IP;
} }
else
{ int cret = _pp->try_decide(_vp, AF_INET);
_pp->protocol = (ret == 0) ? (AF_INET) : (AF_INET6);
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in udpsock %p\n", get_family_name(_pp->protocol), this);
int cret = _pp->make_decided(_vp);
if (cret < 0) if (cret < 0)
{ {
return cret; return cret;
} }
}
return ::sendto(_vp->sfd, (const char*)buffer, length, 0, (const sockaddr*)paddr, addrsz); return ::sendto(_vp->sfd, (const char*)buffer, length, 0, (const sockaddr*)paddr, addrsz);
} }
@ -823,10 +834,7 @@ int udpsock::broadcast(int Port,const void* buffer,int length)
} }
else else
{ {
_pp->protocol = AF_INET; int cret = _pp->try_decide(_vp, AF_INET);
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in udpsock %p\n", get_family_name(_pp->protocol), this);
int cret = _pp->make_decided(_vp);
if (cret < 0) if (cret < 0)
{ {
return cret; return cret;
@ -889,14 +897,12 @@ int udpsock::recvfrom(std::string& fromIP, int& fromPort, void* buffer, int buff
} }
else else
{ {
_pp->protocol = AF_INET; int cret = _pp->try_decide(_vp, AF_INET);
_pp->is_protocol_decided = true;
myliblog("Protocol decided to %s in udpsock %p\n", get_family_name(_pp->protocol), this);
int cret = _pp->make_decided(_vp);
if (cret < 0) if (cret < 0)
{ {
return cret; return cret;
} }
return recvfrom(fromIP, fromPort, buffer, bufferLength); return recvfrom(fromIP, fromPort, buffer, bufferLength);
} }
} }

View File

@ -19,6 +19,7 @@ enum
GSOCK_INVALID_IP = -4, // Invalid IP Address (IPv4,IPv6) GSOCK_INVALID_IP = -4, // Invalid IP Address (IPv4,IPv6)
GSOCK_UNKNOWN_PROTOCOL = -5, // Unknown Protocol GSOCK_UNKNOWN_PROTOCOL = -5, // Unknown Protocol
GSOCK_ERROR_NTOP = -6, // inet_ntop failed. GSOCK_ERROR_NTOP = -6, // inet_ntop failed.
GSOCK_MISMATCH_PROTOCOL = -7, // Protocol mismatch.
}; };
class vsock class vsock