ksocketaddress.cpp

来自「konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版」· C++ 代码 · 共 952 行 · 第 1/2 页

CPP
952
字号
/*  -*- C++ -*- *  Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net> * * *  Permission is hereby granted, free of charge, to any person obtaining *  a copy of this software and associated documentation files (the *  "Software"), to deal in the Software without restriction, including *  without limitation the rights to use, copy, modify, merge, publish, *  distribute, sublicense, and/or sell copies of the Software, and to *  permit persons to whom the Software is furnished to do so, subject to *  the following conditions: * *  The above copyright notice and this permission notice shall be included  *  in all copies or substantial portions of the Software. * *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */#include "config.h"#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <arpa/inet.h>#include <netinet/in.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <qfile.h>#include <qobject.h>#include "klocale.h"#include "ksocketaddress.h"#include "netsupp.h"using namespace KNetwork;#if 0class KIpAddress_localhostV4 : public KIpAddress{public:  KIpAddress_localhostV4()  {    *m_data = htonl(0x7f000001);    m_version = 4;  }};class KIpAddress_localhostV6 : public KIpAddress{public:  KIpAddress_localhostV6()    : KIpAddress(0L, 6)  {    m_data[3] = htonl(1);  }};#endifstatic const char localhostV4_data[] = { 127, 0, 0, 1 };static const char localhostV6_data[] = { 0,0, 0,0,  0,0, 0,0,  0,0, 0,0,  0,0, 0,1 };const KIpAddress KIpAddress::localhostV4(&localhostV4_data, 4);const KIpAddress KIpAddress::localhostV6(&localhostV6_data, 6);const KIpAddress KIpAddress::anyhostV4(0L, 4);const KIpAddress KIpAddress::anyhostV6(0L, 6);// helper function to test if an IPv6 v4-mapped address is equal to its IPv4 counterpartstatic bool check_v4mapped(const Q_UINT32* v6addr, Q_UINT32 v4addr){  // check that the v6 is a v4-mapped address  if (!(v6addr[0] == 0 && v6addr[1] == 0 && v6addr[2] == htonl(0x0000ffff)))    return false;		// not a v4-mapped address  return v6addr[3] == v4addr;}// copy operatorKIpAddress& KIpAddress::operator =(const KIpAddress& other){  m_version = other.m_version;  if (m_version == 4 || m_version == 6)    memcpy(m_data, other.m_data, sizeof(m_data));  return *this;}// comparisonbool KIpAddress::compare(const KIpAddress& other, bool checkMapped) const{  if (m_version == other.m_version)    switch (m_version)      {      case 0:	// both objects are empty	return true;      case 4:	// IPv4 address	return *m_data == *other.m_data;      case 6:	// IPv6 address	// they are 128-bit long, that is, 16 bytes	return memcmp(m_data, other.m_data, 16) == 0;      }  if (checkMapped)    {      // check the possibility of a v4-mapped address being compared to an IPv4 one      if (m_version == 6 && other.m_version == 4 && check_v4mapped(m_data, *other.m_data))	return true;            if (other.m_version == 6 && m_version == 4 && check_v4mapped(other.m_data, *m_data))	return true;    }  return false;}// sets the address to the given addressbool KIpAddress::setAddress(const QString& address){  m_version = 0;  // try to guess the address version  if (address.find(':') != -1)    {#ifdef AF_INET6      // guessing IPv6      Q_UINT32 buf[4];      if (inet_pton(AF_INET6, address.latin1(), buf))	{	  memcpy(m_data, buf, sizeof(m_data));	  m_version = 6;	  return true;	}#endif      return false;    }  else    {      Q_UINT32 buf;      if (inet_pton(AF_INET, address.latin1(), &buf))	{	  *m_data = buf;	  m_version = 4;	  return true;	}      return false;    }  return false;			// can never happen!}bool KIpAddress::setAddress(const char* address){  return setAddress(QString::fromLatin1(address));}// set from binary databool KIpAddress::setAddress(const void* raw, int version){  // this always succeeds  // except if version is invalid  if (version != 4 && version != 6)    return false;  m_version = version;  if (raw != 0L)    memcpy(m_data, raw, version == 4 ? 4 : 16);  else    memset(m_data, 0, 16);  return true;}// presentation formQString KIpAddress::toString() const{  char buf[sizeof "1111:2222:3333:4444:5555:6666:255.255.255.255" + 2];  buf[0] = '\0';  switch (m_version)    {    case 4:      inet_ntop(AF_INET, m_data, buf, sizeof(buf) - 1);      return QString::fromLatin1(buf);    case 6:#ifdef AF_INET6      inet_ntop(AF_INET6, m_data, buf, sizeof(buf) - 1);#endif      return QString::fromLatin1(buf);    }  return QString::null;}/* * An IPv6 socket address * This is taken from RFC 2553. */struct our_sockaddr_in6{# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN  Q_UINT8		sin6_len;  Q_UINT8		sin6_family;# else  //!HAVE_STRUCT_SOCKADDR_SA_LEN  Q_UINT16		sin6_family;# endif  Q_UINT16       	sin6_port;	/* RFC says in_port_t */  Q_UINT32		sin6_flowinfo;  Q_UINT8		sin6_addr[16]; // 24 bytes up to here  Q_UINT32		sin6_scope_id; // 28 bytes total};// useful definitions#define MIN_SOCKADDR_LEN	sizeof(Q_UINT16)#define SOCKADDR_IN_LEN		sizeof(sockaddr_in)#define MIN_SOCKADDR_IN6_LEN	((unsigned long) &(((our_sockaddr_in6*)0)->sin6_scope_id))#define SOCKADDR_IN6_LEN	sizeof(our_sockaddr_in6)#define MIN_SOCKADDR_UN_LEN	(sizeof(Q_UINT16) + sizeof(char))class KNetwork::KSocketAddressData{public:  /*   * Note: maybe this should be virtual   * But since the data is shared via the d pointer, it doesn't really matter   * what one class sees, so will the other   */  class QMixSocketAddressRef : public KInetSocketAddress, public KUnixSocketAddress  {  public:    QMixSocketAddressRef(KSocketAddressData* d)      : KInetSocketAddress(d), KUnixSocketAddress(d)    {    }  };  QMixSocketAddressRef ref;  union  {    struct sockaddr         *generic;    struct sockaddr_in      *in;    struct our_sockaddr_in6 *in6;    struct sockaddr_un      *un;  } addr;  Q_UINT16 curlen, reallen;  KSocketAddressData()    : ref(this)  {    addr.generic = 0L;    curlen = 0;    invalidate();  }  ~KSocketAddressData()  {    if (addr.generic != 0L)      free(addr.generic);  }  inline bool invalid() const  { return reallen == 0; }  inline void invalidate()  { reallen = 0; }  void dup(const sockaddr* sa, Q_UINT16 len, bool clear = true);  void makeipv4()  {    short oldport = 0;    if (!invalid())      switch (addr.generic->sa_family)	{	case AF_INET:	  return;		// nothing to do here#ifdef AF_INET6	case AF_INET6:	  oldport = addr.in6->sin6_port;	  break;#endif	}    // create new space    dup(0L, SOCKADDR_IN_LEN);    addr.in->sin_family = AF_INET;#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN    addr.in->sin_len = SOCKADDR_IN_LEN;#endif    addr.in->sin_port = oldport;  }  void makeipv6()  {    short oldport = 0;    if (!invalid())      switch (addr.generic->sa_family)	{	case AF_INET:	  oldport = addr.in->sin_port;	  break;#ifdef AF_INET6	case AF_INET6:	  return;		// nothing to do here#endif	}    // make room    dup(0L, SOCKADDR_IN6_LEN);#ifdef AF_INET6    addr.in6->sin6_family = AF_INET6;#endif#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN    addr.in6->sin6_len = SOCKADDR_IN6_LEN;#endif    addr.in6->sin6_port = oldport;    // sin6_scope_id and sin6_flowid are zero  }};// create duplicates ofvoid KSocketAddressData::dup(const sockaddr* sa, Q_UINT16 len, bool clear){  if (len < MIN_SOCKADDR_LEN)    {      // certainly invalid      invalidate();      return;    }  if (sa && ((sa->sa_family == AF_INET && len < SOCKADDR_IN_LEN) ||#ifdef AF_INET6	     (sa->sa_family == AF_INET6 && len < MIN_SOCKADDR_IN6_LEN) ||#endif	     (sa->sa_family == AF_UNIX && len < MIN_SOCKADDR_UN_LEN)))    {      // also invalid      invalidate();      return;    }  // good  reallen = len;  if (len > curlen)    {      if (len < 32)	curlen = 32;		// big enough for sockaddr_in and sockaddr_in6      else	curlen = len;      addr.generic = (sockaddr*)realloc(addr.generic, curlen);    }  if (sa != 0L)    {      memcpy(addr.generic, sa, len); // copy      // now, normalise the data      if (addr.generic->sa_family == AF_INET)	reallen = SOCKADDR_IN_LEN; // no need to be larger#ifdef AF_INET6      else if (addr.generic->sa_family == AF_INET6)	{	  // set the extra field (sin6_scope_id)	  	  // the buffer is never smaller than 32 bytes, so this is always	  // allowed	  if (reallen < SOCKADDR_IN6_LEN)	    addr.in6->sin6_scope_id = 0;	  	  reallen = SOCKADDR_IN6_LEN;	}#endif      else if (addr.generic->sa_family == AF_UNIX)	reallen = MIN_SOCKADDR_UN_LEN + strlen(addr.un->sun_path);    }  else if (clear)    {      memset(addr.generic, 0, len);      addr.generic->sa_family = AF_UNSPEC;    }}// default constructorKSocketAddress::KSocketAddress()  : d(new KSocketAddressData){}// constructor from binary dataKSocketAddress::KSocketAddress(const sockaddr *sa, Q_UINT16 len)  : d(new KSocketAddressData){  setAddress(sa, len);}KSocketAddress::KSocketAddress(const KSocketAddress& other)  : d(new(KSocketAddressData)){  *this = other;}KSocketAddress::KSocketAddress(KSocketAddressData *d2)  : d(d2){}KSocketAddress::~KSocketAddress(){  // prevent double-deletion, since we're already being deleted  if (d)    {      d->ref.KInetSocketAddress::d = 0L;      d->ref.KUnixSocketAddress::d = 0L;      delete d;    }}KSocketAddress& KSocketAddress::operator =(const KSocketAddress& other){  if (other.d && !other.d->invalid())    d->dup(other.d->addr.generic, other.d->reallen);  else    d->invalidate();  return *this;}const sockaddr* KSocketAddress::address() const{  if (d->invalid())    return 0L;  return d->addr.generic;}sockaddr* KSocketAddress::address(){  if (d->invalid())    return 0L;  return d->addr.generic;}KSocketAddress& KSocketAddress::setAddress(const sockaddr* sa, Q_UINT16 len){  if (sa != 0L && len >= MIN_SOCKADDR_LEN)    d->dup(sa, len);  else    d->invalidate();  return *this;}Q_UINT16 KSocketAddress::length() const{  if (d->invalid())    return 0;  return d->reallen;}KSocketAddress& KSocketAddress::setLength(Q_UINT16 len)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?