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

tport_t* tport_base_connect ( tport_primary_t pri,
su_addrinfo_t ai,
su_addrinfo_t real_ai,
tp_name_t const *  tpn 
)

Create a connected transport object with socket.

The function tport_connect() creates a secondary transport with a connected socket. It registers the socket with suitable events to the root.

Parameters:
pri primary transport object
ai pointer to addrinfo structure describing socket
real_ai pointer to addrinfo structure describing real target
tpn canonical name of node

Definition at line 947 of file tport.c.

References tport_primary::pri_open, tport_primary::pri_primary, SU_DEBUG_3, SU_DEBUG_5, su_errno, su_is_blocking(), su_root_register(), su_sockaddr_u::su_sa, su_setblocking(), su_socket(), su_strerror(), su_wait_create(), tp_name_t::tpn_canon, tp_name_t::tpn_proto, tport_hostport(), and TPORT_HOSTPORTSIZE.

{
  tport_master_t *mr = pri->pri_master;
  tport_t *self = NULL;

  su_socket_t s, server_socket;
  su_wait_t wait[1] = { SU_WAIT_INIT };
  su_wakeup_f wakeup = tport_wakeup;
  int index = 0;
  int events = SU_WAIT_IN | SU_WAIT_ERR;

  int err;
  unsigned errlevel = 3;
  char buf[TPORT_HOSTPORTSIZE];
  char const *what;

  /* Log an error, return error */
#define TPORT_CONNECT_ERROR(errno, what)                   \
  return                                             \
    ((void)(err = errno,                                   \
          su_wait_destroy(wait),                           \
          (SU_LOG_LEVEL >= errlevel ?                            \
           su_llog(tport_log, errlevel,                    \
                 "%s(%p): %s(pf=%d %s/%s): %s\n",                 \
                         __func__, (void *)pri, #what, ai->ai_family,   \
                 tpn->tpn_proto,                           \
                 tport_hostport(buf, sizeof(buf),                \
                            (void *)ai->ai_addr, 2),       \
                 su_strerror(err)) : (void)0),             \
          tport_zap_secondary(self),                             \
          su_seterrno(err)),                               \
     (void *)NULL)

  s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  if (s == INVALID_SOCKET)
    TPORT_CONNECT_ERROR(su_errno(), "socket");

  what = "tport_alloc_secondary";
  if ((self = tport_alloc_secondary(pri, s, 0, &what)) == NULL)
    TPORT_CONNECT_ERROR(errno, what);

  self->tp_conn_orient = 1;

  if ((server_socket = pri->pri_primary->tp_socket) != INVALID_SOCKET) {
    su_sockaddr_t susa;
    socklen_t susalen = sizeof(susa);

    /* Bind this socket to same IP address as the primary server socket */
    if (getsockname(server_socket, &susa.su_sa, &susalen) < 0) {
      SU_DEBUG_3(("%s(%p): getsockname(): %s\n",
              __func__, (void *)self, su_strerror(su_errno())));
    }
    else {
      susa.su_port = 0;
      if (bind(s, &susa.su_sa, susalen) < 0) {
      SU_DEBUG_3(("%s(%p): bind(local-ip): %s\n",
                __func__, (void *)self, su_strerror(su_errno())));
      }
    }
  }

  /* Set sockname for the tport */
  if (tport_setname(self, tpn->tpn_proto, real_ai, tpn->tpn_canon) == -1)
    TPORT_CONNECT_ERROR(su_errno(), tport_setname);

  /* Try to have a non-blocking connect().
   * The su_wait_create() below makes the socket non-blocking anyway. */
  su_setblocking(s, 0);

  if (connect(s, ai->ai_addr, (socklen_t)(ai->ai_addrlen)) == SOCKET_ERROR) {
    err = su_errno();
    if (!su_is_blocking(err))
      TPORT_CONNECT_ERROR(err, connect);
    events = SU_WAIT_CONNECT | SU_WAIT_ERR;
    wakeup = tport_connected;
    what = "connecting";
  }
  else {
    what = "connected";
    self->tp_is_connected = 1;
  }

  if (su_wait_create(wait, s, self->tp_events = events) == -1)
    TPORT_CONNECT_ERROR(su_errno(), su_wait_create);

  /* Register receiving function with events specified above */
  if ((index = su_root_register(mr->mr_root, wait, wakeup, self, 0)) == -1)
    TPORT_CONNECT_ERROR(su_errno(), su_root_register);

  self->tp_index = index;

  if (ai == real_ai) {
    SU_DEBUG_5(("%s(%p): %s to " TPN_FORMAT "\n",
            __func__, (void *)self, what, TPN_ARGS(self->tp_name)));
  }
  else {
    SU_DEBUG_5(("%s(%p): %s via %s to " TPN_FORMAT "\n",
            __func__, (void *)self, what,
            tport_hostport(buf, sizeof(buf), (void *)ai->ai_addr, 2),
            TPN_ARGS(self->tp_name)));
  }

  tprb_append(&pri->pri_open, self);

  return self;
}


Generated by  Doxygen 1.6.0   Back to index