add supports ipv6 code

This commit is contained in:
root 2018-10-22 22:11:06 -04:00
parent ed4727a484
commit 49b96f7a74
14 changed files with 398 additions and 138 deletions

View File

@ -16,6 +16,8 @@
#include "servant/EndpointInfo.h"
#include "servant/TarsLogger.h"
#include "servant/NetworkUtil.h"
#include "util/tc_socket.h"
namespace tars
{
@ -27,9 +29,10 @@ EndpointInfo::EndpointInfo()
, _weight(-1)
, _weighttype(0)
, _authType(0)
, _isIPv6(false)
{
_setDivision.clear();
memset(&_addr,0,sizeof(struct sockaddr_in));
memset(&_addr,0,sizeof(_addr));
}
EndpointInfo::EndpointInfo(const string& host, uint16_t port, EndpointInfo::EType type, int32_t grid, const string & setDivision, int qos, int weight, unsigned int weighttype, int authType)
@ -43,6 +46,7 @@ EndpointInfo::EndpointInfo(const string& host, uint16_t port, EndpointInfo::ETyp
, _weighttype(weighttype)
, _authType(authType)
{
_isIPv6 = TC_Socket::addressIsIPv6(host);
try
{
if(_weighttype == 0)
@ -59,7 +63,14 @@ EndpointInfo::EndpointInfo(const string& host, uint16_t port, EndpointInfo::ETyp
_weight = (_weight > 100 ? 100 : _weight);
}
NetworkUtil::getAddress(_host, _port, _addr);
if (_isIPv6)
{
NetworkUtil::getAddress(_host, _port, _addr.in6);
}
else
{
NetworkUtil::getAddress(_host, _port, _addr.in);
}
_cmpDesc = createCompareDesc();
@ -139,7 +150,12 @@ uint16_t EndpointInfo::port() const
const struct sockaddr_in& EndpointInfo::addr() const
{
return _addr;
return _addr.in;
}
const struct sockaddr * EndpointInfo::addrPtr() const
{
return _isIPv6 ? (struct sockaddr *)&_addr.in6 : (struct sockaddr *)&_addr.in;
}
EndpointInfo::EType EndpointInfo::type() const

View File

@ -216,6 +216,21 @@ void QueryEpBase::setObjName(const string & sObjName)
}
}
bool isRealEndpoint(const string & s, const string & s1)
{
if (s1.empty())
return true;
const string delim = " \t\n\r";
string::size_type beg;
string::size_type end = 0;
beg = s1.find_first_not_of(delim, end);
if (s1[beg] != 't' && s1[beg] != 'u' && s1[beg] != 's')
return false;
return true;
}
void QueryEpBase::setEndpoints(const string & sEndpoints, set<EndpointInfo> & setEndpoints)
{
if(sEndpoints == "")
@ -227,7 +242,7 @@ void QueryEpBase::setEndpoints(const string & sEndpoints, set<EndpointInfo> & se
bool bFirstWeightType = true;
unsigned int iWeightType = 0;
vector<string> vEndpoints = TC_Common::sepstr<string>(sEndpoints, ":", false);
vector<string> vEndpoints = TC_Common::sepstr<string>(sEndpoints, ":", false, isRealEndpoint);
for (size_t i = 0; i < vEndpoints.size(); ++i)
{

View File

@ -25,18 +25,12 @@
using namespace std;
using namespace tars;
int NetworkUtil::createSocket(bool udp, bool isLocal/* = false*/)
int NetworkUtil::createSocket(bool udp, bool isLocal/* = false*/, bool isIpv6/* = false*/)
{
int fd;
if (udp)
{
fd = socket((isLocal ? PF_LOCAL : PF_INET), SOCK_DGRAM, IPPROTO_UDP);
}
else
{
fd = socket((isLocal ? PF_LOCAL : PF_INET), SOCK_STREAM, IPPROTO_TCP);
}
int domain = isLocal ? PF_LOCAL : (isIpv6 ? PF_INET6 : PF_INET);
int type = udp ? SOCK_DGRAM : SOCK_STREAM;
int protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
int fd = socket(domain, type, protocol);
if (fd == INVALID_SOCKET)
{
@ -127,6 +121,17 @@ void NetworkUtil::doBind(int fd, struct sockaddr_in& addr)
getsockname(fd, reinterpret_cast<struct sockaddr*>(&addr), &len);
}
void NetworkUtil::doBind(int fd, const struct sockaddr *addr, socklen_t len)
{
if (bind(fd, addr, len) == SOCKET_ERROR)
{
closeSocketNoThrow(fd);
ostringstream os;
os << "doBind ex:(" << errorToString(errno) << ")" << __FILE__ << ":" << __LINE__;
throw TarsNetSocketException(os.str());
}
}
bool NetworkUtil::doConnect(int fd, const struct sockaddr_in& addr)
{
bool bConnected = false;
@ -146,6 +151,19 @@ bool NetworkUtil::doConnect(int fd, const struct sockaddr_in& addr)
return bConnected;
}
bool NetworkUtil::doConnect(int fd, const struct sockaddr *addr, socklen_t len)
{
int iRet = ::connect(fd, addr, len);
if (iRet == -1 && errno != EINPROGRESS)
{
::close(fd);
throw TarsNetConnectException(strerror(errno));
}
return iRet == 0 ? true : false;
}
void NetworkUtil::getAddress(const string& host, int port, struct sockaddr_in& addr)
{
memset(&addr, 0, sizeof(struct sockaddr_in));
@ -188,6 +206,46 @@ void NetworkUtil::getAddress(const string& host, int port, struct sockaddr_in& a
}
}
void NetworkUtil::getAddress(const string& host, int port, struct sockaddr_in6& addr)
{
#define RETRY_TIMES (5)
struct addrinfo *res = NULL;
struct addrinfo hints;
memset(&addr, 0, sizeof(addr));
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET6;
ostringstream os;
os << port;
int ret = -1;
int retry = RETRY_TIMES;
do
{
ret = getaddrinfo(host.c_str(), os.str().c_str(), &hints, &res);
}
while (NULL == res && ret == EAI_AGAIN && --retry >= 0);
if (ret)
{
ostringstream ex;
ex << "DNSException ex:(" << errorToString(errno) << ":" << gai_strerror(ret) << ":" << ret << ")" <<
"|" << host << ":" << port << "| at " << __FUNCTION__ << ":" << __LINE__;
if (res)
{
freeaddrinfo(res);
}
throw TarsNetSocketException(ex.str());
}
assert(res);
assert(res->ai_family == PF_INET6);
memcpy(&addr, res->ai_addr, sizeof(addr));
freeaddrinfo(res);
#undef RETRY_TIMES
}
string NetworkUtil::errorToString(int error)
{
return strerror(error);

View File

@ -89,16 +89,17 @@ void Transceiver::connect()
if (_ep.type() == EndpointInfo::UDP)
{
fd = NetworkUtil::createSocket(true);
fd = NetworkUtil::createSocket(true, false, _ep.isIPv6());
NetworkUtil::setBlock(fd, false);
_connStatus = eConnected;
}
else
{
fd = NetworkUtil::createSocket(false);
fd = NetworkUtil::createSocket(false, false, _ep.isIPv6());
NetworkUtil::setBlock(fd, false);
bool bConnected = NetworkUtil::doConnect(fd, _ep.addr());
socklen_t len = _ep.isIPv6() ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
bool bConnected = NetworkUtil::doConnect(fd, _ep.addrPtr(), len);
if(bConnected)
{
setConnected();

View File

@ -18,7 +18,7 @@
#define __TARS_ENDPOINT_INFO_H_
#include "servant/Global.h"
#include "servant/NetworkUtil.h"
#include "util/tc_socket.h"
using namespace std;
@ -122,6 +122,13 @@ public:
*/
const struct sockaddr_in& addr() const;
/**
* Get ipv4 or ipv6 struct sockaddr
*
* @return const struct sockaddr *
*/
const struct sockaddr * addrPtr() const;
/**
*
*
@ -148,6 +155,12 @@ public:
*/
int authType() const { return _authType; }
/**
* @brief is ipv6 socket or not
* @return true if is ipv6
*/
bool isIPv6() const { return _isIPv6; }
/**
*
* @param r
@ -233,7 +246,11 @@ private:
/**
*
*/
struct sockaddr_in _addr;
union
{
struct sockaddr_in in;
struct sockaddr_in6 in6;
} _addr;
/**
*
@ -249,6 +266,11 @@ private:
*
*/
int _authType;
/**
* _host is IPv6 or not
*/
bool _isIPv6;
};
/////////////////////////////////////////////////////////////////////////////
}

View File

@ -41,7 +41,7 @@ struct NetworkUtil
static const int INVALID_SOCKET = -1;
static const int SOCKET_ERROR = -1;
static int createSocket(bool, bool isLocal = false);
static int createSocket(bool, bool isLocal = false, bool isIpv6 = false);
static void closeSocketNoThrow(int);
@ -53,10 +53,16 @@ struct NetworkUtil
static void doBind(int, struct sockaddr_in&);
static void doBind(int, const struct sockaddr *, socklen_t);
static bool doConnect(int, const struct sockaddr_in&);
static bool doConnect(int, const struct sockaddr *, socklen_t);
static void getAddress(const std::string&, int, struct sockaddr_in&);
static void getAddress(const std::string&, int, struct sockaddr_in6&);
static std::string errorToString(int);
};

View File

@ -76,7 +76,7 @@ public:
typedef TC_LoopQueue<MapStatMicMsg*> stat_queue;
const static int MAX_MASTER_NAME_LEN = 127;
const static int MAX_MASTER_IP_LEN = 20;
const static int MAX_MASTER_IP_LEN = 50;
const static int MAX_REPORT_SIZE = 1400; //上报的最大大小限制
const static int MIN_REPORT_SIZE = 500; //上报的最小大小限制
const static int STAT_PROTOCOL_LEN = 100; //一次stat mic上报纯协议部分占用大小用来控制udp大小防止超MTU

View File

@ -98,6 +98,7 @@ public:
_weight = l._weight;
_weighttype = l._weighttype;
_authType = l._authType;
_isIPv6 = l._isIPv6;
}
/**
@ -119,6 +120,7 @@ public:
_weight = l._weight;
_weighttype = l._weighttype;
_authType = l._authType;
_isIPv6 = l._isIPv6;
}
return *this;
@ -132,7 +134,9 @@ public:
*/
bool operator == (const TC_Endpoint& l)
{
return (_host == l._host && _port == l._port && _timeout == l._timeout && _type == l._type && _grid == l._grid && _qos == l._qos && _weight == l._weight && _weighttype == l._weighttype && _authType == l._authType);
return (_host == l._host && _port == l._port && _timeout == l._timeout && _type == l._type &&
_grid == l._grid && _qos == l._qos && _weight == l._weight && _weighttype == l._weighttype &&
_authType == l._authType && _isIPv6 == l._isIPv6);
}
/**
@ -255,6 +259,12 @@ public:
*/
bool isUnixLocal() const { return _port == 0; }
/**
* @brief is ipv6 socket or not
* @return true if is ipv6
*/
bool isIPv6() const { return _isIPv6; }
/**
* @brief
*/
@ -356,6 +366,11 @@ protected:
*
*/
int _authType;
/**
* _host is ipv6 or not
*/
bool _isIPv6;
};
/*************************************TC_ClientSocket**************************************/
@ -397,6 +412,7 @@ public:
_ip = sIp;
_port = iPort;
_timeout = iTimeout;
_isIPv6 = TC_Socket::addressIsIPv6(sIp);
}
/**
@ -450,6 +466,11 @@ protected:
* ,
*/
int _timeout;
/**
* _ip is ipv6 or not
*/
int _isIPv6;
};
/**

View File

@ -241,6 +241,7 @@ public:
template<typename T>
static T strto(const string &sStr, const string &sDefault);
typedef bool (*depthJudge)(const string& str1, const string& str2);
/**
* @brief ,,vector里
*
@ -255,10 +256,11 @@ public:
* @param sStr
* @param sSep ()
* @param withEmpty true代表空的也算一个元素, false时空的过滤
* @param depthJudge
* @return vector
*/
template<typename T>
static vector<T> sepstr(const string &sStr, const string &sSep, bool withEmpty = false);
static vector<T> sepstr(const string &sStr, const string &sSep, bool withEmpty = false, depthJudge judge = nullptr);
/**
* @brief T型转换成字符串T能够使用ostream对象用<<,
@ -639,45 +641,56 @@ T TC_Common::strto(const string &sStr, const string &sDefault)
template<typename T>
vector<T> TC_Common::sepstr(const string &sStr, const string &sSep, bool withEmpty)
vector<T> TC_Common::sepstr(const string &sStr, const string &sSep, bool withEmpty, TC_Common::depthJudge judge)
{
vector<T> vt;
string::size_type pos = 0;
string::size_type pos1 = 0;
int pos_tmp = -1;
while(true)
{
string s;
string s1;
pos1 = sStr.find_first_of(sSep, pos);
if(pos1 == string::npos)
{
if(pos + 1 <= sStr.length())
{
s = sStr.substr(pos);
s = sStr.substr(-1 != pos_tmp ? pos_tmp : pos);
s1 = "";
}
}
else if(pos1 == pos)
else if(pos1 == pos && (pos1 + 1 == sStr.length()))
{
s = "";
s1 = "";
}
else
{
s = sStr.substr(pos, pos1 - pos);
s = sStr.substr(-1 != pos_tmp ? pos_tmp : pos, pos1 - (-1 != pos_tmp ? pos_tmp : pos));
s1 = sStr.substr(pos1 + 1);
if (-1 == pos_tmp)
pos_tmp = pos;
pos = pos1;
}
if(withEmpty)
if (nullptr == judge || judge(s, s1))
{
vt.push_back(strto<T>(s));
}
else
{
if(!s.empty())
if(withEmpty)
{
T tmp = strto<T>(s);
vt.push_back(tmp);
vt.push_back(strto<T>(s));
}
else
{
if(!s.empty())
{
T tmp = strto<T>(s);
vt.push_back(tmp);
}
}
pos_tmp = -1;
}
if(pos1 == string::npos)

View File

@ -1474,7 +1474,7 @@ public:
*
* @param fd
*/
bool accept(int fd);
bool accept(int fd, int domain = AF_INET);
/**
*

View File

@ -433,7 +433,7 @@ public:
* @throws TC_Socket_Exception
* @return ip
*/
static vector<string> getLocalHosts();
static vector<string> getLocalHosts(int domain = AF_INET);
/**
* @brief socket方式.
@ -464,6 +464,30 @@ public:
*/
static void parseAddr(const string &sAddr, struct in_addr &stAddr);
/**
* @brief , (ipv6或域名), in6_addr结构.
*
* @param sAddr
* @param stAddr
* @throws TC_Socket_Exception
* @return
*/
static void parseAddr(const string &sAddr, struct in6_addr &stAddr);
/**
* @brief: Determine whether an address is ipv6 by including the character ':'
* if address is a domain name, return default(not use now)
* @param addr: ip address or domain name
* @param def_value: if address is a domain name, return default(not use now)
* @return: return true if addr is ipv6, false by ipv4, and default by domain name
*/
static bool addressIsIPv6(const string& addr, bool def_value = false)
{
#define IPv6_ADDRESS_CHAR ':'
return (addr.find(IPv6_ADDRESS_CHAR) != string::npos) ? true : false;
#undef IPv6_ADDRESS_CHAR
}
/**
* @brief .
*

View File

@ -19,6 +19,7 @@
#include "util/tc_clientsocket.h"
#include "util/tc_epoller.h"
#include "util/tc_common.h"
#include "util/tc_socket.h"
namespace tars
{
@ -33,6 +34,7 @@ TC_Endpoint::TC_Endpoint()
_weight = -1;
_weighttype = 0;
_authType = 0;
_isIPv6 = false;
}
void TC_Endpoint::init(const string& host, int port, int timeout, int type, int grid, int qos, int weight, unsigned int weighttype, int authType)
@ -59,6 +61,8 @@ void TC_Endpoint::init(const string& host, int port, int timeout, int type, int
}
_authType = authType;
_isIPv6 = TC_Socket::addressIsIPv6(_host);
}
void TC_Endpoint::parse(const string &str)
@ -239,6 +243,7 @@ void TC_Endpoint::parse(const string &str)
{
const_cast<string&>(_host) = "0.0.0.0";
}
_isIPv6 = TC_Socket::addressIsIPv6(_host);
if (_authType < 0)
_authType = 0;
@ -256,15 +261,7 @@ int TC_TCPClient::checkSocket()
{
try
{
if(_port == 0)
{
_socket.createSocket(SOCK_STREAM, AF_LOCAL);
}
else
{
_socket.createSocket(SOCK_STREAM, AF_INET);
}
_socket.createSocket(SOCK_STREAM, _port ? (_isIPv6 ? AF_INET6 : AF_INET) : AF_LOCAL);
//设置非阻塞模式
_socket.setblock(false);
@ -631,14 +628,7 @@ int TC_UDPClient::checkSocket()
{
try
{
if(_port == 0)
{
_socket.createSocket(SOCK_DGRAM, AF_LOCAL);
}
else
{
_socket.createSocket(SOCK_DGRAM, AF_INET);
}
_socket.createSocket(SOCK_DGRAM, _port ? (_isIPv6 ? AF_INET6 : AF_INET) : AF_LOCAL);
}
catch(TC_Socket_Exception &ex)
{

View File

@ -630,7 +630,7 @@ TC_EpollServer::NetThread::Connection::Connection(TC_EpollServer::BindAdapter *p
_iLastRefreshTime = TNOW;
_sock.init(fd, true, AF_INET);
_sock.init(fd, true, pBindAdapter->_ep.isIPv6() ? AF_INET6 : AF_INET);
}
TC_EpollServer::NetThread::Connection::Connection(BindAdapter *pBindAdapter, int fd)
@ -651,7 +651,7 @@ TC_EpollServer::NetThread::Connection::Connection(BindAdapter *pBindAdapter, int
{
_iLastRefreshTime = TNOW;
_sock.init(fd, false, AF_INET);
_sock.init(fd, false, pBindAdapter->_ep.isIPv6() ? AF_INET6 : AF_INET);
}
TC_EpollServer::NetThread::Connection::Connection(BindAdapter *pBindAdapter)
@ -1583,7 +1583,7 @@ TC_EpollServer::BindAdapterPtr TC_EpollServer::NetThread::getBindAdapter(const s
void TC_EpollServer::NetThread::bind(const TC_Endpoint &ep, TC_Socket &s)
{
int type = ep.isUnixLocal()?AF_LOCAL:AF_INET;
int type = ep.isUnixLocal() ? AF_LOCAL : ep.isIPv6() ? AF_INET6 : AF_INET;
if(ep.isTcp())
{
@ -1698,11 +1698,13 @@ void TC_EpollServer::NetThread::terminate()
_epoller.mod(_shutdown.getfd(), H64(ET_CLOSE), EPOLLOUT);
}
bool TC_EpollServer::NetThread::accept(int fd)
bool TC_EpollServer::NetThread::accept(int fd, int domain)
{
struct sockaddr_in stSockAddr;
struct sockaddr_in stSockAddr4;
struct sockaddr_in6 stSockAddr6;
socklen_t iSockAddrSize = sizeof(sockaddr_in);
socklen_t iSockAddrSize = (AF_INET6 == domain) ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);
struct sockaddr *stSockAddr = (AF_INET6 == domain) ? (struct sockaddr *)&stSockAddr6 : (struct sockaddr *)&stSockAddr4;
TC_Socket cs;
@ -1711,9 +1713,9 @@ bool TC_EpollServer::NetThread::accept(int fd)
//接收连接
TC_Socket s;
s.init(fd, false, AF_INET);
s.init(fd, false, domain);
int iRetCode = s.accept(cs, (struct sockaddr *) &stSockAddr, iSockAddrSize);
int iRetCode = s.accept(cs, stSockAddr, iSockAddrSize);
if (iRetCode > 0)
{
@ -1721,14 +1723,12 @@ bool TC_EpollServer::NetThread::accept(int fd)
uint16_t port;
char sAddr[INET_ADDRSTRLEN] = "\0";
char sAddr[INET6_ADDRSTRLEN] = "\0";
struct sockaddr_in *p = (struct sockaddr_in *)&stSockAddr;
inet_ntop(AF_INET, &p->sin_addr, sAddr, sizeof(sAddr));
inet_ntop(domain, (AF_INET6 == domain) ? (const void *)&stSockAddr6.sin6_addr : (const void *)&stSockAddr4.sin_addr, sAddr, sizeof(sAddr));
ip = sAddr;
port = ntohs(p->sin_port);
port = (AF_INET6 == domain) ? ntohs(stSockAddr6.sin6_port) : ntohs(stSockAddr4.sin_port);
debug("accept [" + ip + ":" + TC_Common::tostr(port) + "] [" + TC_Common::tostr(cs.getfd()) + "] incomming");
@ -2085,7 +2085,7 @@ void TC_EpollServer::NetThread::run()
bool ret;
do
{
ret = accept(ev.data.u32);
ret = accept(ev.data.u32, it->second->_ep.isIPv6() ? AF_INET6 : AF_INET);
}while(ret);
}
}

View File

@ -75,21 +75,19 @@ void TC_Socket::createSocket(int iSocketType, int iDomain)
void TC_Socket::getPeerName(string &sPeerAddress, uint16_t &iPeerPort)
{
assert(_iDomain == AF_INET);
assert(_iDomain == AF_INET && _iDomain == AF_INET6);
struct sockaddr stPeer;
bzero(&stPeer, sizeof(struct sockaddr));
socklen_t iPeerLen = sizeof(sockaddr);
char sAddr[INET6_ADDRSTRLEN] = "\0";
struct sockaddr_in stPeer4;
struct sockaddr_in6 stPeer6;
struct sockaddr *stPeer = (AF_INET6 == _iDomain) ? (struct sockaddr *)&stPeer6 : (struct sockaddr *)&stPeer4;
socklen_t iPeerLen = (AF_INET6 == _iDomain) ? sizeof(stPeer6) : sizeof(stPeer4);
getPeerName(&stPeer, iPeerLen);
char sAddr[INET_ADDRSTRLEN] = "\0";
struct sockaddr_in *p = (struct sockaddr_in *)&stPeer;
inet_ntop(_iDomain, &p->sin_addr, sAddr, sizeof(sAddr));
sPeerAddress= sAddr;
iPeerPort = ntohs(p->sin_port);
bzero(stPeer, iPeerLen);
getPeerName(stPeer, iPeerLen);
inet_ntop(_iDomain, (AF_INET6 == _iDomain) ? (const void*)&stPeer6.sin6_addr : (const void *)&stPeer4.sin_addr, sAddr, sizeof(sAddr));
sPeerAddress = sAddr;
iPeerPort = (AF_INET6 == _iDomain) ? ntohs(stPeer6.sin6_port) : ntohs(stPeer4.sin_port);
}
void TC_Socket::getPeerName(string &sPathName)
@ -114,21 +112,19 @@ void TC_Socket::getPeerName(struct sockaddr *pstPeerAddr, socklen_t &iPeerLen)
void TC_Socket::getSockName(string &sSockAddress, uint16_t &iSockPort)
{
assert(_iDomain == AF_INET);
assert(_iDomain == AF_INET || _iDomain == AF_INET6);
struct sockaddr stSock;
bzero(&stSock, sizeof(struct sockaddr));
socklen_t iSockLen = sizeof(sockaddr);
getSockName(&stSock, iSockLen);
char sAddr[INET_ADDRSTRLEN] = "\0";
struct sockaddr_in *p = (struct sockaddr_in *)&stSock;
inet_ntop(_iDomain, &p->sin_addr, sAddr, sizeof(sAddr));
char sAddr[INET6_ADDRSTRLEN] = "\0";
struct sockaddr_in6 in6;
struct sockaddr_in in4;
struct sockaddr *in = (AF_INET6 == _iDomain) ? (struct sockaddr *)&in6 : (struct sockaddr *)&in4;
socklen_t len = (AF_INET6 == _iDomain) ? sizeof(in6) : sizeof(in4);
bzero(in, len);
getSockName(in, len);
inet_ntop(_iDomain, (AF_INET6 == _iDomain) ? (const void *)&in6.sin6_addr : (const void *)&in4.sin_addr, sAddr, sizeof(sAddr));
sSockAddress = sAddr;
iSockPort = ntohs(p->sin_port);
iSockPort = (AF_INET6 == _iDomain) ? ntohs(in6.sin6_port) : ntohs(in4.sin_port);
}
void TC_Socket::getSockName(string &sPathName)
@ -192,29 +188,80 @@ void TC_Socket::parseAddr(const string &sAddr, struct in_addr &stSinAddr)
}
}
void TC_Socket::parseAddr(const string &sAddr, struct in6_addr &stSinAddr)
{
int iRet = inet_pton(AF_INET6, sAddr.c_str(), &stSinAddr);
if(iRet < 0)
{
throw TC_Socket_Exception("[TC_Socket::parseAddr6] inet_pton error", errno);
}
else if(iRet == 0)
{
struct hostent stHostent;
struct hostent *pstHostent;
char buf[2048] = "\0";
int iError;
gethostbyname2_r(sAddr.c_str(), AF_INET6, &stHostent, buf, sizeof(buf), &pstHostent, &iError);
if (pstHostent == NULL)
{
throw TC_Socket_Exception("[TC_Socket::parseAddr6] gethostbyname2_r error! :" + string(hstrerror(iError)));
}
else
{
if (pstHostent->h_addrtype != AF_INET6)
{
throw TC_Socket_Exception("[TC_Socket::parseAddr6] gethostbyname2_r return addrtype is not AF_INET6");
}
stSinAddr = *(struct in6_addr *) pstHostent->h_addr;
}
}
}
void TC_Socket::bind(const string &sServerAddr, int port)
{
assert(_iDomain == AF_INET);
assert(_iDomain == AF_INET || _iDomain == AF_INET6);
struct sockaddr_in bindAddr;
struct sockaddr_in6 bindAddr6;
struct sockaddr_in bindAddr4;
struct sockaddr *bindAddr = (AF_INET6 == _iDomain) ? (struct sockaddr *)&bindAddr6 : (struct sockaddr *)&bindAddr4;
socklen_t len = (AF_INET6 == _iDomain) ? sizeof(bindAddr6) : sizeof(bindAddr4);
bzero(&bindAddr, sizeof(bindAddr));
bzero(bindAddr, len);
bindAddr.sin_family = _iDomain;
bindAddr.sin_port = htons(port);
if (sServerAddr == "")
if (AF_INET6 == _iDomain)
{
bindAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bindAddr6.sin6_family = _iDomain;
bindAddr6.sin6_port = htons(port);
if (sServerAddr == "")
{
bindAddr6.sin6_addr = in6addr_any;
}
else
{
parseAddr(sServerAddr, bindAddr6.sin6_addr);
}
}
else
{
parseAddr(sServerAddr, bindAddr.sin_addr);
bindAddr4.sin_family = _iDomain;
bindAddr4.sin_port = htons(port);
if (sServerAddr == "")
{
bindAddr4.sin_addr.s_addr = htonl(INADDR_ANY);
}
else
{
parseAddr(sServerAddr, bindAddr4.sin_addr);
}
}
try
{
bind((struct sockaddr *)(&bindAddr), sizeof(bindAddr));
bind(bindAddr, len);
}
catch(...)
{
@ -268,28 +315,41 @@ void TC_Socket::close()
int TC_Socket::connectNoThrow(const string &sServerAddr, uint16_t port)
{
assert(_iDomain == AF_INET);
assert(_iDomain == AF_INET || _iDomain == AF_INET6);
if (sServerAddr == "")
{
throw TC_Socket_Exception("[TC_Socket::connect] server address is empty error!");
}
struct sockaddr_in serverAddr;
bzero(&serverAddr, sizeof(serverAddr));
struct sockaddr_in6 serverAddr6;
struct sockaddr_in serverAddr4;
struct sockaddr *serverAddr = (AF_INET6 == _iDomain) ? (struct sockaddr *)&serverAddr6 : (struct sockaddr *)&serverAddr4;
socklen_t len = (AF_INET6 == _iDomain) ? sizeof(serverAddr6) : sizeof(serverAddr4);
serverAddr.sin_family = _iDomain;
parseAddr(sServerAddr, serverAddr.sin_addr);
serverAddr.sin_port = htons(port);
bzero(serverAddr, len);
return connect((struct sockaddr *)(&serverAddr), sizeof(serverAddr));
if (AF_INET6 == _iDomain)
{
serverAddr6.sin6_family = _iDomain;
parseAddr(sServerAddr, serverAddr6.sin6_addr);
serverAddr6.sin6_port = htons(port);
}
else
{
serverAddr4.sin_family = _iDomain;
parseAddr(sServerAddr, serverAddr4.sin_addr);
serverAddr4.sin_port = htons(port);
}
return connect(serverAddr, len);
}
int TC_Socket::connectNoThrow(struct sockaddr* addr)
{
assert(_iDomain == AF_INET);
assert(_iDomain == AF_INET || _iDomain == AF_INET6);
return connect(addr, sizeof(struct sockaddr));
return connect(addr, (AF_INET6 == _iDomain) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
}
void TC_Socket::connect(const string &sServerAddr, uint16_t port)
@ -349,23 +409,21 @@ int TC_Socket::send(const void *pvBuf, size_t iLen, int iFlag)
int TC_Socket::recvfrom(void *pvBuf, size_t iLen, string &sFromAddr, uint16_t &iFromPort, int iFlags)
{
struct sockaddr stFromAddr;
socklen_t iFromLen = sizeof(struct sockaddr);
struct sockaddr_in *p = (struct sockaddr_in *)&stFromAddr;
int iBytes;
struct sockaddr_in6 stFromAddr6;
struct sockaddr_in stFromAddr4;
struct sockaddr *stFromAddr = (AF_INET6 == _iDomain) ? (struct sockaddr *)&stFromAddr6 : (struct sockaddr *)&stFromAddr4;
socklen_t iFromLen = (AF_INET6 == _iDomain) ? sizeof(stFromAddr6) : sizeof(stFromAddr4);
bzero(&stFromAddr, sizeof(struct sockaddr));
int iBytes = recvfrom(pvBuf, iLen, &stFromAddr, iFromLen, iFlags);
bzero(stFromAddr, iFromLen);
iBytes = recvfrom(pvBuf, iLen, stFromAddr, iFromLen, iFlags);
if (iBytes >= 0)
{
char sAddr[INET_ADDRSTRLEN] = "\0";
inet_ntop(_iDomain, &p->sin_addr, sAddr, sizeof(sAddr));
char sAddr[INET6_ADDRSTRLEN] = "\0";
inet_ntop(_iDomain, (AF_INET6 == _iDomain) ? (const void *)&stFromAddr6.sin6_addr : (const void *)&stFromAddr4.sin_addr, sAddr, sizeof(sAddr));
sFromAddr = sAddr;
iFromPort = ntohs(p->sin_port);
iFromPort = (AF_INET6 == _iDomain) ? ntohs(stFromAddr6.sin6_port) : ntohs(stFromAddr4.sin_port);
}
return iBytes;
}
@ -376,24 +434,43 @@ int TC_Socket::recvfrom(void *pvBuf, size_t iLen, struct sockaddr *pstFromAddr,
int TC_Socket::sendto(const void *pvBuf, size_t iLen, const string &sToAddr, uint16_t port, int iFlags)
{
struct sockaddr_in toAddr;
struct sockaddr_in6 toAddr6;
struct sockaddr_in toAddr4;
struct sockaddr *toAddr = (AF_INET6 == _iDomain) ? (struct sockaddr *)&toAddr6 : (struct sockaddr *)&toAddr4;
socklen_t len = (AF_INET6 == _iDomain) ? sizeof(toAddr6) : sizeof(toAddr4);
bzero(&toAddr, sizeof(struct sockaddr_in));
toAddr.sin_family = _iDomain;
if (sToAddr == "")
bzero(toAddr, len);
if (AF_INET6 == _iDomain)
{
toAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
toAddr6.sin6_family = _iDomain;
if (sToAddr == "")
{
//toAddr.sin6_addr = in6addr_linklocal_allrouters;
}
else
{
parseAddr(sToAddr, toAddr6.sin6_addr);
}
toAddr6.sin6_port = htons(port);
}
else
{
parseAddr(sToAddr, toAddr.sin_addr);
toAddr4.sin_family = _iDomain;
if (sToAddr == "")
{
toAddr4.sin_addr.s_addr = htonl(INADDR_BROADCAST);
}
else
{
parseAddr(sToAddr, toAddr4.sin_addr);
}
toAddr4.sin_port = htons(port);
}
toAddr.sin_port = htons(port);
return sendto(pvBuf, iLen, (struct sockaddr *)(&toAddr), sizeof(toAddr), iFlags);
return sendto(pvBuf, iLen, toAddr, len, iFlags);
}
int TC_Socket::sendto(const void *pvBuf, size_t iLen, struct sockaddr *pstToAddr, socklen_t iToLen, int iFlags)
@ -565,12 +642,12 @@ void TC_Socket::createPipe(int fds[2], bool bBlock)
}
}
vector<string> TC_Socket::getLocalHosts()
vector<string> TC_Socket::getLocalHosts(int domain)
{
vector<string> result;
TC_Socket ts;
ts.createSocket(SOCK_STREAM, AF_INET);
ts.createSocket(SOCK_STREAM, domain);
int cmd = SIOCGIFCONF;
@ -619,6 +696,16 @@ vector<string> TC_Socket::getLocalHosts()
result.push_back(sAddr);
}
}
else if (ifr[i].ifr_addr.sa_family == AF_INET6)
{
struct sockaddr_in6* addr = reinterpret_cast<struct sockaddr_in6*>(&ifr[i].ifr_addr);
if(!memcmp(&addr->sin6_addr, &in6addr_any, sizeof(addr->sin6_addr)))
{
char sAddr[INET6_ADDRSTRLEN] = "\0";
inet_ntop(AF_INET6, &(*addr).sin6_addr, sAddr, sizeof(sAddr));
result.push_back(sAddr);
}
}
}
free(ifc.ifc_buf);
@ -626,5 +713,12 @@ vector<string> TC_Socket::getLocalHosts()
return result;
}
bool addressIsIPv6(const string& addr, bool def_value)
{
#define IPv6_ADDRESS_CHAR ':'
return (addr.find(IPv6_ADDRESS_CHAR) != string::npos) ? true : false;
#undef IPv6_ADDRESS_CHAR
}
}