This is first in a series of patches to the TLS code that will improve
certificate validation facilities.  Significant changes in this round
include:

1) The TLS handshake is no longer handled via transparent negotiation.
Certain static methods from tport.c were exposed to make this possible.

2) Certificate subjects are copied out of the peer certificate before
the first message is sent.  The next patch will include code that allows
the stack to reject messages sent to a untrusted peer.

3) The tport module can now report whether a secondary has a verified
certificate chain and the subjects of the peer certificate.

These patches should not change the behavior of NTA or NUA.



Tue Dec 16 11:58:26 CST 2008  Jarod Neuner <j.neu...@networkharbor.com>
  * Helper functions for vtp_connect and vtp_wakeup_pri.
  
  - Expose tport_setname() and tport_wakeup() via tport_internal.h
  - Add tport_register_secondary() for adding secondaries to a root, and
    to alleviate the need to export tprb_append.
  

Tue Dec 16 16:19:37 CST 2008  Jarod Neuner <j.neu...@networkharbor.com>
  * Early TLS Handshake and Verification
  
  tport_type_tls.c:
  * tport_tls_accept():
    - Replaces tport_accept for incoming TLS connections.
  * tport_tls_connect():
    - Replaces tport_base_connect() for outgoing TLS connections.
  
  tport_tls.c:
  * tls_t now use a memory home instead of malloc.
  * removed tls_check_hosts()
  * tls_connect():
    - Replaces tport_base_connect for TLS connection setup.
    - Completes TLS handshake and verifies peer certificates.
    - Destroys suspect TLS connections before sending/receiving payload.
    - Populates a su_strlst_t with subjects from the peer certificate.
  
  tport.c:
  * tport_is_verified()
    - true if peer certificate validated successfully
  * tport_delivered_from_subjects()
    - Certificate subjects listed in the peer certificate.
  
New patches:

[Helper functions for vtp_connect and vtp_wakeup_pri.
Jarod Neuner <janeu...@networkharbor.com>**20081216175826
 
 - Expose tport_setname() and tport_wakeup() via tport_internal.h
 - Add tport_register_secondary() for adding secondaries to a root, and
   to alleviate the need to export tprb_append.
 
] {
hunk ./libsofia-sip-ua/tport/tport.c 402
-  tport_setname(tport_t *, char const *, su_addrinfo_t const *, char const *),
hunk ./libsofia-sip-ua/tport/tport.c 403
-  tport_wakeup(su_root_magic_t *m, su_wait_t *w, tport_t *self),
hunk ./libsofia-sip-ua/tport/tport.c 950
-  tport_master_t *mr = pri->pri_master;
hunk ./libsofia-sip-ua/tport/tport.c 953
-  su_wait_t wait[1] = { SU_WAIT_INIT };
hunk ./libsofia-sip-ua/tport/tport.c 954
-  int index = 0;
hunk ./libsofia-sip-ua/tport/tport.c 965
-           su_wait_destroy(wait),                                   \
hunk ./libsofia-sip-ua/tport/tport.c 1010
-   * The su_wait_create() below makes the socket non-blocking anyway. */
+   * The tport_register_secondary() below makes the socket non-blocking 
anyway. */
hunk ./libsofia-sip-ua/tport/tport.c 1026
-  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 (tport_register_secondary(self, wakeup, events) == -1)
+    TPORT_CONNECT_ERROR(su_errno(), tport_register_secondary);
hunk ./libsofia-sip-ua/tport/tport.c 1040
-  tprb_append(&pri->pri_open, self);
-
hunk ./libsofia-sip-ua/tport/tport.c 1043
+/** Register a new secondary transport. @internal */
+int tport_register_secondary(tport_t *self, su_wakeup_f wakeup, int events)
+{
+  int i;
+  su_root_t *root = tport_is_secondary(self) ? self->tp_master->mr_root : NULL;
+  su_wait_t wait[1] = { SU_WAIT_INIT };
+
+  if (root != NULL
+      /* Create wait object with appropriate events. */
+      &&
+      su_wait_create(wait, self->tp_socket, events) != -1
+      /* Register socket to root */
+      &&
+      (i = su_root_register(root, wait, wakeup, self, 0)) != -1) {
+
+    self->tp_index = i;
+    self->tp_events = events;
+
+    tprb_append(&self->tp_pri->pri_open, self);
+    return 0;
+  }
+
+  su_wait_destroy(wait);
+  return -1;
+}
+
hunk ./libsofia-sip-ua/tport/tport.c 2366
-static
hunk ./libsofia-sip-ua/tport/tport.c 2591
-  self = tport_alloc_secondary(pri, s, 1, &reason);
-
-  if (self) {
-    int i;
-    su_root_t *root = self->tp_master->mr_root;
-    su_wakeup_f wakeup = tport_wakeup;
+  if ((self = tport_alloc_secondary(pri, s, 1, &reason)) == NULL) {
+    SU_DEBUG_3(("%s(%p): incoming secondary on "TPN_FORMAT
+                " failed. reason = %s\n", __func__, pri, 
+                TPN_ARGS(pri->pri_primary->tp_name), reason));
+    return 0;
+  }
+  else {
hunk ./libsofia-sip-ua/tport/tport.c 2599
-    su_wait_t wait[1] = { SU_WAIT_INIT };
hunk ./libsofia-sip-ua/tport/tport.c 2602
-    if (/* Create wait object with appropriate events. */
-       su_wait_create(wait, s, events) != -1
-       /* Register socket to root */
+    if (/* Name this transport */
+        tport_setname(self, pri->pri_protoname, ai, NULL) != -1 
+       /* Register this secondary */ 
hunk ./libsofia-sip-ua/tport/tport.c 2606
-       (i = su_root_register(root, wait, wakeup, self, 0)) != -1) {
+       tport_register_secondary(self, tport_wakeup, events) != -1) {
hunk ./libsofia-sip-ua/tport/tport.c 2608
-      self->tp_index     = i;
hunk ./libsofia-sip-ua/tport/tport.c 2610
-      self->tp_events = events;
-
-      if (tport_setname(self, pri->pri_protoname, ai, NULL) != -1) {
-       SU_DEBUG_5(("%s(%p): new connection from " TPN_FORMAT "\n",
-                   __func__,  (void *)self, TPN_ARGS(self->tp_name)));
hunk ./libsofia-sip-ua/tport/tport.c 2611
-       tprb_append(&pri->pri_open, self);
+      SU_DEBUG_5(("%s(%p): new connection from " TPN_FORMAT "\n",
+                  __func__,  (void *)self, TPN_ARGS(self->tp_name)));
hunk ./libsofia-sip-ua/tport/tport.c 2614
-       /* Return succesfully */
-       return 0;
-      }
+      return 0;
hunk ./libsofia-sip-ua/tport/tport.c 2616
-    else
-      su_wait_destroy(wait);
hunk ./libsofia-sip-ua/tport/tport.c 2620
+    self = NULL;
hunk ./libsofia-sip-ua/tport/tport.c 2623
-  /* XXX - report error ? */
-
hunk ./libsofia-sip-ua/tport/tport.c 2731
-static int tport_wakeup(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
+int tport_wakeup(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
hunk ./libsofia-sip-ua/tport/tport_internal.h 412
+int tport_register_secondary(tport_t *self, su_wakeup_f wakeup, int events);
hunk ./libsofia-sip-ua/tport/tport_internal.h 430
+int tport_setname(tport_t *, char const *, su_addrinfo_t const *, char const 
*);
+
+int tport_wakeup(su_root_magic_t *magic, su_wait_t *w, tport_t *self);
}

[Early TLS Handshake and Verification
Jarod Neuner <janeu...@networkharbor.com>**20081216221937
 
 tport_type_tls.c:
 * tport_tls_accept():
   - Replaces tport_accept for incoming TLS connections.
 * tport_tls_connect():
   - Replaces tport_base_connect() for outgoing TLS connections.
 
 tport_tls.c:
 * tls_t now use a memory home instead of malloc.
 * removed tls_check_hosts()
 * tls_connect():
   - Replaces tport_base_connect for TLS connection setup.
   - Completes TLS handshake and verifies peer certificates.
   - Destroys suspect TLS connections before sending/receiving payload.
   - Populates a su_strlst_t with subjects from the peer certificate.
 
 tport.c:
 * tport_is_verified()
   - true if peer certificate validated successfully
 * tport_delivered_from_subjects()
   - Certificate subjects listed in the peer certificate.
 
] {
hunk ./libsofia-sip-ua/tport/sofia-sip/tport.h 39
+#ifndef SU_STRLST_H
+#include <sofia-sip/su_strlst.h>
+#endif
hunk ./libsofia-sip-ua/tport/sofia-sip/tport.h 273
+/** Test if transport provided a verified certificate chain (TLS only) */
+TPORT_DLL int tport_is_verified(tport_t const *tport);
+
hunk ./libsofia-sip-ua/tport/sofia-sip/tport.h 341
+/** Return TLS Subjects provided by the source transport */
+TPORT_DLL su_strlst_t *tport_delivered_from_subjects(tport_t *tp, msg_t const 
*msg);
+
hunk ./libsofia-sip-ua/tport/tport.c 271
+}
hunk ./libsofia-sip-ua/tport/tport.c 273
+/** Return true if transport certificate verified successfully */
+int tport_is_verified(tport_t const *self)
+{
+  return tport_has_tls(self) && self->tp_verified;
hunk ./libsofia-sip-ua/tport/tport.c 3047
+
+/** Return TLS Subjects provided by the source transport */
+su_strlst_t *tport_delivered_from_subjects(tport_t *tp, msg_t const *msg)
+{
+  if (tp && msg && msg == tp->tp_master->mr_delivery->d_msg) {
+    tport_t *tp_sec = tp->tp_master->mr_delivery->d_tport;
+    return (tp_sec) ? tp_sec->tp_subjects : NULL;
+  }
+  else
+    return NULL;
+}
hunk ./libsofia-sip-ua/tport/tport_internal.h 43
+#include <sofia-sip/su_strlst.h>
hunk ./libsofia-sip-ua/tport/tport_internal.h 159
+  unsigned            tp_verified:1;     /**< Certificate Chain was verified */
hunk ./libsofia-sip-ua/tport/tport_internal.h 182
+  su_strlst_t        *tp_subjects;      /**< Transport Subjects.
+                                         *
+                                         * Subject Name(s) provided by the 
+                                         * peer in a TLS connection (if 
secondary).
+                                         */
+
hunk ./libsofia-sip-ua/tport/tport_tls.c 38
+#define SU_WAKEUP_ARG_T  struct tport_s
hunk ./libsofia-sip-ua/tport/tport_tls.c 42
+#include <sofia-sip/su_alloc.h>
hunk ./libsofia-sip-ua/tport/tport_tls.c 66
-#include "tport_internal.h"
hunk ./libsofia-sip-ua/tport/tport_tls.c 69
-enum  { tls_master, tls_slave };
+enum  { tls_master = 0, tls_slave = 1};
hunk ./libsofia-sip-ua/tport/tport_tls.c 72
+  su_home_t home[1];
hunk ./libsofia-sip-ua/tport/tport_tls.c 76
-  int type;
-  int verified;
+  unsigned int type:1,
+               accept:1,
+               verify_outgoing:1,
+               verify_incoming:1,
+               verified:1;
hunk ./libsofia-sip-ua/tport/tport_tls.c 93
-  char *hosts[TLS_MAX_HOSTS + 1];
+  su_strlst_t *subject;
hunk ./libsofia-sip-ua/tport/tport_tls.c 130
-  tls_t *tls = calloc(1, sizeof(*tls));
+  tls_t *tls = su_home_new(sizeof(*tls));
+  memset(((void *)tls) + sizeof(su_home_t), 0, sizeof(*tls) - 
sizeof(su_home_t));
hunk ./libsofia-sip-ua/tport/tport_tls.c 134
-    tls->type = type;
+    tls->type = type == tls_master ? tls_master : tls_slave;
hunk ./libsofia-sip-ua/tport/tport_tls.c 277
+  tls->verify_incoming = tls->verify_outgoing = ti->verify_peer ? 1 : 0;
+
hunk ./libsofia-sip-ua/tport/tport_tls.c 291
-  int k;
-
hunk ./libsofia-sip-ua/tport/tport_tls.c 294
-  if (tls->read_buffer)
-    free(tls->read_buffer), tls->read_buffer = NULL;
-
hunk ./libsofia-sip-ua/tport/tport_tls.c 303
-  for (k = 0; k < TLS_MAX_HOSTS; k++)
-    if (tls->hosts[k]) {
-      free(tls->hosts[k]), tls->hosts[k] = NULL;
-    }
-
-  free(tls);
+  su_home_unref(tls->home);
hunk ./libsofia-sip-ua/tport/tport_tls.c 370
+    tls->accept = accept ? 1 : 0;
hunk ./libsofia-sip-ua/tport/tport_tls.c 372
-    if (!(tls->read_buffer = malloc(tls_buffer_size)))
-      free(tls), tls = NULL;
+    if (!(tls->read_buffer = su_alloc(tls->home, tls_buffer_size)))
+      su_home_unref(tls->home), tls = NULL;
hunk ./libsofia-sip-ua/tport/tport_tls.c 391
-  if (accept)
-    SSL_set_accept_state(tls->con);
-  else
-    SSL_set_connect_state(tls->con);
hunk ./libsofia-sip-ua/tport/tport_tls.c 394
-  tls_read(tls); /* XXX - works only with non-blocking sockets */
hunk ./libsofia-sip-ua/tport/tport_tls.c 410
-static char *tls_strdup(char const *s)
-{
-  if (s) {
-    size_t len = strlen(s) + 1;
-    char *d = malloc(len);
-    if (d)
-      memcpy(d, s, len);
-    return d;
-  }
-  return NULL;
-}
-
hunk ./libsofia-sip-ua/tport/tport_tls.c 415
-  int k, i, j, error;
+  int i, j, error;
hunk ./libsofia-sip-ua/tport/tport_tls.c 425
-  for (k = 0; k < TLS_MAX_HOSTS && tls->hosts[k]; k++)
-    ;
+  if (!tls->subject)
+    tls->subject = su_strlst_create(tls->home);
hunk ./libsofia-sip-ua/tport/tport_tls.c 449
-      if (strcmp(value->name, "DNS") == 0) {
-       if (k < TLS_MAX_HOSTS) {
-         tls->hosts[k] = tls_strdup(value->value);
-         k += tls->hosts[k] != NULL;
-       }
-      }
+      if (strcmp(value->name, "DNS") == 0)
+        su_strlst_dup_append(tls->subject, value->value);
hunk ./libsofia-sip-ua/tport/tport_tls.c 452
-       char const *uri = strchr(value->value, ':');
-       if (uri ++ && k < TLS_MAX_HOSTS) {
-         tls->hosts[k] = tls_strdup(uri);
-         k += tls->hosts[k] != NULL;
-       }
+       char *uri = su_strlst_dup_append(tls->subject, value->value);
+       char const *url = strchr(uri, ':');
+       if (url++)
+         su_strlst_append(tls->subject, url);
hunk ./libsofia-sip-ua/tport/tport_tls.c 460
-  if (k < TLS_MAX_HOSTS) {
+  {
hunk ./libsofia-sip-ua/tport/tport_tls.c 470
-       for (i = 0; tls->hosts[i]; i++)
-         if (strcasecmp(tls->hosts[i], name) == 0)
+       for (i = 0; i < su_strlst_len(tls->subject); i++)
+         if (strcasecmp(su_strlst_item(tls->subject, i), name) == 0)
hunk ./libsofia-sip-ua/tport/tport_tls.c 474
-       if (i == k)
-         tls->hosts[k++] = tls_strdup(name);
+       if (i == su_strlst_len(tls->subject))
+         su_strlst_dup_append(tls->subject, name);
hunk ./libsofia-sip-ua/tport/tport_tls.c 487
+  if (tls->accept && !tls->verify_incoming)
+    return X509_V_OK;
+  else if (!tls->accept && !tls->verify_outgoing)
+    return X509_V_OK;
hunk ./libsofia-sip-ua/tport/tport_tls.c 494
-int tls_check_hosts(tls_t *tls, char const *hosts[TLS_MAX_HOSTS])
-{
-  int i, j;
-
-  if (tls == NULL) { errno = EINVAL; return -1; }
-  if (!tls->verified) { errno = EAGAIN; return -1; }
-
-  if (!hosts)
-    return 0;
-
-  for (i = 0; hosts[i]; i++) {
-    for (j = 0; tls->hosts[j]; j++) {
-      if (strcasecmp(hosts[i], tls->hosts[j]) == 0)
-       break;
-    }
-    if (tls->hosts[j] == NULL) {
-      errno = EACCES;
-      return -1;
-    }
-  }
-
-  return 0;
-}
-
hunk ./libsofia-sip-ua/tport/tport_tls.c 549
-           tls->type == tls_slave ? "server" : "client",
+           tls->accept ? "server" : "client",
hunk ./libsofia-sip-ua/tport/tport_tls.c 561
-  if (!tls->verified) {
-    int err = tls_post_connection_check(tls);
-
-    if (err != X509_V_OK &&
-       err != SSL_ERROR_SYSCALL &&
-       err != SSL_ERROR_WANT_WRITE &&
-       err != SSL_ERROR_WANT_READ) {
-      SU_DEBUG_1((
-                "%s: server certificate doesn't verify\n",
-                "tls_read"));
-    }
-  }
-
hunk ./libsofia-sip-ua/tport/tport_tls.c 641
-  if (!tls->verified) {
-    if (tls_post_connection_check(tls) != X509_V_OK) {
-      SU_DEBUG_1((
-                "tls_read: server certificate doesn't verify\n"));
-    }
-  }
-
hunk ./libsofia-sip-ua/tport/tport_tls.c 689
+int tls_connect(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
+{
+  tport_master_t *mr = self->tp_master;
+  tport_tls_t *tlstp = (tport_tls_t *)self;
+  tls_t *tls;
+  int events = su_wait_events(w, self->tp_socket);
+  int error;
+
+  SU_DEBUG_7(("%s(%p): events%s%s%s%s\n", __func__, (void *)self, 
+              events & (SU_WAIT_CONNECT) ? " CONNECTING" : "",
+              events & SU_WAIT_IN  ? " NEGOTIATING" : "",
+              events & SU_WAIT_ERR ? " ERROR" : "",
+              events & SU_WAIT_HUP ? " HANGUP" : ""));
+
+#if HAVE_POLL
+  assert(w->fd == self->tp_socket);
+#endif
+
+  if (events & SU_WAIT_ERR)
+    tport_error_event(self);
+
+  if (events & SU_WAIT_HUP && !self->tp_closed)
+    tport_hup_event(self);
+
+  if (self->tp_closed)
+    return 0;
+
+  error = su_soerror(self->tp_socket);
+  if (error) {
+    tport_error_report(self, error, NULL);
+    return 0;
+  }
+
+  if ((tls = tlstp->tlstp_context) == NULL) {
+    SU_DEBUG_3(("%s(%p): Error: no TLS context data for connected socket.\n", 
+                __func__, tlstp));
+    tport_close(self);
+    tport_set_secondary_timer(self);
+    return 0;
+  }
+
+  if (self->tp_is_connected == 0) {
+    int ret, status;
+
+    ret = tls->accept ? SSL_accept(tls->con) : SSL_connect(tls->con);
+    status = SSL_get_error(tls->con, ret);
+
+    switch (status) {
+      case SSL_ERROR_WANT_READ:
+        /* OpenSSL is waiting for the peer to send handshake data */
+        self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP;
+        su_root_eventmask(mr->mr_root, self->tp_index,
+                         self->tp_socket, self->tp_events);
+        return 0;
+
+      case SSL_ERROR_WANT_WRITE:
+        /* OpenSSL is waiting for the peer to receive handshake data */
+        self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP | SU_WAIT_OUT;
+        su_root_eventmask(mr->mr_root, self->tp_index, 
+                           self->tp_socket, self->tp_events);
+        return 0;
+
+      case SSL_ERROR_NONE:
+        /* TLS Handshake complete */
+       if ( tls_post_connection_check(tls) == X509_V_OK ) {
+          su_wait_t wait[1] = {SU_WAIT_INIT};
+          tport_master_t *mr = self->tp_master;
+
+          su_root_deregister(mr->mr_root, self->tp_index);
+          self->tp_index = -1;
+          self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP;
+
+          if ((su_wait_create(wait, self->tp_socket, self->tp_events) == -1) ||
+             ((self->tp_index = su_root_register(mr->mr_root, wait, 
tport_wakeup, 
+                                                           self, 0)) == -1)) {
+            tport_close(self);
+            tport_set_secondary_timer(self);
+           return 0;
+          }
+
+          tls->read_events = SU_WAIT_IN;
+          tls->write_events = 0;
+          self->tp_is_connected = 1;
+         self->tp_verified = tls->verified;
+         self->tp_subjects = tls->subject == NULL ? NULL :
+                             su_strlst_dup(self->tp_home, tls->subject); 
+
+         if (tport_has_queued(self))
+            tport_send_event(self);
+          else
+            tport_set_secondary_timer(self);
+
+          return 0;
+       }
+       break;
+
+      default:
+        {
+         char errbuf[64];
+         ERR_error_string_n(status, errbuf, 64);
+          SU_DEBUG_3(("%s(%p): TLS setup failed (%s)\n", 
+                   __func__, self, errbuf));
+        }
+        break;
+    }
+  }
+
+  /* TLS Handshake Failed or Peer Certificate did not Verify */
+  tport_close(self);
+  tport_set_secondary_timer(self);
+
+  return 0;
+}
+
+
hunk ./libsofia-sip-ua/tport/tport_tls.h 42
+#include "tport_internal.h"
+
hunk ./libsofia-sip-ua/tport/tport_tls.h 69
+typedef struct tport_tls_s {
+  tport_t  tlstp_tp[1];
+  tls_t   *tlstp_context;
+  char    *tlstp_buffer;
+} tport_tls_t;
+
+typedef struct tport_tls_primary_s {
+  tport_primary_t tlspri_pri[1];
+  tls_t *tlspri_master;
+} tport_tls_primary_t;
+
hunk ./libsofia-sip-ua/tport/tport_tls.h 90
+int tls_connect(su_root_magic_t *magic, su_wait_t *w, tport_t *self);
hunk ./libsofia-sip-ua/tport/tport_tls.h 94
-int tls_check_hosts(tls_t *tls, char const *hosts[TLS_MAX_HOSTS]);
-
hunk ./libsofia-sip-ua/tport/tport_type_tls.c 41
+#define SU_WAKEUP_ARG_T  struct tport_s
+
hunk ./libsofia-sip-ua/tport/tport_type_tls.c 94
-
-typedef struct
-{
-  tport_primary_t tlspri_pri[1];
-  tls_t *tlspri_master;
-} tport_tls_primary_t;
-
-typedef struct
-{
-  tport_t tlstp_tp[1];
-  tls_t  *tlstp_context;
-  char   *tlstp_buffer;    /**< 2k Buffer  */
-} tport_tls_t;
+static int tport_tls_accept(tport_primary_t *pri, int events);
+static tport_t *tport_tls_connect(tport_primary_t *pri, su_addrinfo_t *ai,
+                                  tp_name_t const *tpn);
+static void tport_tls_deliver(tport_t *self, msg_t *msg, su_time_t now);
hunk ./libsofia-sip-ua/tport/tport_type_tls.c 105
-  tport_accept,
-  NULL,
+  tport_tls_accept,
+  tport_tls_connect,
hunk ./libsofia-sip-ua/tport/tport_type_tls.c 123
-  tport_accept,
-  NULL,
+  tport_tls_accept,
+  tport_tls_connect,
hunk ./libsofia-sip-ua/tport/tport_type_tls.c 524
+static
+int tport_tls_accept(tport_primary_t *pri, int events)
+{
+  tport_t *self;
+  su_addrinfo_t ai[1];
+  su_sockaddr_t su[1];
+  socklen_t sulen = sizeof su;
+  su_socket_t s = INVALID_SOCKET, l = pri->pri_primary->tp_socket;
+  char const *reason = "accept";
+
+  if (events & SU_WAIT_ERR)
+    tport_error_event(pri->pri_primary);
+
+  if (!(events & SU_WAIT_ACCEPT))
+    return 0;
+
+  memcpy(ai, pri->pri_primary->tp_addrinfo, sizeof ai);
+  ai->ai_canonname = NULL;
+
+  s = accept(l, &su->su_sa, &sulen);
+
+  if (s < 0) {
+    tport_error_report(pri->pri_primary, su_errno(), NULL);
+    return 0;
+  }
+
+  ai->ai_addr = &su->su_sa, ai->ai_addrlen = sulen;
+
+  /* Alloc a new transport object, then register socket events with it */
+  if ((self = tport_alloc_secondary(pri, s, 1, &reason)) == NULL) {
+    SU_DEBUG_3(("%s(%p): incoming secondary on "TPN_FORMAT
+                " failed. reason = %s\n", __func__, pri, 
+                TPN_ARGS(pri->pri_primary->tp_name), reason));
+    return 0;
+  }
+  else {
+    tport_tls_t *tlstp = (tport_tls_t *)self;
+    tport_tls_primary_t *tlspri = (tport_tls_primary_t *)self->tp_pri;
+    int events = SU_WAIT_IN|SU_WAIT_ERR|SU_WAIT_HUP;
+
+    SU_CANONIZE_SOCKADDR(su);
+
+    if (/* Name this transport */
+        tport_setname(self, pri->pri_protoname, ai, NULL) != -1
+       /* Register this secondary */
+       &&
+       tport_register_secondary(self, tls_connect, events) != -1) {
+
+      self->tp_conn_orient = 1;
+      self->tp_is_connected = 0;
+
+      tlstp->tlstp_context = tls_init_slave(tlspri->tlspri_master, s);
+
+      SU_DEBUG_5(("%s(%p): new connection from " TPN_FORMAT "\n",
+                 __func__,  (void *)self, TPN_ARGS(self->tp_name)));
+
+      /* Return succesfully */
+      return 0;
+    }
+
+    /* Failure: shutdown socket,  */
+    tport_close(self);
+    tport_zap_secondary(self);
+    self = NULL;
+  }
+
+  return 0;
+}
+
+static
+tport_t *tport_tls_connect(tport_primary_t *pri,
+                           su_addrinfo_t *ai,
+                          tp_name_t const *tpn)
+{
+  tport_t *self = NULL;
+
+  su_socket_t s, server_socket;
+  int events = SU_WAIT_CONNECT | SU_WAIT_ERR;
+
+  int err;
+  unsigned errlevel = 3;
+  char buf[TPORT_HOSTPORTSIZE];
+  char const *what;
+
+  s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+  if (s == INVALID_SOCKET)
+    goto sys_error;
+
+  what = "tport_alloc_secondary";
+  if ((self = tport_alloc_secondary(pri, s, 0, &what)) == NULL)
+    goto sys_error;
+
+  self->tp_conn_orient = 1;
+
+  if ((server_socket = pri->pri_primary->tp_socket) != INVALID_SOCKET) {
+    su_sockaddr_t susa;
+    socklen_t susalen = sizeof(susa);
+
+    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())));
+      }
+    }
+  }
+
+  if (connect(s, ai->ai_addr, (socklen_t)(ai->ai_addrlen)) == SOCKET_ERROR) {
+    err = su_errno();
+    if (!su_is_blocking(err))
+      goto sys_error;
+  }
+
+  if (tport_setname(self, tpn->tpn_proto, ai, tpn->tpn_canon) != -1
+      &&
+      tport_register_secondary(self, tls_connect, events) != -1) {
+    tport_tls_t *tlstp = (tport_tls_t *)self;
+    tport_tls_primary_t *tlspri = (tport_tls_primary_t *)self->tp_pri;
+    tlstp->tlstp_context = tls_init_client(tlspri->tlspri_master, s);
+  }
+  else
+    goto sys_error;
+
+  SU_DEBUG_5(("%s(%p): connecting to " TPN_FORMAT "\n",
+              __func__, (void *)self, TPN_ARGS(self->tp_name)));
+  
+  tport_set_secondary_timer(self);
+
+  return self;
+
+sys_error:
+  err = errno;
+  if (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));
+  tport_zap_secondary(self);
+  su_seterrno(err);
+  return NULL;
+}
+
+
}

Context:

[nta: NULL host and port in user Via are filled automaticaly
Stas Maximov <smaxi...@ieee.org>**20081215143145
 
 NULL host or port in user-supplied Via header will be filled
 automaticaly by NTA, just like branch and rport params.
 
 Added related test case to test_nta_api.c.
] 
[su_taglist.c. removed globals which should have been static in first place
Pekka Pessi <first.l...@nokia.com>**20081211173213
 
 - t_null_next(), t_null_move(), t_null_dup(), t_null_copy(), t_null_find()
 - t_skip_next(), t_skip_move(), t_skip_len(), t_skip_dup(), t_skip_filter()
 - t_next_next(), t_next_move(), t_next_len(), t_next_dup(), t_next_filter()
] 
[su: removed private functions accidentally declared as globals
Pekka Pessi <first.l...@nokia.com>**20081208145904
 
 su_t64_to_time(), mutex_trylocker(), su_port_set_system_preferences()
] 
[sofia-sip/su_uniqueid.h: proper prototype for su_random()
Pekka Pessi <first.l...@nokia.com>**20081211173249] 
[su/addrinfo.c, su/localinfo.c: made usage() static
Pekka Pessi <first.l...@nokia.com>**20081211173029
 
 Make -Wmissing-prototypes happy.
] 
[sdp_print.c: print sdptl in lowercase, too
Pekka Pessi <first.l...@nokia.com>**20081211120209] 
[RELEASE, configure.ac: opening development head
Pekka Pessi <first.l...@nokia.com>**20081209171108] 
[TAG rel-sofia-sip-1_12_10
Pekka Pessi <first.l...@nokia.com>**20081209122326] 
Patch bundle hash:
7ce90f570a0a21ed54737b674224391478639b52
------------------------------------------------------------------------------
SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada.
The future of the web can't happen without you.  Join us at MIX09 to help
pave the way to the Next Web now. Learn more and register at
http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/
_______________________________________________
Sofia-sip-devel mailing list
Sofia-sip-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sofia-sip-devel

Reply via email to