Logo Search packages:      
Sourcecode: sofia-sip version File versions  Download package

TPORT_DLL tport_t* tport_by_name ( tport_t const *  self,
tp_name_t const *  tpn 
)

Get a transport corresponding to the name

Get transport by name.

Definition at line 4387 of file tport.c.

References SU_ADDR, SU_DEBUG_7, su_sockaddr_u::su_family, tp_name_t::tpn_canon, tp_name_t::tpn_comp, tp_name_t::tpn_host, tp_name_t::tpn_port, tp_name_t::tpn_proto, tport_by_name(), tport_canonize_comp(), TPORT_HOSTPORTSIZE, tport_is_primary(), tport_is_shutdown(), and tport_primary_by_name().

Referenced by nta_msg_tsend(), and tport_by_name().

{
  tport_t const *sub, *next;
  char const *canon, *host, *port, *comp;
#if SU_HAVE_IN6
  char *end, ipaddr[TPORT_HOSTPORTSIZE];
#endif

  assert(self); assert(tpn);

  assert(tpn->tpn_proto); assert(tpn->tpn_host); assert(tpn->tpn_port);
  assert(tpn->tpn_canon);

  if (!tport_is_primary(self))
    self = tport_primary_by_name(self, tpn);

  host = strcmp(tpn->tpn_host, tpn_any) ? tpn->tpn_host : NULL;
  port = strcmp(tpn->tpn_port, tpn_any) ? tpn->tpn_port : NULL;
  canon = tpn->tpn_canon;
  comp = tport_canonize_comp(tpn->tpn_comp);

  if (self && host && port) {
    int resolved = 0, cmp;
    socklen_t sulen;
    su_sockaddr_t su[1];

    sub = self->tp_pri->pri_open;

    memset(su, 0, sizeof su);

#if SU_HAVE_IN6
    if (host_is_ip6_reference(host)) {
      /* Remove [] around IPv6 address */
      host = strncpy(ipaddr, host +  1, sizeof(ipaddr) - 1);
      ipaddr[sizeof(ipaddr) - 1] = '\0';
      if ((end = strchr(host, ']')))
      *end = 0;
      su->su_len = sulen = (socklen_t) sizeof (struct sockaddr_in6);
      su->su_family = AF_INET6;
    }
    else if (host_is_ip6_address(host)) {
      su->su_len = sulen = (socklen_t) sizeof (struct sockaddr_in6);
      su->su_family = AF_INET6;
    }
    else
#endif
    {
      su->su_len = sulen = (socklen_t) sizeof (struct sockaddr_in);
      su->su_family = AF_INET;
    }

    su->su_port = htons(strtoul(port, NULL, 10));

    if (su_inet_pton(su->su_family, host, SU_ADDR(su)) > 0) {
      resolved = 1;
      next = NULL;

      /* Depth-first search */
      while (sub) {
      cmp = (int)((size_t)sub->tp_addrlen - (size_t)sulen);

      if (cmp == 0)
        cmp = memcmp(sub->tp_addr, su, sulen);

      if (cmp == 0) {
        if (sub->tp_left) {
          next = sub;
          sub = sub->tp_left;
          continue;
        }
        break;
      }
      else if (next) {
        sub = next;
        break;
      }
      else if (cmp > 0) {
        sub = sub->tp_left;
        continue;
      }
      else /* if (cmp < 0) */ {
        sub = sub->tp_right;
        continue;
      }
      }
    }
    else {
      SU_DEBUG_7(("tport(%p): EXPENSIVE unresolved " TPN_FORMAT "\n",
              (void *)self, TPN_ARGS(tpn)));

      sub = tprb_first(sub);
    }

    for (; sub; sub = tprb_succ(sub)) {
      if (!sub->tp_reusable)
      continue;
      if (!tport_is_registered(sub))
      continue;
      if (tport_is_shutdown(sub))
      continue;

      if (comp != sub->tp_name->tpn_comp)
      continue;

      if (resolved) {
      if ((socklen_t)sub->tp_addrlen != sulen ||
          memcmp(sub->tp_addr, su, sulen)) {
        SU_DEBUG_7(("tport(%p): not found by name " TPN_FORMAT "\n",
                  (void *)self, TPN_ARGS(tpn)));
        break;
      }
      SU_DEBUG_7(("tport(%p): found %p by name " TPN_FORMAT "\n",
                (void *)self, (void *)sub, TPN_ARGS(tpn)));
      }
      else if ((strcasecmp(canon, sub->tp_canon) &&
            strcasecmp(host, sub->tp_host)) ||
             strcmp(port, sub->tp_port))
      continue;

      return (tport_t *)sub;
    }
  }

  return (tport_t *)self;
}


Generated by  Doxygen 1.6.0   Back to index