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 + -
显示快捷键?