[Freeswitch-svn] [commit] r11769 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua/tport libsofia-sip-ua/tport/sofia-sip

FreeSWITCH SVN mikej at freeswitch.org
Wed Feb 11 08:11:33 PST 2009


Author: mikej
Date: Wed Feb 11 10:11:33 2009
New Revision: 11769

Log:
Tue Dec 16 16:19:37 CST 2008  Jarod Neuner <janeuner at 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.



Modified:
   freeswitch/trunk/libs/sofia-sip/.update
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c

Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update	(original)
+++ freeswitch/trunk/libs/sofia-sip/.update	Wed Feb 11 10:11:33 2009
@@ -1 +1 @@
-Wed Feb 11 10:10:42 CST 2009
+Wed Feb 11 10:11:23 CST 2009

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport.h	Wed Feb 11 10:11:33 2009
@@ -36,6 +36,9 @@
 #ifndef SU_H
 #include <sofia-sip/su.h>
 #endif
+#ifndef SU_STRLST_H
+#include <sofia-sip/su_strlst.h>
+#endif
 #ifndef SU_WAIT_H
 #include <sofia-sip/su_wait.h>
 #endif
@@ -267,6 +270,9 @@
 /** Test if transport has TLS. */
 TPORT_DLL int tport_has_tls(tport_t const *tport);
 
+/** Test if transport provided a verified certificate chain (TLS only) */
+TPORT_DLL int tport_is_verified(tport_t const *tport);
+
 /** Return true if transport is being updated. */
 TPORT_DLL int tport_is_updating(tport_t const *self);
 
@@ -332,6 +338,9 @@
 TPORT_DLL int tport_delivered_from(tport_t *tp, msg_t const *msg,
 				   tp_name_t name[1]);
 
+/** Return TLS Subjects provided by the source transport */
+TPORT_DLL su_strlst_t *tport_delivered_from_subjects(tport_t *tp, msg_t const *msg);
+
 /** Check if transport named is already resolved */
 TPORT_DLL int tport_name_is_resolved(tp_name_t const *);
 

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport.c	Wed Feb 11 10:11:33 2009
@@ -268,7 +268,12 @@
 int tport_has_tls(tport_t const *self)
 {
   return self && self->tp_pri->pri_has_tls;
+}
 
+/** Return true if transport certificate verified successfully */
+int tport_is_verified(tport_t const *self)
+{
+  return tport_has_tls(self) && self->tp_verified;
 }
 
 /** Return true if transport is being updated. */
@@ -3040,6 +3045,17 @@
   }
 }
 
+/** 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;
+}
+
 /** Return UDVM used to decompress the message. */
 int
 tport_delivered_with_comp(tport_t *tp, msg_t const *msg,

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h	Wed Feb 11 10:11:33 2009
@@ -40,6 +40,7 @@
 #endif
 
 #include <sofia-sip/su_uniqueid.h>
+#include <sofia-sip/su_strlst.h>
 
 #ifndef MSG_ADDR_H
 #include <sofia-sip/msg_addr.h>
@@ -155,6 +156,7 @@
   unsigned            tp_has_stun_server:1;
   unsigned            tp_trunc:1;
   unsigned            tp_is_connected:1; /**< Connection is established */
+  unsigned            tp_verified:1;     /**< Certificate Chain was verified */
   unsigned:0;
 
   tport_t *tp_left, *tp_right, *tp_dad; /**< Links in tport tree */
@@ -177,6 +179,12 @@
 					 * or peer name (if secondary).
 					 */
 
+  su_strlst_t        *tp_subjects;      /**< Transport Subjects.
+                                         *
+                                         * Subject Name(s) provided by the 
+                                         * peer in a TLS connection (if secondary).
+                                         */
+
 #define tp_protoname tp_name->tpn_proto
 #define tp_canon     tp_name->tpn_canon
 #define tp_host      tp_name->tpn_host

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c	Wed Feb 11 10:11:33 2009
@@ -35,9 +35,11 @@
 #include "config.h"
 
 #define OPENSSL_NO_KRB5 oh-no
+#define SU_WAKEUP_ARG_T  struct tport_s
 
 #include <sofia-sip/su_types.h>
 #include <sofia-sip/su.h>
+#include <sofia-sip/su_alloc.h>
 #include <sofia-sip/su_wait.h>
 
 #include <openssl/lhash.h>
@@ -61,18 +63,21 @@
 #endif
 
 #include "tport_tls.h"
-#include "tport_internal.h"
 
 char const tls_version[] = OPENSSL_VERSION_TEXT;
 
-enum  { tls_master, tls_slave };
+enum  { tls_master = 0, tls_slave = 1};
 
 struct tls_s {
+  su_home_t home[1];
   SSL_CTX *ctx;
   SSL *con;
   BIO *bio_con;
-  int type;
-  int verified;
+  unsigned int type:1,
+               accept:1,
+               verify_outgoing:1,
+               verify_incoming:1,
+               verified:1;
 
   /* Receiving */
   int read_events;
@@ -85,7 +90,7 @@
   size_t write_buffer_len;
 
   /* Host names */
-  char *hosts[TLS_MAX_HOSTS + 1];
+  su_strlst_t *subject;
 };
 
 enum { tls_buffer_size = 16384 };
@@ -122,10 +127,11 @@
 static
 tls_t *tls_create(int type)
 {
-  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));
 
   if (tls)
-    tls->type = type;
+    tls->type = type == tls_master ? tls_master : tls_slave;
 
   return tls;
 }
@@ -268,6 +274,8 @@
 		     ti->verify_peer == 1 ? SSL_VERIFY_PEER : SSL_VERIFY_NONE,
                      tls_verify_cb);
 
+  tls->verify_incoming = tls->verify_outgoing = ti->verify_peer ? 1 : 0;
+
   if (!SSL_CTX_set_cipher_list(tls->ctx, ti->cipher)) {
     SU_DEBUG_1(("%s: error setting cipher list\n", "tls_init_context"));
     tls_log_errors(1, "tls_init_context", 0);
@@ -280,14 +288,9 @@
 
 void tls_free(tls_t *tls)
 {
-  int k;
-
   if (!tls)
     return;
 
-  if (tls->read_buffer)
-    free(tls->read_buffer), tls->read_buffer = NULL;
-
   if (tls->con != NULL)
     SSL_shutdown(tls->con);
 
@@ -297,12 +300,7 @@
   if (tls->bio_con != NULL)
     BIO_free(tls->bio_con);
 
-  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);
 }
 
 int tls_get_socket(tls_t *tls)
@@ -369,9 +367,10 @@
 
   if (tls) {
     tls->ctx = master->ctx;
+    tls->accept = accept ? 1 : 0;
 
-    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;
   }
   if (!tls)
     return tls;
@@ -389,14 +388,9 @@
   }
 
   SSL_set_bio(tls->con, tls->bio_con, tls->bio_con);
-  if (accept)
-    SSL_set_accept_state(tls->con);
-  else
-    SSL_set_connect_state(tls->con);
   SSL_set_mode(tls->con, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
 
   su_setblocking(sock, 0);
-  tls_read(tls); /* XXX - works only with non-blocking sockets */
 
   return tls;
 }
@@ -413,24 +407,12 @@
   return tls_clone(master, sock, accept = 0);
 }
 
-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;
-}
-
 static
 int tls_post_connection_check(tls_t *tls)
 {
   X509 *cert;
   int extcount;
-  int k, i, j, error;
+  int i, j, error;
 
   if (!tls) return -1;
 
@@ -440,8 +422,8 @@
 
   extcount = X509_get_ext_count(cert);
 
-  for (k = 0; k < TLS_MAX_HOSTS && tls->hosts[k]; k++)
-    ;
+  if (!tls->subject)
+    tls->subject = su_strlst_create(tls->home);
 
   /* Find matching subjectAltName.DNS */
   for (i = 0; i < extcount; i++) {
@@ -464,23 +446,18 @@
 
     for (j = 0; j < sk_CONF_VALUE_num(values); j++) {
       value = sk_CONF_VALUE_value(values, j);
-      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);
       else if (strcmp(value->name, "URI") == 0) {
-	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);
       }
     }
   }
 
-  if (k < TLS_MAX_HOSTS) {
+  {
     X509_NAME *subject;
     char name[256];
 
@@ -490,12 +467,12 @@
 				    name, sizeof name) > 0) {
 	name[(sizeof name) - 1] = '\0';
 
-	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)
 	    break;
 
-	if (i == k)
-	  tls->hosts[k++] = tls_strdup(name);
+	if (i == su_strlst_len(tls->subject))
+	  su_strlst_dup_append(tls->subject, name);
       }
     }
   }
@@ -507,33 +484,13 @@
   if (error == X509_V_OK)
     tls->verified = 1;
 
+  if (tls->accept && !tls->verify_incoming)
+    return X509_V_OK;
+  else if (!tls->accept && !tls->verify_outgoing)
+    return X509_V_OK;
   return error;
 }
 
-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;
-}
-
 static
 int tls_error(tls_t *tls, int ret, char const *who,
 	      void *buf, int size)
@@ -589,7 +546,7 @@
 
   if (0)
     SU_DEBUG_1(("tls_read(%p) called on %s (events %u)\n", (void *)tls,
-	    tls->type == tls_slave ? "server" : "client",
+	    tls->accept ? "server" : "client",
 	    tls->read_events));
 
   if (tls->read_buffer_len)
@@ -601,19 +558,6 @@
   if (ret <= 0)
     return tls_error(tls, ret, "tls_read: SSL_read", NULL, 0);
 
-  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"));
-    }
-  }
-
   return (ssize_t)(tls->read_buffer_len = ret);
 }
 
@@ -694,13 +638,6 @@
 
   tls->write_events = 0;
 
-  if (!tls->verified) {
-    if (tls_post_connection_check(tls) != X509_V_OK) {
-      SU_DEBUG_1((
-		 "tls_read: server certificate doesn't verify\n"));
-    }
-  }
-
   ret = SSL_write(tls->con, buf, size);
   if (ret < 0)
     return tls_error(tls, ret, "tls_write: SSL_write", buf, size);
@@ -748,3 +685,118 @@
     ((mask & SU_WAIT_IN) ? tls->read_events : 0) |
     ((mask & SU_WAIT_OUT) ? tls->write_events : 0);
 }
+
+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;
+}
+

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h	Wed Feb 11 10:11:33 2009
@@ -39,6 +39,8 @@
 #include <sofia-sip/su_types.h>
 #endif
 
+#include "tport_internal.h"
+
 SOFIA_BEGIN_DECLS
 
 #define TLS_MAX_HOSTS (16)
@@ -64,6 +66,17 @@
 			 * used, it is 0. */
 } tls_issues_t;
 
+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;
+
 tls_t *tls_init_master(tls_issues_t *tls_issues);
 tls_t *tls_init_slave(tls_t *tls_master, int sock);
 tls_t *tls_init_client(tls_t *tls_master, int sock);
@@ -74,11 +87,10 @@
 int tls_want_read(tls_t *tls, int events);
 int tls_pending(tls_t const *tls);
 
+int tls_connect(su_root_magic_t *magic, su_wait_t *w, tport_t *self);
 ssize_t tls_write(tls_t *tls, void *buf, size_t size);
 int tls_want_write(tls_t *tls, int events);
 
-int tls_check_hosts(tls_t *tls, char const *hosts[TLS_MAX_HOSTS]);
-
 int tls_events(tls_t const *tls, int flags);
 
 SOFIA_END_DECLS

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c	Wed Feb 11 10:11:33 2009
@@ -38,6 +38,8 @@
 
 #include "config.h"
 
+#define SU_WAKEUP_ARG_T  struct tport_s
+
 #include "tport_internal.h"
 
 #include <stdlib.h>
@@ -89,19 +91,10 @@
 static int tport_tls_recv(tport_t *self);
 static ssize_t tport_tls_send(tport_t const *self, msg_t *msg,
 			      msg_iovec_t iov[], size_t iovused);
-
-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);
 
 tport_vtable_t const tport_tls_vtable =
 {
@@ -109,8 +102,8 @@
   sizeof (tport_tls_primary_t),
   tport_tls_init_primary,
   tport_tls_deinit_primary,
-  tport_accept,
-  NULL,
+  tport_tls_accept,
+  tport_tls_connect,
   sizeof (tport_tls_t),
   tport_tls_init_secondary,
   tport_tls_deinit_secondary,
@@ -127,8 +120,8 @@
   sizeof (tport_tls_primary_t),
   tport_tls_init_client,
   tport_tls_deinit_primary,
-  tport_accept,
-  NULL,
+  tport_tls_accept,
+  tport_tls_connect,
   sizeof (tport_tls_t),
   tport_tls_init_secondary,
   tport_tls_deinit_secondary,
@@ -527,3 +520,149 @@
 
   return size;
 }
+
+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;
+}
+



More information about the Freeswitch-svn mailing list