예제 #1
0
/// Resolve a destination host and realm name to a list of IP addresses,
/// transports and ports.  HTTP is pretty simple - just look up the A records.
void HttpResolver::resolve(const std::string& host,
                           int port,
                           int max_targets,
                           std::vector<AddrInfo>& targets,
                           SAS::TrailId trail)
{
  AddrInfo ai;
  int dummy_ttl = 0;

  TRC_DEBUG("HttpResolver::resolve for host %s, port %d, family %d",
            host.c_str(), port, _address_family);

  port = (port != 0) ? port : DEFAULT_PORT;
  targets.clear();

  if (parse_ip_target(host, ai.address))
  {
    // The name is already an IP address, so no DNS resolution is possible.
    TRC_DEBUG("Target is an IP address");
    ai.port = port;
    ai.transport = TRANSPORT;
    targets.push_back(ai);
  }
  else
  {
    a_resolve(host, _address_family, port, TRANSPORT, max_targets, targets, dummy_ttl, trail);
  }
}
예제 #2
0
void SIPResolver::resolve(const std::string& name,
                          int af,
                          int port,
                          int transport,
                          int retries,
                          std::vector<AddrInfo>& targets,
                          SAS::TrailId trail)
{
  int dummy_ttl = 0;
  targets.clear();

  // First determine the transport following the process in RFC3263 section
  // 4.1.
  AddrInfo ai;

  TRC_DEBUG("SIPResolver::resolve for name %s, port %d, transport %d, family %d",
            name.c_str(), port, transport, af);

  if (trail != 0)
  {
    SAS::Event event(trail, SASEvent::SIPRESOLVE_START, 0);
    event.add_var_param(name);
    std::string port_str = std::to_string(port);
    std::string transport_str = get_transport_str(transport);
    event.add_var_param(port_str);
    event.add_var_param(transport_str);
    SAS::report_event(event);
  }

  if (parse_ip_target(name, ai.address))
  {
    // The name is already an IP address, so no DNS resolution is possible.
    // Use specified transport and port or defaults if not specified.
    TRC_DEBUG("Target is an IP address - default port/transport if required");
    ai.transport = (transport != -1) ? transport : IPPROTO_UDP;
    ai.port = (port != 0) ? port : 5060;
    targets.push_back(ai);

    if (trail != 0)
    {
      SAS::Event event(trail, SASEvent::SIPRESOLVE_IP_ADDRESS, 0);
      event.add_var_param(name);
      std::string port_str = std::to_string(ai.port);
      std::string transport_str = get_transport_str(ai.transport);
      event.add_var_param(transport_str);
      event.add_var_param(port_str);
      SAS::report_event(event);
    }
  }
  else
  {
    std::string srv_name;
    std::string a_name = name;

    if (port != 0)
    {
      // Port is specified, so don't do NAPTR or SRV look-ups.  Default transport
      // if required and move straight to A record look-up.
      TRC_DEBUG("Port is specified");
      transport = (transport != -1) ? transport : IPPROTO_UDP;

      if (trail != 0)
      {
        SAS::Event event(trail, SASEvent::SIPRESOLVE_PORT_A_LOOKUP, 0);
        event.add_var_param(name);
        std::string port_str = std::to_string(port);
        std::string transport_str = get_transport_str(transport);
        event.add_var_param(transport_str);
        event.add_var_param(port_str);
        SAS::report_event(event);
      }
    }
    else if (transport == -1)
    {
      // Transport protocol isn't specified, so do a NAPTR lookup for the target.
      TRC_DEBUG("Do NAPTR look-up for %s", name.c_str());

      if (trail != 0)
      {
        SAS::Event event(trail, SASEvent::SIPRESOLVE_NAPTR_LOOKUP, 0);
        event.add_var_param(name);
        SAS::report_event(event);
      }

      NAPTRReplacement* naptr = _naptr_cache->get(name, dummy_ttl, trail);

      if (naptr != NULL)
      {
        // NAPTR resolved to a supported service
        TRC_DEBUG("NAPTR resolved to transport %d", naptr->transport);
        transport = naptr->transport;
        if (strcasecmp(naptr->flags.c_str(), "S") == 0)
        {
          // Do an SRV lookup with the replacement domain from the NAPTR lookup.
          srv_name = naptr->replacement;

          if (trail != 0)
          {
            SAS::Event event(trail, SASEvent::SIPRESOLVE_NAPTR_SUCCESS_SRV, 0);
            event.add_var_param(name);
            event.add_var_param(srv_name);
            std::string transport_str = get_transport_str(naptr->transport);
            event.add_var_param(transport_str);
            SAS::report_event(event);
          }
        }
        else
        {
          // Move straight to A/AAAA lookup of the domain returned by NAPTR.
          a_name = naptr->replacement;

          if (trail != 0)
          {
            SAS::Event event(trail, SASEvent::SIPRESOLVE_NAPTR_SUCCESS_A, 0);
            event.add_var_param(name);
            event.add_var_param(a_name);
            SAS::report_event(event);
          }
        }
      }
      else
      {
        // NAPTR resolution failed, so do SRV lookups for both UDP and TCP to
        // see which transports are supported.
        TRC_DEBUG("NAPTR lookup failed, so do SRV lookups for UDP and TCP");

        if (trail != 0)
        {
          SAS::Event event(trail, SASEvent::SIPRESOLVE_NAPTR_FAILURE, 0);
          event.add_var_param(name);
          SAS::report_event(event);
        }

        std::vector<std::string> domains;
        domains.push_back("_sip._udp." + name);
        domains.push_back("_sip._tcp." + name);
        std::vector<DnsResult> results;
        _dns_client->dns_query(domains, ns_t_srv, results, trail);
        DnsResult& udp_result = results[0];
        TRC_DEBUG("UDP SRV record %s returned %d records",
                  udp_result.domain().c_str(), udp_result.records().size());
        DnsResult& tcp_result = results[1];
        TRC_DEBUG("TCP SRV record %s returned %d records",
                  tcp_result.domain().c_str(), tcp_result.records().size());

        if (!udp_result.records().empty())
        {
          // UDP SRV lookup returned some records, so use UDP transport.
          TRC_DEBUG("UDP SRV lookup successful, select UDP transport");
          transport = IPPROTO_UDP;
          srv_name = udp_result.domain();
        }
        else if (!tcp_result.records().empty())
        {
          // TCP SRV lookup returned some records, so use TCP transport.
          TRC_DEBUG("TCP SRV lookup successful, select TCP transport");
          transport = IPPROTO_TCP;
          srv_name = tcp_result.domain();
        }
        else
        {
          // Neither UDP nor TCP SRV lookup returned any results, so default to
          // UDP transport and move straight to A/AAAA record lookups.
          TRC_DEBUG("UDP and TCP SRV queries unsuccessful, default to UDP");
          transport = IPPROTO_UDP;
        }
      }

      _naptr_cache->dec_ref(name);
    }
    else if (transport == IPPROTO_UDP)
    {
      // Use specified transport and try an SRV lookup.
      if (trail != 0)
      {
        SAS::Event event(trail, SASEvent::SIPRESOLVE_TRANSPORT_SRV_LOOKUP, 0);
        event.add_var_param(name);
        std::string transport_str = get_transport_str(transport);
        event.add_var_param(transport_str);
        SAS::report_event(event);
      }

      DnsResult result = _dns_client->dns_query("_sip._udp." + name, ns_t_srv, trail);

      if (!result.records().empty())
      {
        srv_name = result.domain();
      }
    }
    else if (transport == IPPROTO_TCP)
    {
      // Use specified transport and try an SRV lookup.
      if (trail != 0)
      {
        SAS::Event event(trail, SASEvent::SIPRESOLVE_TRANSPORT_SRV_LOOKUP, 0);
        event.add_var_param(name);
        std::string transport_str = get_transport_str(transport);
        event.add_var_param(transport_str);
        SAS::report_event(event);
      }

      DnsResult result = _dns_client->dns_query("_sip._tcp." + name, ns_t_srv, trail);

      if (!result.records().empty())
      {
        srv_name = result.domain();
      }
    }

    if (srv_name != "")
    {
      TRC_DEBUG("Do SRV lookup for %s", srv_name.c_str());

      if (trail != 0)
      {
        SAS::Event event(trail, SASEvent::SIPRESOLVE_SRV_LOOKUP, 0);
        event.add_var_param(srv_name);
        std::string transport_str = get_transport_str(transport);
        event.add_var_param(transport_str);
        SAS::report_event(event);
      }

      srv_resolve(srv_name, af, transport, retries, targets, dummy_ttl, trail);
    }
    else
    {
      TRC_DEBUG("Perform A/AAAA record lookup only, name = %s", a_name.c_str());
      port = (port != 0) ? port : 5060;

      if (trail != 0)
      {
        SAS::Event event(trail, SASEvent::SIPRESOLVE_A_LOOKUP, 0);
        event.add_var_param(a_name);
        std::string transport_str = get_transport_str(transport);
        std::string port_str = std::to_string(port);
        event.add_var_param(transport_str);
        event.add_var_param(port_str);
        SAS::report_event(event);
      }

      a_resolve(a_name, af, port, transport, retries, targets, dummy_ttl, trail);
    }
  }
}
예제 #3
0
파일: udp.c 프로젝트: schallee/alib4c
	SOCKET
#else
	int
#endif
udp_client(const char *ip, uint16_t port)
{
#	if HAVE_WINSOCK2_H
		SOCKET sock;
#	else
		int sock;
#	endif
	struct sockaddr_in remote;
	struct sockaddr_in local;
	
	remote.sin_family = AF_INET;
	if(a_resolve(ip, &(remote.sin_addr)))
	{
#		if OS_TYPE_WIN32 && HAVE_WINSOCK2_H
			return INVALID_SOCKET;
#		else
			return -1;
#		endif
	}
	remote.sin_port = htons(port);

	local.sin_family = AF_INET;
	local.sin_addr.s_addr = INADDR_ANY;
	local.sin_port = htons(0);

	sock = socket(AF_INET, SOCK_DGRAM, 0);
#	ifdef __WIN32__
		if(sock == INVALID_SOCKET)
		{
			a_flail_winsock_su(a_error_socket);
			return INVALID_SOCKET;
		}
#	else
		if(sock == -1)
		{
			a_flail_winsock_su(a_error_socket);
			return -1;
		}
#	endif

	if(bind(sock, (struct sockaddr *)(&local), sizeof(local)))
#		ifdef __WIN32__
			{
				a_flail_winsock_su(a_error_bind);
				a_cleanup(A_CLEANUP_SOCK, sock);
				return INVALID_SOCKET;
			}
#		else
			{
				a_flail_posix_su(a_error_bind);
				a_cleanup(A_CLEANUP_SOCK, sock);
				return -1;
			}
#		endif

	if(connect(sock, (struct sockaddr *)(&remote), sizeof(remote)))
#		ifdef __WIN32__
			{
				a_flail_winsock_su(a_error_connect_socket);
				a_cleanup(A_CLEANUP_SOCK, sock);
				return INVALID_SOCKET;
			}
#		else
			{
				a_flail_winsock_su(a_error_connect_socket);
				a_cleanup(A_CLEANUP_SOCK, sock);
				return -1;
			}
#		endif

	return sock;
}