⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket_address.h

📁 LibTorrent is a BitTorrent library written in C++ for *nix, with a focus on high performance and goo
💻 H
字号:
// rak - Rakshasa's toolbox// Copyright (C) 2005-2006, Jari Sundell//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA//// In addition, as a special exception, the copyright holders give// permission to link the code of portions of this program with the// OpenSSL library under certain conditions as described in each// individual source file, and distribute linked combinations// including the two.//// You must obey the GNU General Public License in all respects for// all of the code used other than OpenSSL.  If you modify file(s)// with this exception, you may extend this exception to your version// of the file(s), but you are not obligated to do so.  If you do not// wish to do so, delete this exception statement from your version.// If you delete this exception statement from all source files in the// program, then also delete it here.//// Contact:  Jari Sundell <jaris@ifi.uio.no>////           Skomakerveien 33//           3185 Skoppum, NORWAY// Wrappers for the various sockaddr types with focus on zero-copy// casting between the original type and the wrapper class.//// The default ctor does not initialize any data.//// _n suffixes indicate that the argument or return value is in// network byte order, _h that they are in hardware byte order.// Add define for inet6 scope id?#ifndef RAK_SOCKET_ADDRESS_H#define RAK_SOCKET_ADDRESS_H#include <cstring>#include <string>#include <stdexcept>#include <arpa/inet.h>#include <netinet/in.h>#include <sys/types.h>#include <sys/socket.h>namespace rak {class socket_address_inet;class socket_address_inet6;class socket_address {public:  static const sa_family_t af_local  = AF_LOCAL;  static const sa_family_t af_unix   = AF_UNIX;  //  static const sa_family_t af_file   = AF_FILE;  static const sa_family_t af_inet   = AF_INET;  static const sa_family_t af_inet6  = AF_INET6;  static const sa_family_t af_unspec = AF_UNSPEC;  bool                is_valid() const;  bool                is_bindable() const;  bool                is_address_any() const;  // Should we need to set AF_UNSPEC?  void                clear()                                 { std::memset(this, 0, sizeof(socket_address)); set_family(); }  sa_family_t         family() const                          { return m_sockaddr.sa_family; }  void                set_family()                            { m_sockaddr.sa_family = af_unspec; }  uint16_t            port() const;  void                set_port(uint16_t p);  std::string         address_str() const;  bool                address_c_str(char* buf, socklen_t size) const;  // Attemts to set it as an inet, then an inet6 address. It will  // never set anything but net addresses, no local/unix.  bool                set_address_str(const std::string& a)   { return set_address_c_str(a.c_str()); }  bool                set_address_c_str(const char* a);  uint32_t            length() const;  socket_address_inet*        sa_inet()                       { return reinterpret_cast<socket_address_inet*>(this); }  const socket_address_inet*  sa_inet() const                 { return reinterpret_cast<const socket_address_inet*>(this); }  sockaddr*           c_sockaddr()                            { return &m_sockaddr; }  sockaddr_in*        c_sockaddr_inet()                       { return &m_sockaddrInet; }  const sockaddr*     c_sockaddr() const                      { return &m_sockaddr; }  const sockaddr_in*  c_sockaddr_inet() const                 { return &m_sockaddrInet; }#ifdef RAK_USE_INET6  socket_address_inet6*       sa_inet6()                      { return reinterpret_cast<socket_address_inet6*>(this); }  const socket_address_inet6* sa_inet6() const                { return reinterpret_cast<const socket_address_inet6*>(this); }  sockaddr_in6*       c_sockaddr_inet6()                      { return &m_sockaddrInet6; }  const sockaddr_in6* c_sockaddr_inet6() const                { return &m_sockaddrInet6; }#endif  // Copy a socket address which has the length 'length. Zero out any  // extranous bytes and ensure it does not go beyond the size of this  // struct.  void                copy(const socket_address& src, size_t length);  static socket_address*       cast_from(sockaddr* sa)        { return reinterpret_cast<socket_address*>(sa); }  static const socket_address* cast_from(const sockaddr* sa)  { return reinterpret_cast<const socket_address*>(sa); }  // The different families will be sorted according to the  // sa_family_t's numeric value.  bool                operator == (const socket_address& rhs) const;  bool                operator  < (const socket_address& rhs) const;  bool                operator == (const sockaddr& rhs) const { return *this == *cast_from(&rhs); }  bool                operator == (const sockaddr* rhs) const { return *this == *cast_from(rhs); }  bool                operator  < (const sockaddr& rhs) const { return *this == *cast_from(&rhs); }  bool                operator  < (const sockaddr* rhs) const { return *this == *cast_from(rhs); }private:  union {    sockaddr            m_sockaddr;    sockaddr_in         m_sockaddrInet;#ifdef RAK_USE_INET6    sockaddr_in6        m_sockaddrInet6;#endif  };};// Remeber to set the AF_INET.class socket_address_inet {public:  bool                is_any() const                          { return is_port_any() && is_address_any(); }  bool                is_valid() const                        { return !is_port_any() && !is_address_any(); }  bool                is_port_any() const                     { return port() == 0; }  bool                is_address_any() const                  { return m_sockaddr.sin_addr.s_addr == htonl(INADDR_ANY); }  void                clear()                                 { std::memset(this, 0, sizeof(socket_address_inet)); set_family(); }  uint16_t            port() const                            { return ntohs(m_sockaddr.sin_port); }  uint16_t            port_n() const                          { return m_sockaddr.sin_port; }  void                set_port(uint16_t p)                    { m_sockaddr.sin_port = htons(p); }  void                set_port_n(uint16_t p)                  { m_sockaddr.sin_port = p; }  // Should address() return the uint32_t?  in_addr             address() const                         { return m_sockaddr.sin_addr; }  uint32_t            address_h() const                       { return ntohl(m_sockaddr.sin_addr.s_addr); }  uint32_t            address_n() const                       { return m_sockaddr.sin_addr.s_addr; }  std::string         address_str() const;  bool                address_c_str(char* buf, socklen_t size) const;  void                set_address(in_addr a)                  { m_sockaddr.sin_addr = a; }  void                set_address_h(uint32_t a)               { m_sockaddr.sin_addr.s_addr = htonl(a); }  void                set_address_n(uint32_t a)               { m_sockaddr.sin_addr.s_addr = a; }  bool                set_address_str(const std::string& a)   { return set_address_c_str(a.c_str()); }  bool                set_address_c_str(const char* a);  void                set_address_any()                       { set_port(0); set_address_h(INADDR_ANY); }  sa_family_t         family() const                          { return m_sockaddr.sin_family; }  void                set_family()                            { m_sockaddr.sin_family = AF_INET; }  sockaddr*           c_sockaddr()                            { return reinterpret_cast<sockaddr*>(&m_sockaddr); }  sockaddr_in*        c_sockaddr_inet()                       { return &m_sockaddr; }  const sockaddr*     c_sockaddr() const                      { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }  const sockaddr_in*  c_sockaddr_inet() const                 { return &m_sockaddr; }  bool                operator == (const socket_address_inet& rhs) const;  bool                operator < (const socket_address_inet& rhs) const;private:  struct sockaddr_in  m_sockaddr;};// Unique key for the address, excluding port numbers etc.class socket_address_key {public://   socket_address_host_key() {}  socket_address_key(const socket_address& sa) {    *this = sa;  }  socket_address_key& operator = (const socket_address& sa) {    if (sa.family() == 0) {      std::memset(this, 0, sizeof(socket_address_key));    } else if (sa.family() == socket_address::af_inet) {      // Using hardware order as we use operator < to compare when      // using inet only.      m_addr.s_addr = sa.sa_inet()->address_h();    } else {      // When we implement INET6 handling, embed the ipv4 address in      // the ipv6 address.      throw std::logic_error("socket_address_key(...) received an unsupported protocol family.");    }    return *this;  }//   socket_address_key& operator = (const socket_address_key& sa) {//   }  bool operator < (const socket_address_key& sa) const {    // Compare the memory area instead.    return m_addr.s_addr < sa.m_addr.s_addr;  }    private:  union {    in_addr m_addr;// #ifdef RAK_USE_INET6//     in_addr6 m_addr6;// #endif  };};inline boolsocket_address::is_valid() const {  switch (family()) {  case af_inet:    return sa_inet()->is_valid();//   case af_inet6://     return sa_inet6().is_valid();  default:    return false;  }}inline boolsocket_address::is_bindable() const {  switch (family()) {  case af_inet:    return !sa_inet()->is_address_any();  default:    return false;  }}inline boolsocket_address::is_address_any() const {  switch (family()) {  case af_inet:    return sa_inet()->is_address_any();  default:    return true;  }}inline uint16_tsocket_address::port() const {  switch (family()) {  case af_inet:    return sa_inet()->port();  default:    return 0;  }}inline voidsocket_address::set_port(uint16_t p) {  switch (family()) {  case af_inet:    return sa_inet()->set_port(p);  default:    break;  }}inline std::stringsocket_address::address_str() const {  switch (family()) {  case af_inet:    return sa_inet()->address_str();  default:    return std::string();  }}inline boolsocket_address::address_c_str(char* buf, socklen_t size) const {  switch (family()) {  case af_inet:    return sa_inet()->address_c_str(buf, size);  default:    return false;  }}inline boolsocket_address::set_address_c_str(const char* a) {  if (sa_inet()->set_address_c_str(a)) {    sa_inet()->set_family();    return true;  } else {    return false;  }}// Is the zero length really needed, should we require some length?inline uint32_tsocket_address::length() const {  switch(family()) {  case af_inet:    return sizeof(sockaddr_in);  default:    return 0;  }      }inline voidsocket_address::copy(const socket_address& src, size_t length) {  length = std::min(length, sizeof(socket_address));    // Does this get properly optimized?  std::memset(this, 0, sizeof(socket_address));  std::memcpy(this, &src, length);}// Should we be able to compare af_unspec?inline boolsocket_address::operator == (const socket_address& rhs) const {  if (family() != rhs.family())    return false;  switch (family()) {  case af_inet:    return *sa_inet() == *rhs.sa_inet();//   case af_inet6://     return *sa_inet6() == *rhs.sa_inet6();  default:    throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");  }}inline boolsocket_address::operator < (const socket_address& rhs) const {  if (family() != rhs.family())    return family() < rhs.family();  switch (family()) {  case af_inet:    return *sa_inet() < *rhs.sa_inet();//   case af_inet6://     return *sa_inet6() < *rhs.sa_inet6();  default:    throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");  }}inline std::stringsocket_address_inet::address_str() const {  char buf[INET_ADDRSTRLEN];  if (!address_c_str(buf, INET_ADDRSTRLEN))    return std::string();  return std::string(buf);}inline boolsocket_address_inet::address_c_str(char* buf, socklen_t size) const {  return inet_ntop(family(), &m_sockaddr.sin_addr, buf, size);}inline boolsocket_address_inet::set_address_c_str(const char* a) {  return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);}inline boolsocket_address_inet::operator == (const socket_address_inet& rhs) const {  return    m_sockaddr.sin_addr.s_addr == rhs.m_sockaddr.sin_addr.s_addr &&    m_sockaddr.sin_port == rhs.m_sockaddr.sin_port;}inline boolsocket_address_inet::operator < (const socket_address_inet& rhs) const {  return    m_sockaddr.sin_addr.s_addr < rhs.m_sockaddr.sin_addr.s_addr ||    (m_sockaddr.sin_addr.s_addr == rhs.m_sockaddr.sin_addr.s_addr &&     m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);}}#endif

⌨️ 快捷键说明

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