📄 tuple.cxx
字号:
#if defined(HAVE_CONFIG_H)#include "resip/stack/config.hxx"#endif#include "resip/stack/Tuple.hxx"#include "rutil/compat.hxx"#include <iostream>#include <string.h>#include <sys/types.h>#include <cassert>#if !defined (WIN32)#include <arpa/inet.h>#include <netinet/in.h>#if defined(__APPLE__) && !defined(s6_addr16)#define s6_addr16 __u6_addr.__u6_addr16#endif#endif#include "rutil/Data.hxx"#include "rutil/DnsUtil.hxx"#include "rutil/GenericIPAddress.hxx"#include "rutil/HashMap.hxx"#include "rutil/Logger.hxx"#include "resip/stack/Transport.hxx"using namespace resip;#define RESIPROCATE_SUBSYSTEM Subsystem::DNSTuple::Tuple() : mFlowKey(0), transport(0), onlyUseExistingConnection(false), mTransportType(UNKNOWN_TRANSPORT){ sockaddr_in* addr4 = (sockaddr_in*)&mSockaddr; memset(addr4, 0, sizeof(sockaddr_in)); mSockaddr.sa_family = AF_INET;}Tuple::Tuple(const GenericIPAddress& genericAddress, TransportType type, const Data& targetDomain) : mFlowKey(0), transport(0), onlyUseExistingConnection(false), mTransportType(type), mTargetDomain(targetDomain){ setSockaddr(genericAddress);}Tuple::Tuple(const Data& printableAddr, int port, IpVersion ipVer, TransportType type, const Data& targetDomain) : mFlowKey(0), transport(0), onlyUseExistingConnection(false), mTransportType(type), mTargetDomain(targetDomain){ if (ipVer == V4) { memset(&m_anonv4, 0, sizeof(m_anonv4)); m_anonv4.sin_family = AF_INET; m_anonv4.sin_port = htons(port); if (printableAddr.empty()) { m_anonv4.sin_addr.s_addr = htonl(INADDR_ANY); } else { DnsUtil::inet_pton( printableAddr, m_anonv4.sin_addr); } } else {#ifdef USE_IPV6 memset(&m_anonv6, 0, sizeof(m_anonv6)); m_anonv6.sin6_family = AF_INET6; m_anonv6.sin6_port = htons(port); if (printableAddr.empty()) { m_anonv6.sin6_addr = in6addr_any; } else { DnsUtil::inet_pton( printableAddr, m_anonv6.sin6_addr); }#else assert(0);#endif }}Tuple::Tuple(const Data& printableAddr, int port, TransportType ptype, const Data& targetDomain) : mFlowKey(0), transport(0), onlyUseExistingConnection(false), mTransportType(ptype), mTargetDomain(targetDomain){ if (DnsUtil::isIpV4Address(printableAddr)) { memset(&m_anonv4, 0, sizeof(m_anonv4)); DnsUtil::inet_pton( printableAddr, m_anonv4.sin_addr); m_anonv4.sin_family = AF_INET; m_anonv4.sin_port = htons(port); } else {#ifdef USE_IPV6 memset(&m_anonv6, 0, sizeof(m_anonv6)); DnsUtil::inet_pton( printableAddr, m_anonv6.sin6_addr); m_anonv6.sin6_family = AF_INET6; m_anonv6.sin6_port = htons(port);#else assert(0);#endif }}Tuple::Tuple(const in_addr& ipv4, int port, TransportType ptype, const Data& targetDomain) :mFlowKey(0), transport(0), onlyUseExistingConnection(false), mTransportType(ptype), mTargetDomain(targetDomain){ memset(&m_anonv4, 0, sizeof(sockaddr_in)); m_anonv4.sin_addr = ipv4; m_anonv4.sin_port = htons(port); m_anonv4.sin_family = AF_INET;}#ifdef USE_IPV6Tuple::Tuple(const in6_addr& ipv6, int port, TransportType ptype, const Data& targetDomaina) :mFlowKey(0), transport(0), onlyUseExistingConnection(false), mTransportType(ptype), mTargetDomain(targetDomaina){ memset(&m_anonv6, 0, sizeof(sockaddr_in6)); m_anonv6.sin6_addr = ipv6; m_anonv6.sin6_port = htons(port); m_anonv6.sin6_family = AF_INET6;}#endifTuple::Tuple(const struct sockaddr& addr, TransportType ptype, const Data& targetDomain) : mFlowKey(0), transport(0), onlyUseExistingConnection(false), mSockaddr(addr), mTransportType(ptype), mTargetDomain(targetDomain){ if (addr.sa_family == AF_INET) { m_anonv4 = (sockaddr_in&)(addr); }#ifdef USE_IPV6 else if (addr.sa_family == AF_INET6) { m_anonv6 = (sockaddr_in6&)(addr); }#endif else { assert(0); }}voidTuple::setSockaddr(const GenericIPAddress& addr){ if (addr.isVersion4()) { m_anonv4 = addr.v4Address; } else#ifdef USE_IPV6 { m_anonv6 = addr.v6Address; }#else { assert(0); }#endif}voidTuple::writeBinaryToken(const resip::Tuple& tuple,resip::Data& container){ // .bwc. Maybe should just write the raw sockaddr into a buffer, and tack // on the flowid and onlyUseExistingConnection flag. Would require 10 extra // bytes for V6, and 14 extra bytes for V4. // V6: sin6_len(1), sin6_flowinfo(4), flowId(4), onlyUseExistingConnection(1) // V4: sin_family(2 instead of 1), sin_zero(8), flowId(4), onlyUseExistingConnection(1) UInt32 rawToken[6]; memset(&rawToken, 0, 24); rawToken[0] = tuple.mFlowKey; rawToken[1] += (tuple.getType() << 8); rawToken[1] += (tuple.getPort() << 16); if(tuple.ipVersion()==V6) { rawToken[1] += 0x00000001; in6_addr address = reinterpret_cast<const sockaddr_in6&>(tuple.getSockaddr()).sin6_addr; assert(sizeof(address)==16); memcpy(&rawToken[2],&address,16); } else { in_addr address = reinterpret_cast<const sockaddr_in&>(tuple.getSockaddr()).sin_addr; assert(sizeof(address)==4); memcpy(&rawToken[2],&address,4); } if(tuple.onlyUseExistingConnection) { rawToken[1] += 0x00000010; } container.clear(); container.append((char*)&rawToken[0],(tuple.ipVersion()==V6) ? 24 : 12);}TupleTuple::makeTuple(const resip::Data& binaryFlowToken){ if(binaryFlowToken.size()<12) { // !bwc! Should not assert here, since this sort of thing // can come off the wire easily. // TODO Throw an exception here? DebugLog(<<"binary flow token was too small: " << binaryFlowToken.size()); return Tuple(); } const UInt32* rawToken=reinterpret_cast<const UInt32*>(binaryFlowToken.data()); Socket mFlowKey=rawToken[0]; IpVersion version = (rawToken[1] & 0x00000001 ? V6 : V4); if(!((version==V4 && binaryFlowToken.size()==12) || (version==V6 && binaryFlowToken.size()==24))) { DebugLog(<<"Binary flow token is the wrong size for its IP version."); return Tuple(); } bool isRealFlow = (rawToken[1] & 0x00000010 ? true : false); UInt8 temp = (TransportType)((rawToken[1] & 0x00000F00) >> 8); if(temp >= MAX_TRANSPORT) { DebugLog(<<"Garbage transport type in flow token: " << temp ); return Tuple(); } TransportType type = (TransportType)temp; UInt16 port= (rawToken[1] >> 16); if(version==V6) {#ifdef USE_IPV6 in6_addr address; assert(sizeof(address)==16); memcpy(&address,&rawToken[2],16); Tuple result(address,port,type);#else Tuple result(resip::Data::Empty, port, type);#endif result.mFlowKey=mFlowKey; result.onlyUseExistingConnection=isRealFlow; return result; } else { in_addr address; assert(sizeof(address)==4); memcpy(&address,&rawToken[2],4); Tuple result(address,port,type); result.mFlowKey=mFlowKey; result.onlyUseExistingConnection=isRealFlow; return result; } // !bwc! We should never end up down here, regardless of what is in token // This is just here to keep the compiler from whining. assert(0); return Tuple(); }Data Tuple::presentationFormat() const{#ifdef USE_IPV6 if (isV4()) { return Tuple::inet_ntop(*this); } else if (IN6_IS_ADDR_V4MAPPED(&m_anonv6.sin6_addr)) { return DnsUtil::inet_ntop(*(reinterpret_cast<const in_addr*>( (reinterpret_cast<const unsigned char*>(&m_anonv6.sin6_addr) + 12)))); } else { return Tuple::inet_ntop(*this); }#else return Tuple::inet_ntop(*this);#endif}voidTuple::setPort(int port){ if (mSockaddr.sa_family == AF_INET) // v4 { m_anonv4.sin_port = htons(port); } else {#ifdef USE_IPV6 m_anonv6.sin6_port = htons(port);#else assert(0);#endif }}int Tuple::getPort() const{ if (mSockaddr.sa_family == AF_INET) // v4 { return ntohs(m_anonv4.sin_port); } else {#ifdef USE_IPV6 return ntohs(m_anonv6.sin6_port);#else assert(0);#endif } return -1;}boolTuple::isAnyInterface() const{ if (isV4()) { return m_anonv4.sin_addr.s_addr == htonl(INADDR_ANY); }#if defined (USE_IPV6) else { return memcmp(&m_anonv6.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; }#else return false;#endif}boolTuple::isLoopback() const{ if(ipVersion()==V4) { static Tuple loopbackv4("127.0.0.1",0,UNKNOWN_TRANSPORT); return isEqualWithMask(loopbackv4,8,true,true); } else if (ipVersion()==V6) {#ifdef USE_IPV6#if defined(__linux__) || defined(__APPLE__) || defined(WIN32) return IN6_IS_ADDR_LOOPBACK(&(m_anonv6.sin6_addr)) != 0;#else return ((*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[0])) == 0) && (*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[4])) == 0) && (*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[8])) == 0) && (*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[12])) == ntohl(1)));#endif#endif } else { assert(0); } return false;}bool Tuple::isV4() const{ return mSockaddr.sa_family == AF_INET;}IpVersion Tuple::ipVersion() const{ return mSockaddr.sa_family == AF_INET ? V4 : V6;}socklen_tTuple::length() const{ if (mSockaddr.sa_family == AF_INET) // v4 { return sizeof(sockaddr_in); }#ifdef USE_IPV6 else if (mSockaddr.sa_family == AF_INET6) // v6 { return sizeof(sockaddr_in6); }#endif assert(0); return 0;}bool Tuple::operator==(const Tuple& rhs) const{ if (mSockaddr.sa_family == rhs.mSockaddr.sa_family) { if (mSockaddr.sa_family == AF_INET) // v4 { return (m_anonv4.sin_port == rhs.m_anonv4.sin_port && mTransportType == rhs.mTransportType && memcmp(&m_anonv4.sin_addr, &rhs.m_anonv4.sin_addr, sizeof(in_addr)) == 0); } else // v6 {#ifdef USE_IPV6 return (m_anonv6.sin6_port == rhs.m_anonv6.sin6_port && mTransportType == rhs.mTransportType && memcmp(&m_anonv6.sin6_addr, &rhs.m_anonv6.sin6_addr, sizeof(in6_addr)) == 0);#else assert(0); return false;#endif }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -