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

📄 sockets.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 5 页
字号:
}


BOOL PIPSocket::Connect(const PString & host)
{
  Address ipnum;
#if P_HAS_IPV6
  if (GetHostAddress(host, ipnum))
    return Connect(GetDefaultIpAny(), 0, ipnum);
#else
  if (GetHostAddress(host, ipnum))
    return Connect(INADDR_ANY, 0, ipnum);
#endif  
  return FALSE;
}


BOOL PIPSocket::Connect(const Address & addr)
{
#if P_HAS_IPV6
  return Connect(GetDefaultIpAny(), 0, addr);
#else
  return Connect(INADDR_ANY, 0, addr);
#endif
}


BOOL PIPSocket::Connect(WORD localPort, const Address & addr)
{
#if P_HAS_IPV6
  return Connect(GetDefaultIpAny(), localPort, addr);
#else
  return Connect(INADDR_ANY, localPort, addr);
#endif
}


BOOL PIPSocket::Connect(const Address & iface, const Address & addr)
{
  return Connect(iface, 0, addr);
}


BOOL PIPSocket::Connect(const Address & iface, WORD localPort, const Address & addr)
{
  // close the port if it is already open
  if (IsOpen())
    Close();

  // make sure we have a port
  PAssert(port != 0, "Cannot connect socket without setting port");

#if P_HAS_IPV6

  Psockaddr sa(addr, port);

  // attempt to create a socket with the right family
  if (!OpenSocket(sa->sa_family))
    return FALSE;

  if (localPort != 0 || iface.IsValid()) {
    Psockaddr bind_sa(iface, localPort);

    if (!SetOption(SO_REUSEADDR, 0)) {
      os_close();
      return FALSE;
    }
    
    if (!ConvertOSError(::bind(os_handle, bind_sa, bind_sa.GetSize()))) {
      os_close();
      return FALSE;
    }
  }
  
  // attempt to connect
  if (os_connect(sa, sa.GetSize()))
    return TRUE;
  
#else

  // attempt to create a socket
  if (!OpenSocket())
    return FALSE;

  // attempt to connect
  sockaddr_in sin;
  if (localPort != 0 || iface.IsValid()) {
    if (!SetOption(SO_REUSEADDR, 0)) {
      os_close();
      return FALSE;
    }
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = iface;
    sin.sin_port        = htons(localPort);       // set the port
    if (!ConvertOSError(::bind(os_handle, (struct sockaddr*)&sin, sizeof(sin)))) {
      os_close();
      return FALSE;
    }
  }

  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_port   = htons(port);  // set the port
  sin.sin_addr   = addr;
  if (os_connect((struct sockaddr *)&sin, sizeof(sin)))
    return TRUE;

#endif

  os_close();
  return FALSE;
}


BOOL PIPSocket::Listen(unsigned queueSize, WORD newPort, Reusability reuse)
{
#if P_HAS_IPV6
  return Listen(GetDefaultIpAny(), queueSize, newPort, reuse);
#else
  return Listen(INADDR_ANY, queueSize, newPort, reuse);
#endif
}


BOOL PIPSocket::Listen(const Address & bindAddr,
                       unsigned,
                       WORD newPort,
                       Reusability reuse)
{
  // make sure we have a port
  if (newPort != 0)
    port = newPort;

#if P_HAS_IPV6
  Psockaddr bind_sa(bindAddr, port); 

  if (IsOpen()) {
    int socketType;
    if (!GetOption(SO_TYPE, socketType, SOL_SOCKET) || bind_sa->sa_family != socketType)
      Close();
  }
#endif

  if (!IsOpen()) {
    // attempt to create a socket
#if P_HAS_IPV6
    if (!OpenSocket(bind_sa->sa_family))
      return FALSE;
#else
    if (!OpenSocket())
      return FALSE;
#endif
  }
  
#ifndef __BEOS__
  // attempt to listen
  if (!SetOption(SO_REUSEADDR, reuse == CanReuseAddress ? 1 : 0)) {
    os_close();
    return FALSE;
  }
#else
  // attempt to listen
  int value = reuse == CanReuseAddress ? 1 : 0;
  if (!SetOption(SO_REUSEADDR, &value, sizeof(int))) {
    os_close();
    return FALSE;
  }
#endif // BEOS

#if P_HAS_IPV6

  if (ConvertOSError(::bind(os_handle, bind_sa, bind_sa.GetSize()))) {
    Psockaddr sa;
    socklen_t size = sa.GetSize();
    if (!ConvertOSError(::getsockname(os_handle, sa, &size)))
      return FALSE;

    port = sa.GetPort();
    return TRUE;
  }

#else

  // attempt to listen
  sockaddr_in sin;
  memset(&sin, 0, sizeof(sin));
  sin.sin_family      = AF_INET;
  sin.sin_addr.s_addr = bindAddr;
  sin.sin_port        = htons(port);       // set the port

#ifdef __NUCLEUS_NET__
  int bind_result;
  if (port == 0)
    bind_result = ::bindzero(os_handle, (struct sockaddr*)&sin, sizeof(sin));
  else
    bind_result = ::bind(os_handle, (struct sockaddr*)&sin, sizeof(sin));
  if (ConvertOSError(bind_result))
#else
  if (ConvertOSError(::bind(os_handle, (struct sockaddr*)&sin, sizeof(sin))))
#endif
  {
    socklen_t size = sizeof(sin);
    if (ConvertOSError(::getsockname(os_handle, (struct sockaddr*)&sin, &size))) {
      port = ntohs(sin.sin_port);
      return TRUE;
    }
  }

#endif

  os_close();
  return FALSE;
}


const PIPSocket::Address & PIPSocket::Address::GetLoopback()
{
  return loopback4;
}


#if P_HAS_IPV6

/// Check for v4 mapped i nv6 address ::ffff:a.b.c.d
BOOL PIPSocket::Address::IsV4Mapped() const
{
  if (version != 6)
    return FALSE;
  return IN6_IS_ADDR_V4MAPPED(&v.six) || IN6_IS_ADDR_V4COMPAT(&v.six);
}


const PIPSocket::Address & PIPSocket::Address::GetLoopback6()
{
  return loopback6;
}


const PIPSocket::Address & PIPSocket::Address::GetAny6()
{
  return any6;
}

#endif


BOOL PIPSocket::Address::IsAny() const
{
  return (!IsValid());
}


const PIPSocket::Address & PIPSocket::Address::GetBroadcast()
{
  return broadcast4;
}


PIPSocket::Address::Address()
{
  *this = loopback4;
}


PIPSocket::Address::Address(const PString & dotNotation)
{
  operator=(dotNotation);
}


PIPSocket::Address::Address(PINDEX len, const BYTE * bytes)
{
  switch (len) {
#if P_HAS_IPV6
    case 16 :
      version = 6;
      memcpy(&v.six, bytes, len);
      break;
#endif
    case 4 :
      version = 4;
      memcpy(&v.four, bytes, len);
      break;

    default :
      version = 0;
  }
}


PIPSocket::Address::Address(const in_addr & addr)
{
  version = 4;
  v.four = addr;
}


#if P_HAS_IPV6
PIPSocket::Address::Address(const in6_addr & addr)
{
  version = 6;
  v.six = addr;
}

// Create an IP (v4 or v6) address from a sockaddr (sockaddr_in, sockaddr_in6 or sockaddr_in6_old) structure
PIPSocket::Address::Address(const int ai_family, const int ai_addrlen, struct sockaddr *ai_addr)
{
  switch (ai_family) {
#if P_HAS_IPV6
    case AF_INET6:
      if (ai_addrlen < (int)sizeof(sockaddr_in6))
        break;

      version = 6;
      v.six = ((struct sockaddr_in6 *)ai_addr)->sin6_addr;
      //sin6_scope_id, should be taken into account for link local addresses
      return;
#endif
    case AF_INET: 
      if (ai_addrlen < (int)sizeof(sockaddr_in))
        break;

      version = 4;
      v.four = ((struct sockaddr_in  *)ai_addr)->sin_addr;
      return;
  }
  version = 0;
}

#endif


#ifdef __NUCLEUS_NET__
PIPSocket::Address::Address(const struct id_struct & addr)
{
  operator=(addr);
}


PIPSocket::Address & PIPSocket::Address::operator=(const struct id_struct & addr)
{
  s_addr = (((unsigned long)addr.is_ip_addrs[0])<<24) +
           (((unsigned long)addr.is_ip_addrs[1])<<16) +
           (((unsigned long)addr.is_ip_addrs[2])<<8) +
           (((unsigned long)addr.is_ip_addrs[3]));
  return *this;
}
#endif
 

PIPSocket::Address & PIPSocket::Address::operator=(const in_addr & addr)
{
  version = 4;
  v.four = addr;
  return *this;
}

#if P_HAS_IPV6
PIPSocket::Address & PIPSocket::Address::operator=(const in6_addr & addr)
{
  version = 6;
  v.six = addr;
  return *this;
}
#endif


PObject::Comparison PIPSocket::Address::Compare(const PObject & obj) const
{
  const PIPSocket::Address & other = (const PIPSocket::Address &)obj;

  if (version < other.version)
    return LessThan;
  if (version > other.version)
    return GreaterThan;

#if P_HAS_IPV6
  if (version == 6) {
    int result = memcmp(&v.six, &other.v.six, sizeof(v.six));
    if (result < 0)
      return LessThan;
    if (result > 0)
      return GreaterThan;
    return EqualTo;
  }
#endif

  if ((DWORD)*this < other)
    return LessThan;
  if ((DWORD)*this > other)
    return GreaterThan;
  return EqualTo;
}

#if P_HAS_IPV6
bool PIPSocket::Address::operator*=(const PIPSocket::Address & addr) const
{
  if (version == addr.version)
    return operator==(addr);

  if (this->GetVersion() == 6 && this->IsV4Mapped()) 
    return PIPSocket::Address((*this)[12], (*this)[13], (*this)[14], (*this)[15]) == addr;
  else if (addr.GetVersion() == 6 && addr.IsV4Mapped()) 
    return *this == PIPSocket::Address(addr[12], addr[13], addr[14], addr[15]);
  return FALSE;
}

bool PIPSocket::Address::operator==(in6_addr & addr) const
{
  PIPSocket::Address a(addr);
  return Compare(a) == EqualTo;
}
#endif


bool PIPSocket::Address::operator==(in_addr & addr) const
{
  PIPSocket::Address a(addr);
  return Compare(a) == EqualTo;
}


bool PIPSocket::Address::operator==(DWORD dw) const
{
  if (dw != 0)
    return (DWORD)*this == dw;

  return !IsValid();
}


PIPSocket::Address & PIPSocket::Address::operator=(const PString & dotNotation)
{
#if P_HAS_IPV6

  struct addrinfo *res;
  struct addrinfo hints = { AI_NUMERICHOST, PF_UNSPEC }; // Could be IPv4: x.x.x.x or IPv6: x:x:x:x::x
  
  version = 0;
  memset(&v, 0, sizeof(v));
  
  if (getaddrinfo((const char *)dotNotation, NULL , &hints, &res) == 0) {
    if (res->ai_family == PF_INET6) {
      // IPv6 addr
      version = 6;
      struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 *)res->ai_addr;
      v.six = addr_in6->sin6_addr;
    } else {
      // IPv4 addr
      version = 4;
      struct sockaddr_in * addr_in = (struct sockaddr_in *)res->ai_addr;
      v.four = addr_in->sin_addr;
    }
    freeaddrinfo(res);
  }

#else //P_HAS_IPV6

  if (::strspn(dotNotation, "0123456789.") < ::strlen(dotNotation))
    *this = 0;
  else {
    version = 4;
    v.four.s_addr = inet_addr((const char *)dotNotation);
    if (v.four.s_addr == (DWORD)INADDR_NONE)
      v.four.s_addr = 0;
  }

#endif

  return *this;
}


PString PIPSocket::Address::AsString() const
{
#if P_HAS_IPV6
  if (version == 6) {
    PString str;
    Psockaddr sa(*this, 0);
    PAssertOS(getnameinfo(sa, sa.GetSize(), str.GetPointer(1024), 1024, NULL, 0, NI_NUMERICHOST) == 0);
    PINDEX percent = str.Find('%'); // used for scoped address e.g. fe80::1%ne0, (ne0=network interface 0)
    if (percen

⌨️ 快捷键说明

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