inline asio::error_code getnameinfo_emulation()

in demo_example/asio/asio/detail/impl/socket_ops.ipp [3536:3662]


inline asio::error_code getnameinfo_emulation(
    const socket_addr_type* sa, std::size_t salen, char* host,
    std::size_t hostlen, char* serv, std::size_t servlen, int flags,
    asio::error_code& ec)
{
  using namespace std;

  const char* addr;
  size_t addr_len;
  unsigned short port;
  switch (sa->sa_family)
  {
  case ASIO_OS_DEF(AF_INET):
    if (salen != sizeof(sockaddr_in4_type))
    {
      return ec = asio::error::invalid_argument;
    }
    addr = reinterpret_cast<const char*>(
        &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr);
    addr_len = sizeof(in4_addr_type);
    port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port;
    break;
  case ASIO_OS_DEF(AF_INET6):
    if (salen != sizeof(sockaddr_in6_type))
    {
      return ec = asio::error::invalid_argument;
    }
    addr = reinterpret_cast<const char*>(
        &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr);
    addr_len = sizeof(in6_addr_type);
    port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port;
    break;
  default:
    return ec = asio::error::address_family_not_supported;
  }

  if (host && hostlen > 0)
  {
    if (flags & NI_NUMERICHOST)
    {
      if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0)
      {
        return ec;
      }
    }
    else
    {
      hostent hent;
      char hbuf[8192] = "";
      hostent* hptr = socket_ops::gethostbyaddr(addr,
          static_cast<int>(addr_len), sa->sa_family,
          &hent, hbuf, sizeof(hbuf), ec);
      if (hptr && hptr->h_name && hptr->h_name[0] != '\0')
      {
        if (flags & NI_NOFQDN)
        {
          char* dot = strchr(hptr->h_name, '.');
          if (dot)
          {
            *dot = 0;
          }
        }
        gai_strcpy(host, hptr->h_name, hostlen);
        socket_ops::freehostent(hptr);
      }
      else
      {
        socket_ops::freehostent(hptr);
        if (flags & NI_NAMEREQD)
        {
          return ec = asio::error::host_not_found;
        }
        if (socket_ops::inet_ntop(sa->sa_family,
              addr, host, hostlen, 0, ec) == 0)
        {
          return ec;
        }
      }
    }
  }

  if (serv && servlen > 0)
  {
    if (flags & NI_NUMERICSERV)
    {
      if (servlen < 6)
      {
        return ec = asio::error::no_buffer_space;
      }
#if defined(ASIO_HAS_SECURE_RTL)
      sprintf_s(serv, servlen, "%u", ntohs(port));
#else // defined(ASIO_HAS_SECURE_RTL)
      sprintf(serv, "%u", ntohs(port));
#endif // defined(ASIO_HAS_SECURE_RTL)
    }
    else
    {
#if defined(ASIO_HAS_PTHREADS)
      static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
      ::pthread_mutex_lock(&mutex);
#endif // defined(ASIO_HAS_PTHREADS)
      servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0);
      if (sptr && sptr->s_name && sptr->s_name[0] != '\0')
      {
        gai_strcpy(serv, sptr->s_name, servlen);
      }
      else
      {
        if (servlen < 6)
        {
          return ec = asio::error::no_buffer_space;
        }
#if defined(ASIO_HAS_SECURE_RTL)
        sprintf_s(serv, servlen, "%u", ntohs(port));
#else // defined(ASIO_HAS_SECURE_RTL)
        sprintf(serv, "%u", ntohs(port));
#endif // defined(ASIO_HAS_SECURE_RTL)
      }
#if defined(ASIO_HAS_PTHREADS)
      ::pthread_mutex_unlock(&mutex);
#endif // defined(ASIO_HAS_PTHREADS)
    }
  }

  ec.assign(0, ec.category());
  return ec;
}