Index: contrib/ca_script/Makefile
===================================================================
--- contrib/ca_script/Makefile	(revision 29)
+++ contrib/ca_script/Makefile	(revision 19)
@@ -32,7 +32,4 @@
 O = WIDE
 OU = "AAA WG"
-
-#Default lifetime
-DAYS = 365
 
 #Values for the CA
@@ -133,5 +130,4 @@
 	@openssl ca $(CONFIG) -in $(DIR)/clients/csr/$(name).csr \
 		-out $(DIR)/clients/certs/$(name).cert \
-		-days $(DAYS) \
 		-batch
 	@ln -s $(DIR)/clients/certs/$(name).cert $(DIR)/certs/`openssl x509 -noout -hash < $(DIR)/clients/certs/$(name).cert`.0
Index: doc/freediameter.conf.sample
===================================================================
--- doc/freediameter.conf.sample	(revision 24)
+++ doc/freediameter.conf.sample	(revision 20)
@@ -68,5 +68,4 @@
 #ListenOn = "202.249.37.5";
 #ListenOn = "2001:200:903:2::202:1";
-#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0";
 
 ##############################################################
@@ -185,9 +184,9 @@
 #  No_TLS;       # assume transparent security instead of TLS
 #  Port = 3868;  # The port to connect to
+#  SCTP_streams = 30;
 #  TcTimer = 30;
 #  TwTimer = 30;
 #  ConnectTo = "202.249.37.5";
 #  ConnectTo = "2001:200:903:2::202:1";
-#  TLS_Prio = "NORMAL";
 # Examples:
 #ConnectPeer = "aaa.wide.ad.jp";
@@ -202,9 +201,11 @@
 SecPort = 3867;
 TLS_old_method;
+No_IP;
+Prefer_TCP;
 SCTP_streams = 50;
+ListenOn = "202.249.37.5";
+ListenOn = "2001:200:903:2::202:1";
 TcTimer = 60;
 TwTimer = 6;
-#ListenOn = "133.243.146.201";
-#ListenOn = "fe80::21d:9ff:fe89:7d68%eth0";
 NoRelay;
 LoadExtension = "extensions/dbg_monitor.fdx";
@@ -212,6 +213,6 @@
 LoadExtension = "extensions/dict_eap.fdx";
 ConnectPeer = "jules.nautilus6.org" ;
-ConnectPeer = "aaa.nautilus6.org" { No_TLS; No_IP; } ;
-TLS_Cred = "/etc/openssl-ca/clients/certs/test.cert" , "/etc/openssl-ca/clients/privkeys/test.key.pem";
+ConnectPeer = "aaa.nautilus6.org" { No_TLS; No_IP; No_TCP; SCTP_streams = 60; } ;
+TLS_Cred = "/etc/openssl-ca/clients/certs/fdtest.cert" , "/etc/openssl-ca/clients/privkeys/fdtest.key.pem";
 TLS_CA = "/etc/openssl-ca/public-www/cacert.pem";
 # TLS_CRL = "/etc/openssl-ca/public-www/crl.pem";
Index: extensions/dbg_monitor/monitor.c
===================================================================
--- extensions/dbg_monitor/monitor.c	(revision 25)
+++ extensions/dbg_monitor/monitor.c	(revision 11)
@@ -49,7 +49,7 @@
 static void got_sig(int signal)
 {
-	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_DICT, 0, NULL), /* continue */);
-	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_CONFIG, 0, NULL), /* continue */);
-	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_EXT, 0, NULL), /* continue */);
+	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_DICT, NULL), /* continue */);
+	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_CONFIG, NULL), /* continue */);
+	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_EXT, NULL), /* continue */);
 }
 /* Thread to display periodical debug information */
@@ -77,7 +77,6 @@
 		#endif /* DEBUG */
 		TRACE_DEBUG(NONE, "Monitor information");
-		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_QUEUES, 0, NULL), /* continue */);
-		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_SERV, 0, NULL), /* continue */);
-		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_PEERS, 0, NULL), /* continue */);
+		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_QUEUES, NULL), /* continue */);
+		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_PEERS, NULL), /* continue */);
 		pthread_testcancel();
 	}
Index: freeDiameter/CMakeLists.txt
===================================================================
--- freeDiameter/CMakeLists.txt	(revision 25)
+++ freeDiameter/CMakeLists.txt	(revision 20)
@@ -10,9 +10,7 @@
 SET(FD_COMMON_SRC
 	fD.h
-	cnxctx.h
 	config.c
 	cnxctx.c
 	dispatch.c
-	endpoints.c
 	extensions.c
 	dict_base_proto.c
@@ -23,9 +21,8 @@
 	p_psm.c
 	server.c
-	tcp.c
 	)
 
 IF(NOT DISABLE_SCTP)
-	SET(FD_COMMON_SRC ${FD_COMMON_SRC} sctp.c sctps.c)
+	SET(FD_COMMON_SRC ${FD_COMMON_SRC} sctp.c)
 ENDIF(NOT DISABLE_SCTP)
 
Index: freeDiameter/cnxctx.c
===================================================================
--- freeDiameter/cnxctx.c	(revision 30)
+++ freeDiameter/cnxctx.c	(revision 20)
@@ -35,770 +35,71 @@
 
 #include "fD.h"
-#include "cnxctx.h"
 
-/* The maximum size of Diameter message we accept to receive (<= 2^24) to avoid too big mallocs in case of trashed headers */
-#ifndef DIAMETER_MSG_SIZE_MAX
-#define DIAMETER_MSG_SIZE_MAX	65535	/* in bytes */
-#endif /* DIAMETER_MSG_SIZE_MAX */
-
-/* Connections contexts (cnxctx) in freeDiameter are wrappers around the sockets and TLS operations .
- * They are used to hide the details of the processing to the higher layers of the daemon.
- * They are always oriented on connections (TCP or SCTP), connectionless modes (UDP or SCTP) are not supported.
- */
-
-/* Note: this file could be moved to libfreeDiameter instead, but since it uses gnuTLS we prefer to keep it in the daemon */
-
-/* Lifetime of a cnxctx object:
- * 1) Creation
- *    a) a server socket:
- *       - create the object with fd_cnx_serv_tcp or fd_cnx_serv_sctp
- *       - start listening incoming connections: fd_cnx_serv_listen
- *       - accept new clients with fd_cnx_serv_accept.
- *    b) a client socket:
- *       - connect to a remote server with fd_cnx_cli_connect
- *
- * 2) Initialization
- *    - if TLS is started first, call fd_cnx_handshake
- *    - otherwise to receive clear messages, call fd_cnx_start_clear. fd_cnx_handshake can be called later.
- *
- * 3) Usage
- *    - fd_cnx_receive, fd_cnx_send : exchange messages on this connection (send is synchronous, receive is not, but blocking).
- *    - fd_cnx_recv_setaltfifo : when a message is received, the event is sent to an external fifo list. fd_cnx_receive does not work when the alt_fifo is set.
- *    - fd_cnx_getid : retrieve a descriptive string for the connection (for debug)
- *    - fd_cnx_getremoteid : identification of the remote peer (IP address or fqdn)
- *    - fd_cnx_getcred : get the remote peer TLS credentials, after handshake
- *    - fd_cnx_getendpoints : get the endpoints (IP) of the connection
- *
- * 4) End
- *    - fd_cnx_destroy
- */
-
-
-/*******************************************/
-/*     Creation of a connection object     */
-/*******************************************/
-
-/* Initialize a context structure */
-static struct cnxctx * fd_cnx_init(int full)
+/* Initialize a connection context */
+struct cnxctx * fd_cnx_init(int sock, int proto)
 {
 	struct cnxctx * conn = NULL;
-
-	TRACE_ENTRY("%d", full);
-
+	
+	TRACE_ENTRY("%d %d", sock, proto);
+	CHECK_PARAMS_DO( (proto == IPPROTO_TCP) || (proto == IPPROTO_SCTP), return NULL);
+	
 	CHECK_MALLOC_DO( conn = malloc(sizeof(struct cnxctx)), return NULL );
 	memset(conn, 0, sizeof(struct cnxctx));
-
-	if (full) {
-		CHECK_FCT_DO( fd_fifo_new ( &conn->cc_incoming ), return NULL );
+	
+	conn->cc_socket = sock;
+	conn->cc_proto  = proto;
+	
+	fd_list_init(&conn->cc_ep_remote, conn);
+	fd_list_init(&conn->cc_ep_local, conn);
+	
+	if (proto == IPPROTO_SCTP) {
+#ifndef DISABLE_SCTP
+		CHECK_FCT_DO( fd_sctp_get_str_info( sock, &conn->cc_sctp_para.str_in, &conn->cc_sctp_para.str_out ),
+				{ free(conn); return NULL; } );
+		conn->cc_sctp_para.pairs = (conn->cc_sctp_para.str_out < conn->cc_sctp_para.str_in) ? conn->cc_sctp_para.str_out : conn->cc_sctp_para.str_in;
+#else /* DISABLE_SCTP */
+		ASSERT(0);
+#endif /* DISABLE_SCTP */
 	}
-
+	
 	return conn;
 }
 
-/* Create and bind a server socket to the given endpoint and port */
-struct cnxctx * fd_cnx_serv_tcp(uint16_t port, int family, struct fd_endpoint * ep)
-{
-	struct cnxctx * cnx = NULL;
-	sSS dummy;
-	sSA * sa = (sSA *) &dummy;
-
-	TRACE_ENTRY("%hu %d %p", port, family, ep);
-
-	CHECK_PARAMS_DO( port, return NULL );
-	CHECK_PARAMS_DO( ep || family, return NULL );
-	CHECK_PARAMS_DO( (! family) || (family == AF_INET) || (family == AF_INET6), return NULL );
-	CHECK_PARAMS_DO( (! ep) || (!family) || (ep->ss.ss_family == family), return NULL );
-
-	/* The connection object */
-	CHECK_MALLOC_DO( cnx = fd_cnx_init(0), return NULL );
-
-	/* Prepare the socket address information */
-	if (ep) {
-		memcpy(sa, &ep->ss, sizeof(sSS));
-	} else {
-		memset(&dummy, 0, sizeof(dummy));
-		sa->sa_family = family;
-	}
-	if (sa->sa_family == AF_INET) {
-		((sSA4 *)sa)->sin_port = htons(port);
-	} else {
-		((sSA6 *)sa)->sin6_port = htons(port);
-	}
-
-	/* Create the socket */
-	CHECK_FCT_DO( fd_tcp_create_bind_server( &cnx->cc_socket, sa, sizeof(sSS) ), goto error );
-
-	/* Generate the name for the connection object */
-	{
-		char addrbuf[INET6_ADDRSTRLEN];
-		int  rc;
-		rc = getnameinfo(sa, sizeof(sSS), addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
-		if (rc)
-			snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
-		snprintf(cnx->cc_id, sizeof(cnx->cc_id), "Srv TCP [%s]:%hu (%d)", addrbuf, port, cnx->cc_socket);
-	}
-
-	cnx->cc_proto = IPPROTO_TCP;
-
-	return cnx;
-
-error:
-	fd_cnx_destroy(cnx);
-	return NULL;
-}
-
-/* Same function for SCTP, with a list of local endpoints to bind to */
-struct cnxctx * fd_cnx_serv_sctp(uint16_t port, struct fd_list * ep_list)
-{
-#ifdef DISABLE_SCTP
-	TRACE_DEBUG(INFO, "This function should never been called when SCTP is disabled...");
-	ASSERT(0);
-	CHECK_FCT_DO( ENOTSUP, return NULL);
-#else /* DISABLE_SCTP */
-	struct cnxctx * cnx = NULL;
-	sSS dummy;
-	sSA * sa = (sSA *) &dummy;
-
-	TRACE_ENTRY("%hu %p", port, ep_list);
-
-	CHECK_PARAMS_DO( port, return NULL );
-
-	/* The connection object */
-	CHECK_MALLOC_DO( cnx = fd_cnx_init(0), return NULL );
-
-	/* Create the socket */
-	CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, ep_list, port ), goto error );
-
-	/* Generate the name for the connection object */
-	snprintf(cnx->cc_id, sizeof(cnx->cc_id), "Srv SCTP :%hu (%d)", port, cnx->cc_socket);
-
-	cnx->cc_proto = IPPROTO_SCTP;
-
-	return cnx;
-
-error:
-	fd_cnx_destroy(cnx);
-	return NULL;
-#endif /* DISABLE_SCTP */
-}
-
-/* Allow clients to connect on the server socket */
-int fd_cnx_serv_listen(struct cnxctx * conn)
-{
-	CHECK_PARAMS( conn );
-
-	switch (conn->cc_proto) {
-		case IPPROTO_TCP:
-			CHECK_FCT(fd_tcp_listen(conn->cc_socket));
-			break;
-
-#ifndef DISABLE_SCTP
-		case IPPROTO_SCTP:
-			CHECK_FCT(fd_sctp_listen(conn->cc_socket));
-			break;
-#endif /* DISABLE_SCTP */
-
-		default:
-			CHECK_PARAMS(0);
-	}
-
-	return 0;
-}
-
-/* Accept a client (blocking until a new client connects) -- cancelable */
-struct cnxctx * fd_cnx_serv_accept(struct cnxctx * serv)
-{
-	struct cnxctx * cli = NULL;
-	sSS ss;
-	socklen_t ss_len = sizeof(ss);
-	int cli_sock = 0;
-	struct fd_endpoint * ep;
-
-	TRACE_ENTRY("%p", serv);
-	CHECK_PARAMS_DO(serv, return NULL);
-	
-	/* Accept the new connection -- this is blocking until new client enters or cancellation */
-	CHECK_SYS_DO( cli_sock = accept(serv->cc_socket, (sSA *)&ss, &ss_len), return NULL );
-	
-	if (TRACE_BOOL(INFO)) {
-		fd_log_debug("%s : accepted new client [", fd_cnx_getid(serv));
-		sSA_DUMP_NODE( &ss, NI_NUMERICHOST );
-		fd_log_debug("].\n");
-	}
-	
-	CHECK_MALLOC_DO( cli = fd_cnx_init(1), { shutdown(cli_sock, SHUT_RDWR); return NULL; } );
-	cli->cc_socket = cli_sock;
-	cli->cc_proto = serv->cc_proto;
-	
-	/* Generate the name for the connection object */
-	{
-		char addrbuf[INET6_ADDRSTRLEN];
-		char portbuf[10];
-		int  rc;
-		
-		/* Numeric values for debug */
-		rc = getnameinfo((sSA *)&ss, sizeof(sSS), addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV);
-		if (rc) {
-			snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
-			portbuf[0] = '\0';
-		}
-		
-		snprintf(cli->cc_id, sizeof(cli->cc_id), "Incoming %s [%s]:%s (%d) @ serv (%d)", 
-				IPPROTO_NAME(cli->cc_proto), 
-				addrbuf, portbuf, 
-				cli->cc_socket, serv->cc_socket);
-		
-		/* Name for log messages */
-		rc = getnameinfo((sSA *)&ss, sizeof(sSS), cli->cc_remid, sizeof(cli->cc_remid), NULL, 0, 0);
-		if (rc)
-			snprintf(cli->cc_remid, sizeof(cli->cc_remid), "[err:%s]", gai_strerror(rc));
-	}
-
-#ifndef DISABLE_SCTP
-	/* SCTP-specific handlings */
-	if (cli->cc_proto == IPPROTO_SCTP) {
-		/* Retrieve the number of streams */
-		CHECK_FCT_DO( fd_sctp_get_str_info( cli->cc_socket, &cli->cc_sctp_para.str_in, &cli->cc_sctp_para.str_out, NULL ), goto error );
-		if (cli->cc_sctp_para.str_out > cli->cc_sctp_para.str_in)
-			cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_out;
-		else
-			cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_in;
-	}
-#endif /* DISABLE_SCTP */
-
-	return cli;
-error:
-	fd_cnx_destroy(cli);
-	return NULL;
-}
-
-/* Client side: connect to a remote server -- cancelable */
-struct cnxctx * fd_cnx_cli_connect_tcp(sSA * sa /* contains the port already */, socklen_t addrlen)
-{
-	int sock;
-	struct cnxctx * cnx = NULL;
-	
-	TRACE_ENTRY("%p %d", sa, addrlen);
-	CHECK_PARAMS_DO( sa && addrlen, return NULL );
-	
-	/* Create the socket and connect, which can take some time and/or fail */
-	CHECK_FCT_DO( fd_tcp_client( &sock, sa, addrlen ), return NULL );
-	
-	if (TRACE_BOOL(INFO)) {
-		fd_log_debug("Connection established to server '");
-		sSA_DUMP_NODE_SERV( sa, NI_NUMERICSERV);
-		fd_log_debug("' (TCP:%d).\n", sock);
-	}
-	
-	/* Once the socket is created successfuly, prepare the remaining of the cnx */
-	CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); return NULL; } );
-	
-	cnx->cc_socket = sock;
-	cnx->cc_proto  = IPPROTO_TCP;
-	
-	/* Generate the names for the object */
-	{
-		char addrbuf[INET6_ADDRSTRLEN];
-		char portbuf[10];
-		int  rc;
-		
-		/* Numeric values for debug */
-		rc = getnameinfo(sa, addrlen, addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV);
-		if (rc) {
-			snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
-			portbuf[0] = '\0';
-		}
-		
-		snprintf(cnx->cc_id, sizeof(cnx->cc_id), "Client of TCP server [%s]:%s (%d)", addrbuf, portbuf, cnx->cc_socket);
-		
-		/* Name for log messages */
-		rc = getnameinfo(sa, addrlen, cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0);
-		if (rc)
-			snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc));
-	}
-	
-	return cnx;
-
-error:
-	fd_cnx_destroy(cnx);
-	return NULL;
-}
-
-/* Same for SCTP, accepts a list of remote addresses to connect to (see sctp_connectx for how they are used) */
-struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_list * list)
-{
-#ifdef DISABLE_SCTP
-	TRACE_DEBUG(INFO, "This function should never been called when SCTP is disabled...");
-	ASSERT(0);
-	CHECK_FCT_DO( ENOTSUP, return NULL);
-#else /* DISABLE_SCTP */
-	int sock;
-	struct cnxctx * cnx = NULL;
-	sSS primary;
-	
-	TRACE_ENTRY("%p", list);
-	CHECK_PARAMS_DO( list && !FD_IS_LIST_EMPTY(list), return NULL );
-	
-	CHECK_FCT_DO( fd_sctp_client( &sock, no_ip6, port, list ), return NULL );
-	
-	/* Once the socket is created successfuly, prepare the remaining of the cnx */
-	CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); return NULL; } );
-	
-	cnx->cc_socket = sock;
-	cnx->cc_proto  = IPPROTO_SCTP;
-	
-	/* Retrieve the number of streams and primary address */
-	CHECK_FCT_DO( fd_sctp_get_str_info( sock, &cnx->cc_sctp_para.str_in, &cnx->cc_sctp_para.str_out, &primary ), goto error );
-	if (cnx->cc_sctp_para.str_out > cnx->cc_sctp_para.str_in)
-		cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_out;
-	else
-		cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_in;
-	
-	if (TRACE_BOOL(INFO)) {
-		fd_log_debug("Connection established to server '");
-		sSA_DUMP_NODE_SERV( &primary, NI_NUMERICSERV);
-		fd_log_debug("' (SCTP:%d, %d/%d streams).\n", sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out);
-	}
-	
-	/* Generate the names for the object */
-	{
-		char addrbuf[INET6_ADDRSTRLEN];
-		char portbuf[10];
-		int  rc;
-		
-		/* Numeric values for debug */
-		rc = getnameinfo((sSA *)&primary, sizeof(sSS), addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV);
-		if (rc) {
-			snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
-			portbuf[0] = '\0';
-		}
-		
-		snprintf(cnx->cc_id, sizeof(cnx->cc_id), "Client of SCTP server [%s]:%s (%d)", addrbuf, portbuf, cnx->cc_socket);
-		
-		/* Name for log messages */
-		rc = getnameinfo((sSA *)&primary, sizeof(sSS), cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0);
-		if (rc)
-			snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc));
-	}
-	
-	return cnx;
-
-error:
-	fd_cnx_destroy(cnx);
-	return NULL;
-#endif /* DISABLE_SCTP */
-}
-
-/* Return a string describing the connection, for debug */
-char * fd_cnx_getid(struct cnxctx * conn)
-{
-	CHECK_PARAMS_DO( conn, return "" );
-	return conn->cc_id;
-}
-
-/* Return the protocol of a connection */
-int fd_cnx_getproto(struct cnxctx * conn)
-{
-	CHECK_PARAMS_DO( conn, return 0 );
-	return conn->cc_proto;
-}
-
-/* Return the TLS state of a connection */
-int fd_cnx_getTLS(struct cnxctx * conn)
-{
-	CHECK_PARAMS_DO( conn, return 0 );
-	return conn->cc_tls;
-}
-
-/* Get the list of endpoints (IP addresses) of the local and remote peers on this connection */
-int fd_cnx_getendpoints(struct cnxctx * conn, struct fd_list * local, struct fd_list * remote)
-{
-	TRACE_ENTRY("%p %p %p", conn, local, remote);
-	CHECK_PARAMS(conn);
-	
-	if (local) {
-		/* Retrieve the local endpoint(s) of the connection */
-		switch (conn->cc_proto) {
-			case IPPROTO_TCP: {
-				sSS ss;
-				socklen_t sl;
-				CHECK_FCT(fd_tcp_get_local_ep(conn->cc_socket, &ss, &sl));
-				CHECK_FCT(fd_ep_add_merge( local, (sSA *)&ss, sl, EP_FL_LL | EP_FL_PRIMARY));
-			}
-			break;
-
-			#ifndef DISABLE_SCTP
-			case IPPROTO_SCTP: {
-				CHECK_FCT(fd_sctp_get_local_ep(conn->cc_socket, local));
-			}
-			break;
-			#endif /* DISABLE_SCTP */
-
-			default:
-				CHECK_PARAMS(0);
-		}
-	}
-	
-	if (remote) {
-		/* Check we have a full connection object, not a listening socket (with no remote) */
-		CHECK_PARAMS( conn->cc_incoming );
-		
-		/* Retrieve the peer endpoint(s) of the connection */
-		switch (conn->cc_proto) {
-			case IPPROTO_TCP: {
-				sSS ss;
-				socklen_t sl;
-				CHECK_FCT(fd_tcp_get_remote_ep(conn->cc_socket, &ss, &sl));
-				CHECK_FCT(fd_ep_add_merge( remote, (sSA *)&ss, sl, EP_FL_LL | EP_FL_PRIMARY ));
-			}
-			break;
-
-			#ifndef DISABLE_SCTP
-			case IPPROTO_SCTP: {
-				CHECK_FCT(fd_sctp_get_remote_ep(conn->cc_socket, remote));
-			}
-			break;
-			#endif /* DISABLE_SCTP */
-
-			default:
-				CHECK_PARAMS(0);
-		}
-	}
-
-	return 0;
-}
-
-
-/* Get a string describing the remote peer address (ip address or fqdn) */
-char * fd_cnx_getremoteid(struct cnxctx * conn)
-{
-	CHECK_PARAMS_DO( conn, return "" );
-	return conn->cc_remid;
-}
-
-
-/**************************************/
-/*     Use of a connection object     */
-/**************************************/
-
-/* Receiver thread (TCP & noTLS) : incoming message is directly saved into the target queue */
-static void * rcvthr_notls_tcp(void * arg)
-{
-	struct cnxctx * conn = arg;
-	
-	TRACE_ENTRY("%p", arg);
-	CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
-	
-	/* Set the thread name */
-	{
-		char buf[48];
-		snprintf(buf, sizeof(buf), "Receiver (%d) TCP/noTLS)", conn->cc_socket);
-		fd_log_threadname ( buf );
-	}
-	
-	ASSERT( conn->cc_proto == IPPROTO_TCP );
-	ASSERT( conn->cc_tls == 0 );
-	ASSERT( Target_Queue(conn) );
-	
-	/* Receive from a TCP connection: we have to rebuild the message boundaries */
-	do {
-		uint8_t header[4];
-		uint8_t * newmsg;
-		size_t  length;
-		ssize_t ret = 0;
-		size_t	received = 0;
-
-		do {
-			ret = recv(conn->cc_socket, &header[received], sizeof(header) - received, 0);
-			if (ret <= 0) {
-				CHECK_SYS_DO(ret, /* continue */);
-				goto error; /* Stop the thread, the recipient of the event will cleanup */
-			}
-
-			received += ret;
-		} while (received < sizeof(header));
-
-		length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
-
-		/* Check the received word is a valid begining of a Diameter message */
-		if ((header[0] != DIAMETER_VERSION)	/* defined in <libfreeDiameter.h> */
-		   || (length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
-			/* The message is suspect */
-			TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], length);
-			goto error; /* Stop the thread, the recipient of the event will cleanup */
-		}
-
-		/* Ok, now we can really receive the data */
-		CHECK_MALLOC_DO(  newmsg = malloc( length ), goto error );
-		memcpy(newmsg, header, sizeof(header));
-
-		while (received < length) {
-			pthread_cleanup_push(free, newmsg); /* In case we are canceled, clean the partialy built buffer */
-			ret = recv(conn->cc_socket, newmsg + received, length - received, 0);
-			pthread_cleanup_pop(0);
-
-			if (ret <= 0) {
-				CHECK_SYS_DO(ret, /* continue */);
-				free(newmsg);
-				goto error; /* Stop the thread, the recipient of the event will cleanup */
-			}
-			received += ret;
-		}
-		
-		/* We have received a complete message, send it */
-		CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg), /* continue or destroy everything? */);
-		
-	} while (conn->cc_loop);
-	
-out:
-	TRACE_DEBUG(FULL, "Thread terminated");	
-	return NULL;
-error:
-	CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
-	goto out;
-}
-
-#ifndef DISABLE_SCTP
-/* Receiver thread (SCTP & noTLS) : incoming message is directly saved into cc_incoming, no need to care for the stream ID */
-static void * rcvthr_notls_sctp(void * arg)
-{
-	struct cnxctx * conn = arg;
-	uint8_t * buf;
-	size_t    bufsz;
-	int	  event;
-	
-	TRACE_ENTRY("%p", arg);
-	CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
-	
-	/* Set the thread name */
-	{
-		char buf[48];
-		snprintf(buf, sizeof(buf), "Receiver (%d) SCTP/noTLS)", conn->cc_socket);
-		fd_log_threadname ( buf );
-	}
-	
-	ASSERT( conn->cc_proto == IPPROTO_SCTP );
-	ASSERT( conn->cc_tls == 0 );
-	ASSERT( Target_Queue(conn) );
-	
-	do {
-		CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, NULL, &buf, &bufsz, &event), goto error );
-		if (event == FDEVP_CNX_ERROR) {
-			goto error;
-		}
-		
-		CHECK_FCT_DO( fd_event_send( Target_Queue(conn), event, bufsz, buf), goto error );
-		
-	} while (conn->cc_loop);
-	
-out:
-	TRACE_DEBUG(FULL, "Thread terminated");	
-	return NULL;
-error:
-	CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
-	goto out;
-}
-#endif /* DISABLE_SCTP */
-
-/* Returns 0 on error, received data size otherwise (always >= 0) */
-static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
-{
-	ssize_t ret;
-again:	
-	CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz),
-		{
-			switch (ret) {
-				case GNUTLS_E_REHANDSHAKE: 
-					CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
-						{
-							if (TRACE_BOOL(INFO)) {
-								fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s\n", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
-							}
-							ret = 0;
-							goto end;
-						} );
-
-				case GNUTLS_E_AGAIN:
-				case GNUTLS_E_INTERRUPTED:
-					goto again;
-
-				default:
-					TRACE_DEBUG(INFO, "This TLS error is not handled, assume unrecoverable error");
-					ret = 0;
-			}
-		} );
-end:	
-	return ret;
-}
-
-/* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */
-int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
-{
-	/* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP */
-	do {
-		uint8_t header[4];
-		uint8_t * newmsg;
-		size_t  length;
-		ssize_t ret = 0;
-		size_t	received = 0;
-
-		do {
-			ret = fd_tls_recv_handle_error(conn, session, &header[received], sizeof(header) - received);
-			if (ret == 0) {
-				/* The connection is closed */
-				goto out;
-			}
-			received += ret;
-		} while (received < sizeof(header));
-
-		length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
-
-		/* Check the received word is a valid beginning of a Diameter message */
-		if ((header[0] != DIAMETER_VERSION)	/* defined in <libfreeDiameter.h> */
-		   || (length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
-			/* The message is suspect */
-			TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], length);
-			goto out;
-		}
-
-		/* Ok, now we can really receive the data */
-		CHECK_MALLOC(  newmsg = malloc( length ) );
-		memcpy(newmsg, header, sizeof(header));
-
-		while (received < length) {
-			pthread_cleanup_push(free, newmsg); /* In case we are canceled, clean the partialy built buffer */
-			ret = fd_tls_recv_handle_error(conn, session, newmsg + received, length - received);
-			pthread_cleanup_pop(0);
-
-			if (ret == 0) {
-				free(newmsg);
-				goto out; /* Stop the thread, the recipient of the event will cleanup */
-			}
-			received += ret;
-		}
-		
-		/* We have received a complete message, send it */
-		CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg), /* continue or destroy everything? */);
-		
-	} while (1);
-out:
-	return ENOTCONN;
-}
-
-/* Receiver thread (TLS & 1 stream SCTP or TCP) : gnutls directly handles the socket, save records into the target queue */
-static void * rcvthr_tls_single(void * arg)
-{
-	struct cnxctx * conn = arg;
-	
-	TRACE_ENTRY("%p", arg);
-	CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto error);
-	
-	/* Set the thread name */
-	{
-		char buf[48];
-		snprintf(buf, sizeof(buf), "Receiver (%d) TLS/ single stream)", conn->cc_socket);
-		fd_log_threadname ( buf );
-	}
-	
-	ASSERT( conn->cc_tls == 1 );
-	ASSERT( Target_Queue(conn) );
-	
-	CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */);
-error:
-	CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
-	TRACE_DEBUG(FULL, "Thread terminated");	
-	return NULL;
-}
-
-/* Start receving messages in clear (no TLS) on the connection */
-int fd_cnx_start_clear(struct cnxctx * conn, int loop)
-{
-	TRACE_ENTRY("%p %i", conn, loop);
-	
-	CHECK_PARAMS( conn && Target_Queue(conn) && (!conn->cc_tls) && (!conn->cc_loop));
-	
-	/* Save the loop request */
-	conn->cc_loop = loop;
-	
-	/* Release resources in case of a previous call was already made */
-	CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */);
-	
-	switch (conn->cc_proto) {
-		case IPPROTO_TCP:
-			/* Start the tcp_notls thread */
-			CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_notls_tcp, conn ) );
-			break;
-#ifndef DISABLE_SCTP
-		case IPPROTO_SCTP:
-			/* Start the tcp_notls thread */
-			CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_notls_sctp, conn ) );
-			break;
-#endif /* DISABLE_SCTP */
-		default:
-			TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto);
-			return ENOTSUP;
-	}
-			
-	return 0;
-}
-
-/* Prepare a gnutls session object for handshake */
-int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority, void * alt_creds)
-{
-	/* Create the master session context */
-	CHECK_GNUTLS_DO( gnutls_init (session, mode), return ENOMEM );
-
-	/* Set the algorithm suite */
-	if (priority) {
-		const char * errorpos;
-		CHECK_GNUTLS_DO( gnutls_priority_set_direct( *session, priority, &errorpos ), 
-			{ TRACE_DEBUG(INFO, "Error in priority string '%s' at position: '%s'\n", priority, errorpos); return EINVAL; } );
-	} else {
-		CHECK_GNUTLS_DO( gnutls_priority_set( *session, fd_g_config->cnf_sec_data.prio_cache ), return EINVAL );
-	}
-
-	/* Set the credentials of this side of the connection */
-	CHECK_GNUTLS_DO( gnutls_credentials_set (*session, GNUTLS_CRD_CERTIFICATE, alt_creds ?: fd_g_config->cnf_sec_data.credentials), return EINVAL );
-
-	/* Request the remote credentials as well */
-	if (mode == GNUTLS_SERVER) {
-		gnutls_certificate_server_set_request (*session, GNUTLS_CERT_REQUIRE);
-	}
-	
-	return 0;
-}
-
-/* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */
-int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority, void * alt_creds)
+/* TLS handshake the connection */
+int fd_cnx_handshake(struct cnxctx * conn, int mode)
 {
 	TRACE_ENTRY( "%p %d", conn, mode);
-	CHECK_PARAMS( conn && (!conn->cc_tls) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) );
-
+	CHECK_PARAMS( conn && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) );
+	
 	/* Save the mode */
 	conn->cc_tls_para.mode = mode;
 	
-	/* Cancel receiving thread if any -- it should already be terminated anyway, we just release the resources */
-	CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */);
+	/* Create the master session context */
+	CHECK_GNUTLS_DO( gnutls_init (&conn->cc_tls_para.session, mode), return ENOMEM );
 	
-	/* Once TLS handshake is done, we don't stop after the first message */
-	conn->cc_loop = 1;
+	/* Set the algorithm suite */
+	CHECK_GNUTLS_DO( gnutls_priority_set( conn->cc_tls_para.session, fd_g_config->cnf_sec_data.prio_cache ), return EINVAL );
 	
-	/* Prepare the master session credentials and priority */
-	CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, priority, alt_creds) );
+	/* Set the credentials of this side of the connection */
+	CHECK_GNUTLS_DO( gnutls_credentials_set (conn->cc_tls_para.session, GNUTLS_CRD_CERTIFICATE, fd_g_config->cnf_sec_data.credentials), return EINVAL );
+	
+	/* Request the remote credentials as well */
+	if (mode == GNUTLS_SERVER) {
+		gnutls_certificate_server_set_request (conn->cc_tls_para.session, GNUTLS_CERT_REQUIRE);
+	}
+
+	/* Set the socket info in the session */
+	gnutls_transport_set_ptr (conn->cc_tls_para.session, (gnutls_transport_ptr_t) conn->cc_socket);
 
 	/* Special case: multi-stream TLS is not natively managed in GNU TLS, we use a wrapper library */
-	if (conn->cc_sctp_para.pairs > 1) {
-#ifdef DISABLE_SCTP
+	if ((conn->cc_proto == IPPROTO_SCTP) && (conn->cc_sctp_para.pairs > 0)) {
+#ifndef DISABLE_SCTP
+		TODO("Initialize the SCTP TLS wrapper");
+		TODO("Set the lowat, push and pull functions");
+#else /* DISABLE_SCTP */
 		ASSERT(0);
-		CHECK_FCT( ENOTSUP );
-#else /* DISABLE_SCTP */
-		/* Initialize the wrapper, start the demux thread */
-		CHECK_FCT( fd_sctps_init(conn) );
 #endif /* DISABLE_SCTP */
-	} else {
-		/* Set the socket info in the session */
-		gnutls_transport_set_ptr (conn->cc_tls_para.session, (gnutls_transport_ptr_t) conn->cc_socket);
 	}
-
+	
 	/* Handshake master session */
 	{
@@ -807,14 +108,14 @@
 			{
 				if (TRACE_BOOL(INFO)) {
-					fd_log_debug("TLS Handshake failed on socket %d (%s) : %s\n", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
+					fd_log_debug("TLS Handshake failed on socket %d : %s\n", conn->cc_socket, gnutls_strerror(ret));
 				}
 				return EINVAL;
 			} );
-
+		
 		/* Now verify the remote credentials are valid -- only simple test here */
 		CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (conn->cc_tls_para.session, &ret), return EINVAL );
 		if (ret) {
 			if (TRACE_BOOL(INFO)) {
-				fd_log_debug("TLS: Remote certificate invalid on socket %d (%s) :\n", conn->cc_socket, conn->cc_id);
+				fd_log_debug("TLS: Remote certificate invalid on socket %d :\n", conn->cc_socket);
 				if (ret & GNUTLS_CERT_INVALID)
 					fd_log_debug(" - The certificate is not trusted (unknown CA?)\n");
@@ -831,257 +132,12 @@
 		}
 	}
-
-	/* Multi-stream TLS: handshake other streams as well */
-	if (conn->cc_sctp_para.pairs > 1) {
+	
+	/* Other sessions in case of multi-stream SCTP are resumed from the master */
+	if ((conn->cc_proto == IPPROTO_SCTP) && (conn->cc_sctp_para.pairs > 0)) {
 #ifndef DISABLE_SCTP
-		/* Resume all additional sessions from the master one. */
-		CHECK_FCT(fd_sctps_handshake_others(conn, priority, alt_creds));
-		
-		/* Mark the connection as protected from here */
-		conn->cc_tls = 1;
-
-		/* Start decrypting the messages from all threads and queuing them in target queue */
-		CHECK_FCT(fd_sctps_startthreads(conn));
+		TODO("Init and resume all additional sessions from the master one.");
 #endif /* DISABLE_SCTP */
-	} else {
-		/* Mark the connection as protected from here */
-		conn->cc_tls = 1;
-
-		/* Start decrypting the data */
-		CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_tls_single, conn ) );
 	}
 	
 	return 0;
 }
-
-/* Retrieve TLS credentials of the remote peer, after handshake */
-int fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsigned int *cert_list_size)
-{
-	TRACE_ENTRY("%p %p %p", conn, cert_list, cert_list_size);
-	CHECK_PARAMS( conn && (conn->cc_tls) && cert_list && cert_list_size );
-	
-	/* This function only works for X.509 certificates. */
-	CHECK_PARAMS( gnutls_certificate_type_get (conn->cc_tls_para.session) == GNUTLS_CRT_X509 );
-	
-	*cert_list = gnutls_certificate_get_peers (conn->cc_tls_para.session, cert_list_size);
-	if (*cert_list == NULL) {
-		TRACE_DEBUG(INFO, "No certificate was provided by remote peer / an error occurred.");
-		return EINVAL;
-	}
-
-	TRACE_DEBUG( FULL, "Remote peer provided %d certificates.\n", *cert_list_size);
-	
-	return 0;
-}
-
-/* Receive next message. if timeout is not NULL, wait only until timeout. This function only pulls from a queue, mgr thread is filling that queue aynchrounously. */
-int fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned char **buf, size_t * len)
-{
-	int    ev;
-	size_t ev_sz;
-	void * ev_data;
-	
-	TRACE_ENTRY("%p %p %p %p", conn, timeout, buf, len);
-	CHECK_PARAMS(conn && (conn->cc_socket > 0) && buf && len);
-	CHECK_PARAMS(conn->cc_rcvthr != (pthread_t)NULL);
-	CHECK_PARAMS(conn->cc_alt == NULL);
-
-	/* Now, pull the first event */
-get_next:
-	if (timeout) {
-		CHECK_FCT( fd_event_timedget(conn->cc_incoming, timeout, FDEVP_PSM_TIMEOUT, &ev, &ev_sz, &ev_data) );
-	} else {
-		CHECK_FCT( fd_event_get(conn->cc_incoming, &ev, &ev_sz, &ev_data) );
-	}
-	
-	switch (ev) {
-		case FDEVP_CNX_MSG_RECV:
-			/* We got one */
-			*len = ev_sz;
-			*buf = ev_data;
-			return 0;
-			
-		case FDEVP_PSM_TIMEOUT:
-			TRACE_DEBUG(FULL, "Timeout event received");
-			return ETIMEDOUT;
-			
-		case FDEVP_CNX_EP_CHANGE:
-			/* We ignore this event */
-			goto get_next;
-			
-		case FDEVP_CNX_ERROR:
-			TRACE_DEBUG(FULL, "Received ERROR event on the connection");
-			return ENOTCONN;
-	}
-	
-	TRACE_DEBUG(INFO, "Received unexpected event %d (%s)", ev, fd_pev_str(ev));
-	return EINVAL;
-}
-
-/* Set an alternate FIFO list to send FDEVP_CNX_* events to */
-int fd_cnx_recv_setaltfifo(struct cnxctx * conn, struct fifo * alt_fifo)
-{
-	TRACE_ENTRY( "%p %p", conn, alt_fifo );
-	CHECK_PARAMS( conn && alt_fifo && conn->cc_incoming );
-	
-	/* The magic function does it all */
-	CHECK_FCT( fd_fifo_move( &conn->cc_incoming, alt_fifo, &conn->cc_alt ) );
-	
-	return 0;
-}
-
-/* Wrapper around gnutls_record_recv to handle some error codes */
-static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
-{
-	ssize_t ret;
-again:	
-	CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz),
-		{
-			switch (ret) {
-				case GNUTLS_E_REHANDSHAKE: 
-					CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
-						{
-							if (TRACE_BOOL(INFO)) {
-								fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s\n", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
-							}
-							goto end;
-						} );
-
-				case GNUTLS_E_AGAIN:
-				case GNUTLS_E_INTERRUPTED:
-					goto again;
-
-				default:
-					TRACE_DEBUG(INFO, "This TLS error is not handled, assume unrecoverable error");
-			}
-		} );
-end:	
-	return ret;
-}
-
-
-
-/* Send function when no multi-stream is involved, or sending on stream #0 (send() always use stream 0)*/
-static int send_simple(struct cnxctx * conn, unsigned char * buf, size_t len)
-{
-	ssize_t ret;
-	size_t sent = 0;
-	TRACE_ENTRY("%p %p %zd", conn, buf, len);
-	do {
-		if (conn->cc_tls) {
-			CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_tls_para.session, buf + sent, len - sent), return ENOTCONN );
-		} else {
-			CHECK_SYS( ret = send(conn->cc_socket, buf + sent, len - sent, 0) ); /* better to replace with sendmsg for atomic sending? */
-		}
-		sent += ret;
-	} while ( sent < len );
-	return 0;
-}
-
-/* Send a message -- this is synchronous -- and we assume it's never called by several threads at the same time, so we don't protect. */
-int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
-{
-	TRACE_ENTRY("%p %p %zd", conn, buf, len);
-	
-	CHECK_PARAMS(conn && (conn->cc_socket > 0) && buf && len);
-
-	TRACE_DEBUG(FULL, "Sending %zdb %sdata on connection %s", len, conn->cc_tls ? "TLS-protected ":"", conn->cc_id);
-	
-	switch (conn->cc_proto) {
-		case IPPROTO_TCP:
-			CHECK_FCT( send_simple(conn, buf, len) );
-			break;
-		
-#ifndef DISABLE_SCTP
-		case IPPROTO_SCTP: {
-			int multistr = 0;
-			
-			if ((conn->cc_sctp_para.str_out > 1) && ((! conn->cc_tls) || (conn->cc_sctp_para.pairs > 1)))  {
-				/* Update the id of the stream we will send this message on */
-				conn->cc_sctp_para.next += 1;
-				conn->cc_sctp_para.next %= (conn->cc_tls ? conn->cc_sctp_para.pairs : conn->cc_sctp_para.str_out);
-				multistr = 1;
-			}
-			
-			if ((!multistr) || (conn->cc_sctp_para.next == 0)) {
-				CHECK_FCT( send_simple(conn, buf, len) );
-			} else {
-				if (!conn->cc_tls) {
-					CHECK_FCT( fd_sctp_sendstr(conn->cc_socket, conn->cc_sctp_para.next, buf, len) );
-				} else {
-					/* push the record to the appropriate session */
-					ssize_t ret;
-					size_t sent = 0;
-					ASSERT(conn->cc_sctps_data.array != NULL);
-					do {
-						CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_sctps_data.array[conn->cc_sctp_para.next].session, buf + sent, len - sent), return ENOTCONN );
-						sent += ret;
-					} while ( sent < len );
-				}
-			}
-		}
-		break;
-#endif /* DISABLE_SCTP */
-	
-		default:
-			TRACE_DEBUG(INFO, "Unknwon protocol: %d", conn->cc_proto);
-			return ENOTSUP;	/* or EINVAL... */
-	}
-	
-	return 0;
-}
-
-
-/**************************************/
-/*     Destruction of connection      */
-/**************************************/
-
-/* Destroy a conn structure, and shutdown the socket */
-void fd_cnx_destroy(struct cnxctx * conn)
-{
-	TRACE_ENTRY("%p", conn);
-	
-	CHECK_PARAMS_DO(conn, return);
-
-	/* In case of TLS, stop receiver thread, then close properly the gnutls session */
-	if ((conn->cc_tls) && (conn->cc_sctp_para.pairs > 1)) {
-#ifndef DISABLE_SCTP
-		/* Multi-stream TLS: Stop all decipher threads, but not the demux thread */
-		fd_sctps_stopthreads(conn);
-#endif /* DISABLE_SCTP */
-	} else {
-		/* Stop the decoding thread */
-		CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
-	}
-	
-	/* Terminate properly the TLS session(s) */
-	if (conn->cc_tls) {
-		/* Master session */
-		CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR), /* Continue */ );
-		gnutls_deinit(conn->cc_tls_para.session);
-		
-#ifndef DISABLE_SCTP
-		if (conn->cc_sctp_para.pairs > 1) {
-			/* Multi-stream TLS: destroy the wrapper and stop the demux thread */
-			fd_sctps_destroy(conn);
-		}
-#endif /* DISABLE_SCTP */
-		
-	}
-	
-	/* Shut the connection down */
-	if (conn->cc_socket > 0) {
-		shutdown(conn->cc_socket, SHUT_RDWR);
-	}
-	
-	/* Empty and destroy FIFO list */
-	if (conn->cc_incoming) {
-		fd_event_destroy( &conn->cc_incoming, free );
-	}
-	
-	/* Free the object */
-	free(conn);
-	
-	/* Done! */
-	return;
-}
Index: eeDiameter/cnxctx.h
===================================================================
--- freeDiameter/cnxctx.h	(revision 29)
+++ 	(revision )
@@ -1,124 +1,0 @@
-/*********************************************************************************************************
-* Software License Agreement (BSD License)                                                               *
-* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
-*													 *
-* Copyright (c) 2009, WIDE Project and NICT								 *
-* All rights reserved.											 *
-* 													 *
-* Redistribution and use of this software in source and binary forms, with or without modification, are  *
-* permitted provided that the following conditions are met:						 *
-* 													 *
-* * Redistributions of source code must retain the above 						 *
-*   copyright notice, this list of conditions and the 							 *
-*   following disclaimer.										 *
-*    													 *
-* * Redistributions in binary form must reproduce the above 						 *
-*   copyright notice, this list of conditions and the 							 *
-*   following disclaimer in the documentation and/or other						 *
-*   materials provided with the distribution.								 *
-* 													 *
-* * Neither the name of the WIDE Project or NICT nor the 						 *
-*   names of its contributors may be used to endorse or 						 *
-*   promote products derived from this software without 						 *
-*   specific prior written permission of WIDE Project and 						 *
-*   NICT.												 *
-* 													 *
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
-* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
-* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
-* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
-* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
-*********************************************************************************************************/
-
-/* This file contains the definitions for internal use in the connection context files */
-
-#ifndef _CNXCTX_H
-#define _CNXCTX_H
-
-/* The connection context structure */
-struct cnxctx {
-	char		cc_id[60];	/* The name of this connection */
-	char		cc_remid[60];	/* Id of remote peer */
-
-	int 		cc_socket;	/* The socket object of the connection -- <=0 if no socket is created */
-
-	int 		cc_proto;	/* IPPROTO_TCP or IPPROTO_SCTP */
-	int		cc_tls;		/* Is TLS already started ? */
-
-	pthread_t	cc_rcvthr;	/* thread for receiving messages on the connection */
-	int		cc_loop;	/* tell the thread if it loops or stops after the first message is received */
-	
-	struct fifo *	cc_incoming;	/* FIFO queue of events received on the connection, FDEVP_CNX_* */
-	struct fifo *	cc_alt;		/* alternate fifo to send FDEVP_CNX_* events to. */
-	#define Target_Queue(cnx)	((cnx)->cc_alt ?: (cnx)->cc_incoming)
-
-	/* If cc_tls == true */
-	struct {
-		int				 mode; 		/* GNUTLS_CLIENT / GNUTLS_SERVER */
-		gnutls_session_t 		 session;	/* Session object (stream #0 in case of SCTP) */
-	}		cc_tls_para;
-
-	/* If cc_proto == SCTP */
-	struct	{
-		uint16_t str_out;	/* Out streams */
-		uint16_t str_in;	/* In streams */
-		uint16_t pairs;		/* max number of pairs ( = min(in, out)) */
-		uint16_t next;		/* # of stream the next message will be sent to */
-	} 		cc_sctp_para;
-
-	/* If both conditions */
-	struct {
-		struct sctps_ctx *array; /* an array of cc_sctp_para.pairs elements -- the #0 is special (session is outside)*/
-		struct sr_store	 *sess_store; /* Session data of the master session, to resume the children sessions */
-	} 		cc_sctps_data;
-};
-
-/* TLS */
-int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session);
-int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority, void * alt_creds);
-
-/* TCP */
-int fd_tcp_create_bind_server( int * sock, sSA * sa, socklen_t salen );
-int fd_tcp_listen( int sock );
-int fd_tcp_client( int *sock, sSA * sa, socklen_t salen );
-int fd_tcp_get_local_ep(int sock, sSS * ss, socklen_t *sl);
-int fd_tcp_get_remote_ep(int sock, sSS * ss, socklen_t *sl);
-
-#ifndef DISABLE_SCTP
-/* SCTP */
-int fd_sctp_create_bind_server( int * sock, struct fd_list * list, uint16_t port );
-int fd_sctp_listen( int sock );
-int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list );
-int fd_sctp_get_local_ep(int sock, struct fd_list * list);
-int fd_sctp_get_remote_ep(int sock, struct fd_list * list);
-int fd_sctp_get_str_info( int sock, uint16_t *in, uint16_t *out, sSS *primary );
-int fd_sctp_sendstr(int sock, uint16_t strid, uint8_t * buf, size_t len);
-int fd_sctp_recvmeta(int sock, uint16_t * strid, uint8_t ** buf, size_t * len, int *event);
-
-/* TLS over SCTP (multi-stream) */
-struct sctps_ctx {
-	struct cnxctx 	*parent; 	/* for info such as socket, conn name, event list */
-	uint16_t	 strid;		/* Stream # of this session */
-	struct fifo	*raw_recv;	/* Raw data received on this stream, for demux */
-	struct {
-		uint8_t *buf;
-		size_t   bufsz;
-		size_t   offset;
-	} 		 partial;	/* If the pull function did not read the full content of first message in raw, it stores it here for next read call. */
-	pthread_t	 thr;		/* Thread to decrypt raw data in this pair of streams */
-	gnutls_session_t session;	/* TLS context using this pair of streams -- except if strid == 0, in that case session is outside the array */
-};
-
-int fd_sctps_init(struct cnxctx * conn);
-int fd_sctps_handshake_others(struct cnxctx * conn, char * priority, void * alt_creds);
-int fd_sctps_startthreads(struct cnxctx * conn);
-void fd_sctps_stopthreads(struct cnxctx * conn);
-void fd_sctps_destroy(struct cnxctx * conn);
-
-#endif /* DISABLE_SCTP */
-
-#endif /* _CNXCTX_H */
-
Index: freeDiameter/config.c
===================================================================
--- freeDiameter/config.c	(revision 24)
+++ freeDiameter/config.c	(revision 20)
@@ -100,5 +100,5 @@
 			struct fd_endpoint * ep = (struct fd_endpoint *)li;
 			if (li != fd_g_config->cnf_endpoints.next) fd_log_debug("                             ");
-			sSA_DUMP_NODE( &ep->sa, NI_NUMERICHOST );
+			sSA_DUMP_NODE( &ep->ss, NI_NUMERICHOST );
 			fd_log_debug("\n");
 			li = li->next;
@@ -229,23 +229,4 @@
 	}
 	
-	/* Validate local endpoints */
-	if ((!FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) && (fd_g_config->cnf_flags.no_ip4 || fd_g_config->cnf_flags.no_ip6)) {
-		struct fd_list * li;
-		for ( li = fd_g_config->cnf_endpoints.next; li != &fd_g_config->cnf_endpoints; li = li->next) {
-			struct fd_endpoint * ep = (struct fd_endpoint *)li;
-			if ( (fd_g_config->cnf_flags.no_ip4 && (ep->sa.sa_family == AF_INET))
-			   ||(fd_g_config->cnf_flags.no_ip6 && (ep->sa.sa_family == AF_INET6)) ) {
-				li = li->prev;
-				fd_list_unlink(&ep->chain);
-				if (TRACE_BOOL(INFO)) {
-					fd_log_debug("Info: Removing local address conflicting with the flags no_IP / no_IP6 : ");
-					sSA_DUMP_NODE( &ep->sa, AI_NUMERICHOST );
-					fd_log_debug("\n");
-				}
-				free(ep);
-			}
-		}
-	}
-	
 	/* Configure TLS default parameters */
 	if (! fd_g_config->cnf_sec_data.prio_string) {
@@ -258,15 +239,12 @@
 	}
 	if (! fd_g_config->cnf_sec_data.dh_bits) {
-		if (TRACE_BOOL(INFO)) {
-			fd_log_debug("Generating Diffie-Hellman parameters of size %d (this takes a few seconds)... ", GNUTLS_DEFAULT_DHBITS);
-		}
+		TRACE_DEBUG(FULL, "Generating DH parameters...");
 		CHECK_GNUTLS_DO( gnutls_dh_params_generate2( 
 					fd_g_config->cnf_sec_data.dh_cache,
 					GNUTLS_DEFAULT_DHBITS),
 				 { TRACE_DEBUG(INFO, "Error in DH bits value : %d", GNUTLS_DEFAULT_DHBITS); return EINVAL; } );
-		if (TRACE_BOOL(INFO)) {
-			fd_log_debug("Done!\n");
-		}
-	}
+		TRACE_DEBUG(FULL, "DH parameters generated.");
+	}
+	
 	
 	return 0;
Index: eeDiameter/endpoints.c
===================================================================
--- freeDiameter/endpoints.c	(revision 24)
+++ 	(revision )
@@ -1,110 +1,0 @@
-/*********************************************************************************************************
-* Software License Agreement (BSD License)                                                               *
-* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
-*													 *
-* Copyright (c) 2009, WIDE Project and NICT								 *
-* All rights reserved.											 *
-* 													 *
-* Redistribution and use of this software in source and binary forms, with or without modification, are  *
-* permitted provided that the following conditions are met:						 *
-* 													 *
-* * Redistributions of source code must retain the above 						 *
-*   copyright notice, this list of conditions and the 							 *
-*   following disclaimer.										 *
-*    													 *
-* * Redistributions in binary form must reproduce the above 						 *
-*   copyright notice, this list of conditions and the 							 *
-*   following disclaimer in the documentation and/or other						 *
-*   materials provided with the distribution.								 *
-* 													 *
-* * Neither the name of the WIDE Project or NICT nor the 						 *
-*   names of its contributors may be used to endorse or 						 *
-*   promote products derived from this software without 						 *
-*   specific prior written permission of WIDE Project and 						 *
-*   NICT.												 *
-* 													 *
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
-* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
-* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
-* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
-* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
-*********************************************************************************************************/
-
-#include "fD.h"
-
-
-/* Add an endpoint information in a list */
-int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t flags )
-{
-	struct fd_endpoint * ep;
-	struct fd_list * li;
-	int cmp = -1;
-	
-	TRACE_ENTRY("%p %p %u %x", list, sa, sl, flags);
-	CHECK_PARAMS( list && sa && (sl <= sizeof(sSS)) );
-	
-	/* Search place in the list */
-	for (li = list->next; li != list; li = li->next) {
-		ep = (struct fd_endpoint *)li;
-		
-		cmp = memcmp(&ep->ss, sa, sl);
-		if (cmp >= 0)
-			break;
-	}
-	
-	if (cmp) {
-		/* new item to be added */
-		CHECK_MALLOC( ep = malloc(sizeof(struct fd_endpoint)) );
-		memset(ep, 0, sizeof(struct fd_endpoint));
-		fd_list_init(&ep->chain, NULL);
-		memcpy(&ep->ss, sa, sl);
-		
-		/* Insert in the list */
-		fd_list_insert_before(li, &ep->chain);
-	}
-	
-	/* Merge the flags */
-	ep->flags |= flags;
-	
-	return 0;
-}
-
-/* Delete endpoints that do not have a matching flag from a list (0: delete all endpoints) */
-int fd_ep_filter( struct fd_list * list, uint32_t flags )
-{
-	struct fd_list * li;
-	
-	TRACE_ENTRY("%p %x", list, flags);
-	CHECK_PARAMS(list);
-	
-	for (li = list->next; li != list; li = li->next) {
-		struct fd_endpoint * ep = (struct fd_endpoint *)li;
-		
-		if (! (ep->flags & flags)) {
-			li = li->prev;
-			fd_list_unlink(&ep->chain);
-			free(ep);
-		}
-	}
-	
-	return 0;
-}
-
-/* Reset the given flag(s) from all items in the list */
-int fd_ep_clearflags( struct fd_list * list, uint32_t flags )
-{
-	struct fd_list * li;
-	
-	TRACE_ENTRY("%p %x", list, flags);
-	CHECK_PARAMS(list);
-	
-	for (li = list->next; li != list; li = li->next) {
-		struct fd_endpoint * ep = (struct fd_endpoint *)li;
-		ep->flags &= ~flags;
-	}
-	
-	return 0;
-}
Index: freeDiameter/fD.h
===================================================================
--- freeDiameter/fD.h	(revision 29)
+++ freeDiameter/fD.h	(revision 20)
@@ -152,35 +152,18 @@
 enum {
 	/* Dump all info about this peer in the debug log */
-	 FDEVP_DUMP_ALL = 1500
+	 FDEVP_DUMP_ALL = 2000
 	
 	/* request to terminate this peer : disconnect, requeue all messages */
 	,FDEVP_TERMINATE
 	
-	/* A connection object has received a message. (data contains the buffer) */
-	,FDEVP_CNX_MSG_RECV
-			 
-	/* A connection object has encountered an error (disconnected). */
-	,FDEVP_CNX_ERROR
-	
-	/* Endpoints of a connection have been changed (multihomed SCTP). */
-	,FDEVP_CNX_EP_CHANGE
-	
-	/* A new connection has been established (data contains the appropriate info) */
-	,FDEVP_CNX_INCOMING
+	/* A message was received in the peer */
+	,FDEVP_MSG_INCOMING
 	
 	/* The PSM state is expired */
 	,FDEVP_PSM_TIMEOUT
-	
 };
 const char * fd_pev_str(int event);
 #define CHECK_EVENT( _e ) \
 	(((int)(_e) >= FDEVP_DUMP_ALL) && ((int)(_e) <= FDEVP_PSM_TIMEOUT))
-
-/* The data structure for FDEVP_CNX_INCOMING events */
-struct cnx_incoming {
-	struct msg	* cer;		/* the CER message received on this connection */
-	struct cnxctx	* cnx;		/* The connection context */
-	int  		  validate;	/* The peer is new, it must be validated (by an extension) or error CEA to be sent */
-};
 
 /* Structure to store a sent request */
@@ -190,14 +173,45 @@
 };
 
+/* The connection context structure */
+struct cnxctx {
+	int 		cc_socket;	/* The socket object of the connection -- <=0 if no socket is created */
+	
+	struct fifo   **cc_events;	/* Location of the events list to send connection events */
+	
+	int 		cc_proto;	/* IPPROTO_TCP or IPPROTO_SCTP */
+	int		cc_tls;		/* Is TLS already started ? */
+	
+	uint16_t	cc_port;	/* Remote port of the connection, when we are client */
+	struct fd_list	cc_ep_remote;	/* The remote address(es) of the connection */
+	struct fd_list	cc_ep_local;	/* The local address(es) of the connection */
+	
+	/* If cc_proto == SCTP */
+	struct	{
+		int		str_out;/* Out streams */
+		int		str_in;	/* In streams */
+		int		pairs;	/* max number of pairs ( = min(in, out)) */
+		int		next;	/* # of stream the next message will be sent to */
+	} 		cc_sctp_para;
+	
+	/* If cc_tls == true */
+	struct {
+		int				 mode; 		/* GNUTLS_CLIENT / GNUTLS_SERVER */
+		gnutls_session_t 		 session;	/* Session object (stream #0 in case of SCTP) */
+	}		cc_tls_para;
+	
+	/* If both conditions */
+	struct {
+		gnutls_session_t 		*res_sessions;	/* Sessions of other pairs of streams, resumed from the first */
+		/* Buffers, threads, ... */
+	}		cc_sctp_tls_para;
+};
 
 /* Functions */
-int  fd_peer_fini();
+int fd_peer_fini();
 void fd_peer_dump_list(int details);
 void fd_peer_dump(struct fd_peer * peer, int details);
-int  fd_peer_alloc(struct fd_peer ** ptr);
-int  fd_peer_free(struct fd_peer ** ptr);
-int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx );
+int fd_peer_alloc(struct fd_peer ** ptr);
+int fd_peer_free(struct fd_peer ** ptr);
 /* fd_peer_add declared in freeDiameter.h */
-int fd_peer_validate( struct fd_peer * peer );
 
 /* Peer expiry */
@@ -207,33 +221,25 @@
 
 /* Peer state machine */
-int  fd_psm_start();
-int  fd_psm_begin(struct fd_peer * peer );
-int  fd_psm_terminate(struct fd_peer * peer );
+int fd_psm_start();
+int fd_psm_begin(struct fd_peer * peer );
+int fd_psm_terminate(struct fd_peer * peer );
 void fd_psm_abord(struct fd_peer * peer );
 
 /* Server sockets */
 void fd_servers_dump();
-int  fd_servers_start();
-int  fd_servers_stop();
-
-/* Connection contexts -- there are also definitions in cnxctx.h for the relevant files */
-struct cnxctx * fd_cnx_serv_tcp(uint16_t port, int family, struct fd_endpoint * ep);
-struct cnxctx * fd_cnx_serv_sctp(uint16_t port, struct fd_list * ep_list);
-int             fd_cnx_serv_listen(struct cnxctx * conn);
-struct cnxctx * fd_cnx_serv_accept(struct cnxctx * serv);
-struct cnxctx * fd_cnx_cli_connect_tcp(sSA * sa, socklen_t addrlen);
-struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_list * list);
-int             fd_cnx_start_clear(struct cnxctx * conn, int loop);
-int             fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority, void * alt_creds);
-char *          fd_cnx_getid(struct cnxctx * conn);
-int		fd_cnx_getproto(struct cnxctx * conn);
-int		fd_cnx_getTLS(struct cnxctx * conn);
-int             fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsigned int *cert_list_size);
-int             fd_cnx_getendpoints(struct cnxctx * conn, struct fd_list * local, struct fd_list * remote);
-char *          fd_cnx_getremoteid(struct cnxctx * conn);
-int             fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned char **buf, size_t * len);
-int             fd_cnx_recv_setaltfifo(struct cnxctx * conn, struct fifo * alt_fifo); /* send FDEVP_CNX_MSG_RECV event to the fifo list */
-int             fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len);
-void            fd_cnx_destroy(struct cnxctx * conn);
+int fd_servers_start();
+void fd_servers_stop();
+
+/* Connection contexts */
+struct cnxctx * fd_cnx_init(int sock, int proto);
+int fd_cnx_handshake(struct cnxctx * conn, int mode);
+
+/* SCTP */
+#ifndef DISABLE_SCTP
+int fd_sctp_create_bind_server( int * socket, uint16_t port );
+int fd_sctp_get_str_info( int socket, int *in, int *out );
+
+#endif /* DISABLE_SCTP */
+
 
 
Index: freeDiameter/fdd.y
===================================================================
--- freeDiameter/fdd.y	(revision 24)
+++ freeDiameter/fdd.y	(revision 20)
@@ -212,14 +212,23 @@
 listenon:		LISTENON '=' QSTRING ';'
 			{
+				struct fd_endpoint * ep;
 				struct addrinfo hints, *ai;
 				int ret;
+				
+				CHECK_MALLOC_DO( ep = malloc(sizeof(struct fd_endpoint)),
+					{ yyerror (&yylloc, conf, "Out of memory"); YYERROR; } );
+				memset(ep, 0, sizeof(struct fd_endpoint));
+				fd_list_init(&ep->chain, NULL);
+				ep->meta.conf = 1;
 				
 				memset(&hints, 0, sizeof(hints));
 				hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
 				ret = getaddrinfo($3, NULL, &hints, &ai);
-				if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; }
-				CHECK_FCT_DO( fd_ep_add_merge( &conf->cnf_endpoints, ai->ai_addr, ai->ai_addrlen, EP_FL_CONF ), YYERROR );
+				if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); free(ep); YYERROR; }
+				ASSERT( ai->ai_addrlen <= sizeof(sSS) );
+				memcpy(&ep->ss, ai->ai_addr, ai->ai_addrlen);
+				free($3);
 				freeaddrinfo(ai);
-				free($3);
+				fd_list_insert_before(&conf->cnf_endpoints, &ep->chain);
 			}
 			;
@@ -327,5 +336,4 @@
 				/* Now destroy any content in the structure */
 				free(fddpi.pi_diamid);
-				free(fddpi.pi_sec_data.priority);
 				while (!FD_IS_LIST_EMPTY(&fddpi.pi_endpoints)) {
 					struct fd_list * li = fddpi.pi_endpoints.next;
@@ -407,12 +415,14 @@
 				fddpi.pi_port = (uint16_t)$4;
 			}
+			| peerparams SCTPSTREAMS '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($4 > 0) && ($4 < 1<<16),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				fddpi.pi_streams = (uint16_t)$4;
+			}
 			| peerparams TCTIMER '=' INTEGER ';'
 			{
 				fddpi.pi_tctimer = $4;
 			}
-			| peerparams TLS_PRIO '=' QSTRING ';'
-			{
-				fddpi.pi_sec_data.priority = $4;
-			}
 			| peerparams TWTIMER '=' INTEGER ';'
 			{
@@ -421,8 +431,13 @@
 			| peerparams CONNTO '=' QSTRING ';'
 			{
+				struct fd_endpoint * ep;
 				struct addrinfo hints, *ai;
 				int ret;
-				int disc = 0;
 				
+				CHECK_MALLOC_DO( ep = malloc(sizeof(struct fd_endpoint)),
+					{ yyerror (&yylloc, conf, "Out of memory"); YYERROR; } );
+				memset(ep, 0, sizeof(struct fd_endpoint));
+				fd_list_init(&ep->chain, NULL);
+				ep->meta.conf = 1;
 				memset(&hints, 0, sizeof(hints));
 				hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST;
@@ -430,13 +445,14 @@
 				if (ret == EAI_NONAME) {
 					/* The name was maybe not numeric, try again */
-					disc = EP_FL_DISC;
+					ep->meta.disc = 1;
 					hints.ai_flags &= ~ AI_NUMERICHOST;
 					ret = getaddrinfo($4, NULL, &hints, &ai);
 				}
-				if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; }
+				if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); free(ep); YYERROR; }
 				
-				CHECK_FCT_DO( fd_ep_add_merge( &fddpi.pi_endpoints, ai->ai_addr, ai->ai_addrlen, EP_FL_CONF | disc ), YYERROR );
+				memcpy(&ep->ss, ai->ai_addr, ai->ai_addrlen);
 				free($4);
 				freeaddrinfo(ai);
+				fd_list_insert_before(&fddpi.pi_endpoints, &ep->chain);
 			}
 			;
Index: freeDiameter/main.c
===================================================================
--- freeDiameter/main.c	(revision 25)
+++ freeDiameter/main.c	(revision 20)
@@ -51,5 +51,4 @@
 struct fd_config * fd_g_config = &conf;
 
-/* gcrypt functions to support posix threads */
 GCRY_THREAD_OPTION_PTHREAD_IMPL;
 
@@ -106,9 +105,4 @@
 	CHECK_FCT(  fd_ext_load()  );
 	
-	fd_conf_dump();
-	
-	/* Start the servers */
-	CHECK_FCT( fd_servers_start() );
-	
 	/* Start the peer state machines */
 	CHECK_FCT( fd_psm_start() );
@@ -116,7 +110,8 @@
 	/* Now, just wait for events */
 	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized.");
+	fd_conf_dump();
 	while (1) {
-		int code; size_t sz; void * data;
-		CHECK_FCT_DO(  fd_event_get(fd_g_config->cnf_main_ev, &code, &sz, &data),  break  );
+		int code;
+		CHECK_FCT_DO(  fd_event_get(fd_g_config->cnf_main_ev, &code, NULL),  break  );
 		switch (code) {
 			case FDEV_DUMP_DICT:
@@ -159,5 +154,4 @@
 	
 	/* cleanups */
-	CHECK_FCT_DO( fd_servers_stop(), /* Stop accepting new connections */ );
 	TODO("Stop dispatch thread(s) properly (no cancel yet)");
 	CHECK_FCT_DO( fd_peer_fini(), /* Stop all connections */ );
@@ -339,5 +333,5 @@
 	
 	TRACE_DEBUG(INFO, "Received signal %s (%d), exiting", SIGNALSTR(sig), sig);
-	CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), exit(2) );
+	CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), exit(2) );
 	return NULL;
 }
Index: freeDiameter/p_expiry.c
===================================================================
--- freeDiameter/p_expiry.c	(revision 25)
+++ freeDiameter/p_expiry.c	(revision 16)
@@ -47,11 +47,12 @@
 static void * gc_th_fct(void * arg)
 {
-	fd_log_threadname ( "Peers/garb. col." );
-	TRACE_ENTRY( "%p", arg );
+	fd_log_threadname ( "Peers/garbage" );
+	TRACE_ENTRY( "" );
 	
 	do {
 		struct fd_list * li, purge = FD_LIST_INITIALIZER(purge);
 		
-		sleep(GC_TIME);	/* sleep is a cancellation point */
+		pthread_testcancel();
+		sleep(GC_TIME);
 		
 		/* Now check in the peers list if any peer can be deleted */
@@ -87,5 +88,5 @@
 	TRACE_DEBUG(INFO, "An error occurred in peers module! GC thread is terminating...");
 	ASSERT(0);
-	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
+	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), );
 	return NULL;
 }
@@ -95,5 +96,5 @@
 {
 	fd_log_threadname ( "Peers/expire" );
-	TRACE_ENTRY( "%p", arg );
+	TRACE_ENTRY( "" );
 	
 	CHECK_POSIX_DO( pthread_mutex_lock(&exp_mtx),  goto error );
@@ -123,5 +124,5 @@
 			
 			CHECK_POSIX_DO2(  pthread_cond_timedwait( &exp_cnd, &exp_mtx, &first->p_exp_timer ),  
-					ETIMEDOUT, /* ETIMEDOUT is a normal return value, continue */,
+					ETIMEDOUT, /* ETIMEDOUT is a normal error, continue */,
 					/* on other error, */ goto error );
 	
@@ -132,5 +133,5 @@
 		/* Now, the first peer in the list is expired; signal it */
 		fd_list_unlink( &first->p_expiry );
-		CHECK_FCT_DO( fd_event_send(first->p_events, FDEVP_TERMINATE, 0, NULL), goto error );
+		CHECK_FCT_DO( fd_event_send(first->p_events, FDEVP_TERMINATE, NULL), goto error );
 		
 	} while (1);
@@ -140,5 +141,5 @@
 	TRACE_DEBUG(INFO, "An error occurred in peers module! Expiry thread is terminating...");
 	ASSERT(0);
-	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
+	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), );
 	return NULL;
 }
Index: freeDiameter/p_psm.c
===================================================================
--- freeDiameter/p_psm.c	(revision 29)
+++ freeDiameter/p_psm.c	(revision 20)
@@ -55,10 +55,7 @@
 	#define case_str( _val )\
 		case _val : return #_val
+		case_str(FDEVP_TERMINATE);
 		case_str(FDEVP_DUMP_ALL);
-		case_str(FDEVP_TERMINATE);
-		case_str(FDEVP_CNX_MSG_RECV);
-		case_str(FDEVP_CNX_ERROR);
-		case_str(FDEVP_CNX_EP_CHANGE);
-		case_str(FDEVP_CNX_INCOMING);
+		case_str(FDEVP_MSG_INCOMING);
 		case_str(FDEVP_PSM_TIMEOUT);
 		
@@ -128,4 +125,26 @@
 }
 
+/* Wait for the next event in the PSM, or timeout */
+static int psm_ev_timedget(struct fd_peer * peer, int *code, void ** data)
+{
+	struct fd_event * ev;
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %p %p", peer, code, data);
+	
+	ret = fd_fifo_timedget(peer->p_events, &ev, &peer->p_psm_timer);
+	if (ret == ETIMEDOUT) {
+		*code = FDEVP_PSM_TIMEOUT;
+		*data = NULL;
+	} else {
+		CHECK_FCT( ret );
+		*code = ev->code;
+		*data = ev->data;
+		free(ev);
+	}
+	
+	return 0;
+}
+
 /* The state machine thread (controler) */
 static void * p_psm_th( void * arg )
@@ -134,5 +153,4 @@
 	int created_started = started;
 	int event;
-	size_t ev_sz;
 	void * ev_data;
 	
@@ -163,8 +181,8 @@
 psm_loop:
 	/* Get next event */
-	CHECK_FCT_DO( fd_event_timedget(peer->p_events, &peer->p_psm_timer, FDEVP_PSM_TIMEOUT, &event, &ev_sz, &ev_data), goto psm_end );
-	TRACE_DEBUG(FULL, "'%s'\t<-- '%s'\t(%p,%zd)\t'%s'",
+	CHECK_FCT_DO( psm_ev_timedget(peer, &event, &ev_data), goto psm_end );
+	TRACE_DEBUG(FULL, "'%s'\t<-- '%s'\t(%p)\t'%s'",
 			STATE_STR(peer->p_hdr.info.pi_state),
-			fd_pev_str(event), ev_data, ev_sz,
+			fd_pev_str(event), ev_data,
 			peer->p_hdr.info.pi_diamid);
 
@@ -209,30 +227,4 @@
 	}
 	
-	/* A new connection was established and CER containing this peer id was received */
-	if (event == FDEVP_CNX_INCOMING) {
-		struct cnx_incoming * params = ev_data;
-		ASSERT(params);
-		
-		switch (peer->p_hdr.info.pi_state) {
-			case STATE_CLOSED:
-				TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake, move to OPEN or REOPEN state");
-				break;
-				
-			case STATE_WAITCNXACK:
-			case STATE_WAITCEA:
-				TODO("Election");
-				break;
-				
-			default:
-				TODO("Reply with error CEA");
-				TODO("Close the connection");
-				/* reject_incoming_connection */
-			
-		}
-		
-		free(ev_data);
-		goto psm_loop;
-	}
-	
 	/* MSG_RECEIVED: fd_p_expi_update(struct fd_peer * peer ) */
 	/* If timeout or OPEN : call cb if defined */
@@ -249,8 +241,9 @@
 psm_end:
 	pthread_cleanup_pop(1); /* set STATE_ZOMBIE */
-	peer->p_psm = (pthread_t)NULL;
-	pthread_detach(pthread_self());
 	return NULL;
 }	
+	
+	
+
 
 /* Create the PSM thread of one peer structure */
@@ -274,7 +267,6 @@
 	TRACE_ENTRY("%p", peer);
 	CHECK_PARAMS( CHECK_PEER(peer) );
-	
 	if (peer->p_hdr.info.pi_state != STATE_ZOMBIE) {
-		CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, NULL) );
+		CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, NULL) );
 	} else {
 		TRACE_DEBUG(FULL, "Peer '%s' was already terminated", peer->p_hdr.info.pi_diamid);
Index: freeDiameter/peers.c
===================================================================
--- freeDiameter/peers.c	(revision 29)
+++ freeDiameter/peers.c	(revision 20)
@@ -101,11 +101,8 @@
 	
 	p->p_hdr.info.pi_lft     = info->pi_lft;
+	p->p_hdr.info.pi_streams = info->pi_streams;
 	p->p_hdr.info.pi_port    = info->pi_port;
 	p->p_hdr.info.pi_tctimer = info->pi_tctimer;
 	p->p_hdr.info.pi_twtimer = info->pi_twtimer;
-	
-	if (info->pi_sec_data.priority) {
-		CHECK_MALLOC( p->p_hdr.info.pi_sec_data.priority = strdup(info->pi_sec_data.priority) );
-	}
 	
 	/* Move the items from one list to the other */
@@ -117,5 +114,4 @@
 		}
 	
-	
 	/* The internal data */
 	if (orig_dbg) {
@@ -131,7 +127,7 @@
 	
 	for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
-		struct fd_peer * next = (struct fd_peer *)li;
-		int cmp = strcasecmp( p->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamid );
-		if (cmp > 0)
+		struct fd_peer * prev = (struct fd_peer *)li;
+		int cmp = strcasecmp( p->p_hdr.info.pi_diamid, prev->p_hdr.info.pi_diamid );
+		if (cmp < 0)
 			continue;
 		if (cmp == 0)
@@ -233,5 +229,5 @@
 	
 	if (p->p_cnxctx) {
-		fd_cnx_destroy(p->p_cnxctx);
+		TODO("destroy p->p_cnxctx");
 	}
 	
@@ -297,5 +293,4 @@
 		list_empty = FD_IS_LIST_EMPTY(&fd_g_peers);
 		CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
-		CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &now)  );
 	}
 	
@@ -375,100 +370,2 @@
 }
 
-/* Handle an incoming CER request on a new connection */
-int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx )
-{
-	struct msg * msg;
-	struct dict_object *avp_oh_model;
-	avp_code_t code = AC_ORIGIN_HOST;
-	struct avp *avp_oh;
-	struct avp_hdr * avp_hdr;
-	struct fd_list * li;
-	int found = 0;
-	int ret = 0;
-	struct fd_peer * peer;
-	struct cnx_incoming * ev_data;
-	
-	TRACE_ENTRY("%p %p", cer, cnx);
-	CHECK_PARAMS(cer && *cer && cnx && *cnx);
-	
-	msg = *cer; 
-	
-	/* Find the Diameter Identity of the remote peer in the message */
-	CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE, &code, &avp_oh_model, ENOENT) );
-	CHECK_FCT( fd_msg_search_avp ( msg, avp_oh_model, &avp_oh ) );
-	CHECK_FCT( fd_msg_avp_hdr ( avp_oh, &avp_hdr ) );
-	
-	/* Search if we already have this peer id in our list */
-	CHECK_POSIX( pthread_rwlock_rdlock(&fd_g_peers_rw) );
-	
-	for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
-		peer = (struct fd_peer *)li;
-		int cmp = strncasecmp( avp_hdr->avp_value->os.data, peer->p_hdr.info.pi_diamid, avp_hdr->avp_value->os.len );
-		if (cmp > 0)
-			continue;
-		if (cmp == 0)
-			found = 1;
-		break;
-	}
-	
-	if (!found) {
-		/* Create a new peer entry for this new remote peer */
-		peer = NULL;
-		CHECK_FCT_DO( ret = fd_peer_alloc(&peer), goto out );
-		
-		/* Set the peer Diameter Id and the responder flag parameters */
-		CHECK_MALLOC_DO( peer->p_hdr.info.pi_diamid = malloc(avp_hdr->avp_value->os.len + 1), { ret = ENOMEM; goto out; } );
-		CHECK_MALLOC_DO( peer->p_dbgorig = strdup(fd_cnx_getid(*cnx)), { ret = ENOMEM; goto out; } );
-		peer->p_flags.pf_responder = 1;
-		
-		/* Upgrade the lock to write lock */
-		CHECK_POSIX_DO( ret = pthread_rwlock_wrlock(&fd_g_peers_rw), goto out );
-		
-		/* Insert the new peer in the list (the PSM will take care of setting the expiry after validation) */
-		fd_list_insert_before( li, &peer->p_hdr.chain );
-		
-		/* Release the write lock */
-		CHECK_POSIX_DO( ret = pthread_rwlock_unlock(&fd_g_peers_rw), goto out );
-		
-		/* Start the PSM, which will receive the event bellow */
-		CHECK_FCT_DO( ret = fd_psm_begin(peer), goto out );
-	}
-		
-	/* Send the new connection event to the PSM */
-	CHECK_MALLOC_DO( ev_data = malloc(sizeof(struct cnx_incoming)), { ret = ENOMEM; goto out; } );
-	memset(ev_data, 0, sizeof(ev_data));
-	
-	ev_data->cer = msg;
-	ev_data->cnx = *cnx;
-	ev_data->validate = !found;
-	
-	CHECK_FCT_DO( ret = fd_event_send(peer->p_events, FDEVP_CNX_INCOMING, sizeof(ev_data), ev_data), goto out );
-	
-out:	
-	CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
-
-	if (ret == 0) {
-		/* Reset the "out" parameters, so that they are not cleanup on function return. */
-		*cer = NULL;
-		*cnx = NULL;
-	}
-	
-	return ret;
-}
-
-/* Save a callback to accept / reject incoming unknown peers */
-int fd_peer_validate_register ( int (*peer_validate)(struct peer_info * /* info */, int * /* auth */, int (**cb2)(struct peer_info *)) )
-{
-	
-	TODO("...");
-	return ENOTSUP;
-}
-
-/* Validate a peer by calling the callbacks in turn -- return 0 if the peer is validated, ! 0 in case of error or if the peer is rejected */
-int fd_peer_validate( struct fd_peer * peer )
-{
-	TODO("Default to reject");
-	TODO("Call all callbacks in turn");
-	TODO("Save cb2 in the peer if needed");
-	return ENOTSUP;
-}
Index: freeDiameter/sctp.c
===================================================================
--- freeDiameter/sctp.c	(revision 29)
+++ freeDiameter/sctp.c	(revision 20)
@@ -35,1062 +35,16 @@
 
 #include "fD.h"
-#include "cnxctx.h"
 
-#include <netinet/sctp.h>
-#include <sys/uio.h>
-
-/* Size of buffer to receive ancilliary data. May need to be enlarged if more sockopt are set... */
-#ifndef CMSG_BUF_LEN
-#define CMSG_BUF_LEN	1024
-#endif /* CMSG_BUF_LEN */
-
-/* Level of SCTP-specific traces */
-#ifdef DEBUG_SCTP
-#define SCTP_LEVEL	FULL
-#else /* DEBUG_SCTP */
-#define SCTP_LEVEL	ANNOYING
-#endif /* DEBUG_SCTP */
-
-/* Pre-binding socket options -- # streams read in config */
-static int fd_setsockopt_prebind(int sk)
+int fd_sctp_create_bind_server( int * socket, uint16_t port )
 {
-	socklen_t sz;
+	TODO("Create sctp server, using fd_g_config: cnf_endpoints, no_ip4, no_ip6, cnf_sctp_str");
 	
-	TRACE_ENTRY( "%d", sk);
-	
-	CHECK_PARAMS( sk > 0 );
-	
-	/* Subscribe to some notifications */
-	{
-		struct sctp_event_subscribe event;
-
-		memset(&event, 0, sizeof(event));
-		event.sctp_data_io_event	= 1;	/* to receive the stream ID in SCTP_SNDRCV ancilliary data on message reception */
-		event.sctp_association_event	= 0;	/* new or closed associations (mostly for one-to-many style sockets) */
-		event.sctp_address_event	= 1;	/* address changes */
-		event.sctp_send_failure_event	= 1;	/* delivery failures */
-		event.sctp_peer_error_event	= 1;	/* remote peer sends an error */
-		event.sctp_shutdown_event	= 1;	/* peer has sent a SHUTDOWN */
-		event.sctp_partial_delivery_event = 1;	/* a partial delivery is aborted, probably indicating the connection is being shutdown */
-		// event.sctp_adaptation_layer_event = 0;	/* adaptation layer notifications */
-		// event.sctp_authentication_event = 0;	/* when new key is made active */
-
-		/* Set the option to the socket */
-		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) );
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			sz = sizeof(event);
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, &sz) );
-			if (sz != sizeof(event))
-			{
-				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(event));
-				return ENOTSUP;
-			}
-
-			fd_log_debug( "SCTP_EVENTS : sctp_data_io_event          : %hhu\n", event.sctp_data_io_event);
-			fd_log_debug( "       	     sctp_association_event      : %hhu\n", event.sctp_association_event);
-			fd_log_debug( "       	     sctp_address_event	         : %hhu\n", event.sctp_address_event);
-			fd_log_debug( "       	     sctp_send_failure_event     : %hhu\n", event.sctp_send_failure_event);
-			fd_log_debug( "       	     sctp_peer_error_event       : %hhu\n", event.sctp_peer_error_event);
-			fd_log_debug( "       	     sctp_shutdown_event	 : %hhu\n", event.sctp_shutdown_event);
-			fd_log_debug( "       	     sctp_partial_delivery_event : %hhu\n", event.sctp_partial_delivery_event);
-			fd_log_debug( "       	     sctp_adaptation_layer_event : %hhu\n", event.sctp_adaptation_layer_event);
-			// fd_log_debug( "             sctp_authentication_event    : %hhu\n", event.sctp_authentication_event);
-		}
-		
-	}
-	
-	/* Set the INIT parameters, such as number of streams */
-	{
-		struct sctp_initmsg init;
-		memset(&init, 0, sizeof(init));
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			sz = sizeof(init);
-
-			/* Read socket defaults */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz)  );
-			if (sz != sizeof(init))
-			{
-				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(init));
-				return ENOTSUP;
-			}
-			fd_log_debug( "Def SCTP_INITMSG : sinit_num_ostreams   : %hu\n", init.sinit_num_ostreams);
-			fd_log_debug( "                   sinit_max_instreams  : %hu\n", init.sinit_max_instreams);
-			fd_log_debug( "                   sinit_max_attempts   : %hu\n", init.sinit_max_attempts);
-			fd_log_debug( "                   sinit_max_init_timeo : %hu\n", init.sinit_max_init_timeo);
-		}
-
-		/* Set the init options -- need to receive SCTP_COMM_UP to confirm the requested parameters */
-		init.sinit_num_ostreams	  = fd_g_config->cnf_sctp_str;	/* desired number of outgoing streams */
-		init.sinit_max_init_timeo = CNX_TIMEOUT * 1000;
-
-		/* Set the option to the socket */
-		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init))  );
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			/* Check new values */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz)  );
-			fd_log_debug( "New SCTP_INITMSG : sinit_num_ostreams   : %hu\n", init.sinit_num_ostreams);
-			fd_log_debug( "                   sinit_max_instreams  : %hu\n", init.sinit_max_instreams);
-			fd_log_debug( "                   sinit_max_attempts   : %hu\n", init.sinit_max_attempts);
-			fd_log_debug( "                   sinit_max_init_timeo : %hu\n", init.sinit_max_init_timeo);
-		}
-	}
-	
-	/* Set the SCTP_DISABLE_FRAGMENTS option, required for TLS */
-	#ifdef SCTP_DISABLE_FRAGMENTS
-	{
-		int nofrag;
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			sz = sizeof(nofrag);
-			/* Read socket defaults */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz)  );
-			if (sz != sizeof(nofrag))
-			{
-				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nofrag));
-				return ENOTSUP;
-			}
-			fd_log_debug( "Def SCTP_DISABLE_FRAGMENTS value : %s\n", nofrag ? "true" : "false");
-		}
-
-		nofrag = 0;	/* We turn ON the fragmentation */
-		
-		/* Set the option to the socket */
-		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, sizeof(nofrag))  );
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			/* Check new values */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz)  );
-			fd_log_debug( "New SCTP_DISABLE_FRAGMENTS value : %s\n", nofrag ? "true" : "false");
-		}
-	}
-	#else /* SCTP_DISABLE_FRAGMENTS */
-	# error "TLS requires support of SCTP_DISABLE_FRAGMENTS"
-	#endif /* SCTP_DISABLE_FRAGMENTS */
-	
-	
-	/* Set the RETRANSMIT parameters */
-	#ifdef SCTP_RTOINFO
-	{
-		struct sctp_rtoinfo rtoinfo;
-		memset(&rtoinfo, 0, sizeof(rtoinfo));
-
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			sz = sizeof(rtoinfo);
-			/* Read socket defaults */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz)  );
-			if (sz != sizeof(rtoinfo))
-			{
-				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(rtoinfo));
-				return ENOTSUP;
-			}
-			fd_log_debug( "Def SCTP_RTOINFO : srto_initial : %u\n", rtoinfo.srto_initial);
-			fd_log_debug( "                   srto_max     : %u\n", rtoinfo.srto_max);
-			fd_log_debug( "                   srto_min     : %u\n", rtoinfo.srto_min);
-		}
-
-		rtoinfo.srto_max     = fd_g_config->cnf_timer_tw * 500 - 1000;	/* Maximum retransmit timer (in ms) (set to Tw / 2 - 1) */
-
-		/* Set the option to the socket */
-		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo))  );
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			/* Check new values */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz)  );
-			fd_log_debug( "New SCTP_RTOINFO : srto_initial : %u\n", rtoinfo.srto_initial);
-			fd_log_debug( "                   srto_max     : %u\n", rtoinfo.srto_max);
-			fd_log_debug( "                   srto_min     : %u\n", rtoinfo.srto_min);
-		}
-	}
-	#else /* SCTP_RTOINFO */
-	TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_RTOINFO");
-	#endif /* SCTP_RTOINFO */
-	
-	/* Set the ASSOCIATION parameters */
-	#ifdef SCTP_ASSOCINFO
-	{
-		struct sctp_assocparams assoc;
-		memset(&assoc, 0, sizeof(assoc));
-
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			sz = sizeof(assoc);
-			/* Read socket defaults */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz)  );
-			if (sz != sizeof(assoc))
-			{
-				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(assoc));
-				return ENOTSUP;
-			}
-			fd_log_debug( "Def SCTP_ASSOCINFO : sasoc_asocmaxrxt               : %hu\n", assoc.sasoc_asocmaxrxt);
-			fd_log_debug( "                     sasoc_number_peer_destinations : %hu\n", assoc.sasoc_number_peer_destinations);
-			fd_log_debug( "                     sasoc_peer_rwnd                : %u\n" , assoc.sasoc_peer_rwnd);
-			fd_log_debug( "                     sasoc_local_rwnd               : %u\n" , assoc.sasoc_local_rwnd);
-			fd_log_debug( "                     sasoc_cookie_life              : %u\n" , assoc.sasoc_cookie_life);
-		}
-
-		assoc.sasoc_asocmaxrxt = 5;	/* Maximum retransmission attempts: we want fast detection of errors */
-		
-		/* Set the option to the socket */
-		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, sizeof(assoc))  );
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			/* Check new values */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz)  );
-			fd_log_debug( "New SCTP_ASSOCINFO : sasoc_asocmaxrxt               : %hu\n", assoc.sasoc_asocmaxrxt);
-			fd_log_debug( "                     sasoc_number_peer_destinations : %hu\n", assoc.sasoc_number_peer_destinations);
-			fd_log_debug( "                     sasoc_peer_rwnd                : %u\n" , assoc.sasoc_peer_rwnd);
-			fd_log_debug( "                     sasoc_local_rwnd               : %u\n" , assoc.sasoc_local_rwnd);
-			fd_log_debug( "                     sasoc_cookie_life              : %u\n" , assoc.sasoc_cookie_life);
-		}
-	}
-	#else /* SCTP_ASSOCINFO */
-	TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_ASSOCINFO");
-	#endif /* SCTP_ASSOCINFO */
-	
-	
-	/* The SO_LINGER option will be re-set if we want to perform SCTP ABORT */
-	#ifdef SO_LINGER
-	{
-		struct linger linger;
-		memset(&linger, 0, sizeof(linger));
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			sz = sizeof(linger);
-			/* Read socket defaults */
-			CHECK_SYS(  getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz)  );
-			if (sz != sizeof(linger))
-			{
-				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(linger));
-				return ENOTSUP;
-			}
-			fd_log_debug( "Def SO_LINGER : l_onoff  : %d\n", linger.l_onoff);
-			fd_log_debug( " 	       l_linger : %d\n", linger.l_linger);
-		}
-		
-		linger.l_onoff	= 0;	/* Do not activate the linger */
-		linger.l_linger = 0;	/* Return immediately when closing (=> abort) */
-		
-		/* Set the option */
-		CHECK_SYS(  setsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger))  );
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			/* Check new values */
-			CHECK_SYS(  getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz)  );
-			fd_log_debug( "New SO_LINGER : l_onoff  : %d\n", linger.l_onoff);
-			fd_log_debug( "		  l_linger : %d\n", linger.l_linger);
-		}
-	}
-	#else /* SO_LINGER */
-	TRACE_DEBUG(SCTP_LEVEL, "Skipping SO_LINGER");
-	#endif /* SO_LINGER */
-	
-	/* Set the NODELAY option (Nagle-like algorithm) */
-	#ifdef SCTP_NODELAY
-	{
-		int nodelay;
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			sz = sizeof(nodelay);
-			/* Read socket defaults */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz)  );
-			if (sz != sizeof(nodelay))
-			{
-				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nodelay));
-				return ENOTSUP;
-			}
-			fd_log_debug( "Def SCTP_NODELAY value : %s\n", nodelay ? "true" : "false");
-		}
-
-		nodelay = 0;	/* We turn ON the Nagle algorithm (probably the default already) */
-		
-		/* Set the option to the socket */
-		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay))  );
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			/* Check new values */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz)  );
-			fd_log_debug( "New SCTP_NODELAY value : %s\n", nodelay ? "true" : "false");
-		}
-	}
-	#else /* SCTP_NODELAY */
-	TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_NODELAY");
-	#endif /* SCTP_NODELAY */
-	
-	/* Set the interleaving option */
-	#ifdef SCTP_FRAGMENT_INTERLEAVE
-	{
-		int interleave;
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			sz = sizeof(interleave);
-			/* Read socket defaults */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz)  );
-			if (sz != sizeof(interleave))
-			{
-				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(interleave));
-				return ENOTSUP;
-			}
-			fd_log_debug( "Def SCTP_FRAGMENT_INTERLEAVE value : %d\n", interleave);
-		}
-
-		#if 0
-		interleave = 2;	/* Allow partial delivery on several streams at the same time, since we are stream-aware in our security modules */
-		#else /* 0 */
-		interleave = 1;	/* hmmm actually, we are not yet capable of handling this, and we don t need it. */
-		#endif /* 0 */
-		
-		/* Set the option to the socket */
-		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, sizeof(interleave))  );
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			/* Check new values */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz)  );
-			fd_log_debug( "New SCTP_FRAGMENT_INTERLEAVE value : %d\n", interleave);
-		}
-	}
-	#else /* SCTP_FRAGMENT_INTERLEAVE */
-	TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_FRAGMENT_INTERLEAVE");
-	#endif /* SCTP_FRAGMENT_INTERLEAVE */
-	
-	/* Set the v4 mapped addresses option */
-	#ifdef SCTP_I_WANT_MAPPED_V4_ADDR
-	{
-		int v4mapped;
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			sz = sizeof(v4mapped);
-			/* Read socket defaults */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz)  );
-			if (sz != sizeof(v4mapped))
-			{
-				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(v4mapped));
-				return ENOTSUP;
-			}
-			fd_log_debug( "Def SCTP_I_WANT_MAPPED_V4_ADDR value : %s\n", v4mapped ? "true" : "false");
-		}
-
-#ifndef SCTP_USE_MAPPED_ADDRESSES
-		v4mapped = 0;	/* We don't want v4 mapped addresses */
-#else /* SCTP_USE_MAPPED_ADDRESSES */
-		v4mapped = 1;	/* but we may have to, otherwise the bind fails in some environments */
-#endif /* SCTP_USE_MAPPED_ADDRESSES */
-		
-		/* Set the option to the socket */
-		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, sizeof(v4mapped))  );
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			/* Check new values */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz)  );
-			fd_log_debug( "New SCTP_I_WANT_MAPPED_V4_ADDR value : %s\n", v4mapped ? "true" : "false");
-		}
-	}
-	#else /* SCTP_I_WANT_MAPPED_V4_ADDR */
-	TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR");
-	#endif /* SCTP_I_WANT_MAPPED_V4_ADDR */
-			   
-			   
-	/* Other settable options (draft-ietf-tsvwg-sctpsocket-17):
-	   SO_RCVBUF			size of receiver window
-	   SO_SNDBUF			size of pending data to send
-	   SCTP_AUTOCLOSE		for one-to-many only
-	   SCTP_SET_PEER_PRIMARY_ADDR	ask remote peer to use this local address as primary
-	   SCTP_PRIMARY_ADDR		use this address as primary locally
-	   SCTP_ADAPTATION_LAYER	set adaptation layer indication 
-	   SCTP_PEER_ADDR_PARAMS	control heartbeat per peer address
-	   SCTP_DEFAULT_SEND_PARAM	parameters for the sendto() call
-	   SCTP_MAXSEG			max size of fragmented segments -- bound to PMTU
-	   SCTP_AUTH_CHUNK		request authentication of some type of chunk
-	    SCTP_HMAC_IDENT		authentication algorithms
-	    SCTP_AUTH_KEY		set a shared key
-	    SCTP_AUTH_ACTIVE_KEY	set the active key
-	    SCTP_AUTH_DELETE_KEY	remove a key
-	    SCTP_AUTH_DEACTIVATE_KEY	will not use that key anymore
-	   SCTP_DELAYED_SACK		control delayed acks
-	   SCTP_PARTIAL_DELIVERY_POINT	control partial delivery size
-	   SCTP_USE_EXT_RCVINFO		use extended receive info structure (information about the next message if available)
-	   SCTP_MAX_BURST		number of packets that can be burst emitted
-	   SCTP_CONTEXT			save a context information along with the association.
-	   SCTP_EXPLICIT_EOR		enable sending one message across several send calls
-	   SCTP_REUSE_PORT		share one listening port with several sockets
-	   
-	   read-only options:
-	   SCTP_STATUS			retrieve info such as number of streams, pending packets, state, ...
-	   SCTP_GET_PEER_ADDR_INFO	get information about a specific peer address of the association.
-	   SCTP_PEER_AUTH_CHUNKS	list of chunks the remote peer wants authenticated
-	   SCTP_LOCAL_AUTH_CHUNKS	list of chunks the local peer wants authenticated
-	   SCTP_GET_ASSOC_NUMBER	number of associations in a one-to-many socket
-	   SCTP_GET_ASSOC_ID_LIST	list of these associations
-	*/
-	
-	/* In case of no_ip4, force the v6only option -- is it a valid option for SCTP ? */
-	#ifdef IPV6_V6ONLY
-	if (fd_g_config->cnf_flags.no_ip4) {
-		int opt = 1;
-		CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)));
-	}
-	#endif /* IPV6_V6ONLY */
-	
-	return 0;
+	return ENOTSUP;
 }
 
-
-/* Post-binding socket options */
-static int fd_setsockopt_postbind(int sk, int bound_to_default)
+int fd_sctp_get_str_info( int socket, int *in, int *out )
 {
-	TRACE_ENTRY( "%d %d", sk, bound_to_default);
+	TODO("Retrieve streams info from the socket");
 	
-	CHECK_PARAMS( (sk > 0) );
-	
-	/* Set the ASCONF option */
-	#ifdef SCTP_AUTO_ASCONF
-	{
-		int asconf;
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			socklen_t sz;
-
-			sz = sizeof(asconf);
-			/* Read socket defaults */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz)  );
-			if (sz != sizeof(asconf))
-			{
-				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(asconf));
-				return ENOTSUP;
-			}
-			fd_log_debug( "Def SCTP_AUTO_ASCONF value : %s\n", asconf ? "true" : "false");
-		}
-
-		asconf = bound_to_default ? 1 : 0;	/* allow automatic use of added or removed addresses in the association (for bound-all sockets) */
-		
-		/* Set the option to the socket */
-		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, sizeof(asconf))  );
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			socklen_t sz = sizeof(asconf);
-			/* Check new values */
-			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz)  );
-			fd_log_debug( "New SCTP_AUTO_ASCONF value : %s\n", asconf ? "true" : "false");
-		}
-	}
-	#else /* SCTP_AUTO_ASCONF */
-	TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_AUTO_ASCONF");
-	#endif /* SCTP_AUTO_ASCONF */
-	
-	return 0;
+	return ENOTSUP;
 }
-
-/* Create a socket server and bind it according to daemon s configuration */
-int fd_sctp_create_bind_server( int * sock, struct fd_list * list, uint16_t port )
-{
-	int family;
-	int bind_default;
-	
-	TRACE_ENTRY("%p %p %hu", sock, list, port);
-	CHECK_PARAMS(sock);
-	
-	if (fd_g_config->cnf_flags.no_ip6) {
-		family = AF_INET;
-	} else {
-		family = AF_INET6; /* can create socket for both IP and IPv6 */
-	}
-	
-	/* Create the socket */
-	CHECK_SYS( *sock = socket(family, SOCK_STREAM, IPPROTO_SCTP) );
-	
-	/* Set pre-binding socket options, including number of streams etc... */
-	CHECK_FCT( fd_setsockopt_prebind(*sock) );
-	
-	bind_default = (! list) || (FD_IS_LIST_EMPTY(list)) ;
-redo:
-	if ( bind_default ) {
-		/* Implicit endpoints : bind to default addresses */
-		union {
-			sSS  ss;
-			sSA  sa;
-			sSA4 sin;
-			sSA6 sin6;
-		} s;
-		
-		/* 0.0.0.0 and [::] are all zeros */
-		memset(&s, 0, sizeof(s));
-		
-		s.sa.sa_family = family;
-		
-		if (family == AF_INET)
-			s.sin.sin_port = htons(port);
-		else
-			s.sin6.sin6_port = htons(port);
-		
-		CHECK_SYS( bind(*sock, &s.sa, sizeof(s)) );
-		
-	} else {
-		/* Explicit endpoints to bind to from config */
-		
-		union {
-			sSA     * sa;
-			sSA4	*sin;
-			sSA6	*sin6;
-			uint8_t *buf;
-		} ptr;
-		union {
-			sSA     * sa;
-			uint8_t * buf;
-		} sar;
-		int count = 0; /* number of sock addr in sar array */
-		size_t offset = 0;
-		struct fd_list * li;
-		
-		sar.buf = NULL;
-		
-		/* Create a flat array from the list of configured addresses */
-		for (li = list->next; li != list; li = li->next) {
-			struct fd_endpoint * ep = (struct fd_endpoint *)li;
-			size_t sz = 0;
-			
-			if (! (ep->flags & EP_FL_CONF))
-				continue;
-			
-			count++;
-			
-			/* Size of the new SA we are adding (sar may contain a mix of sockaddr_in and sockaddr_in6) */
-#ifndef SCTP_USE_MAPPED_ADDRESSES
-			if (ep->sa.sa_family == AF_INET6)
-#else /* SCTP_USE_MAPPED_ADDRESSES */
-			if (family == AF_INET6)
-#endif /* SCTP_USE_MAPPED_ADDRESSES */
-				sz = sizeof(sSA6);
-			else
-				sz = sizeof(sSA4);
-			
-			/* augment sar to contain the additional info */
-			CHECK_MALLOC( sar.buf = realloc(sar.buf, offset + sz)  );
-			
-			ptr.buf = sar.buf + offset; /* place of the new SA */
-			offset += sz; /* update to end of sar */
-			
-			if (sz == sizeof(sSA4)) {
-				memcpy(ptr.buf, &ep->sin, sz);
-				ptr.sin->sin_port = htons(port);
-			} else {
-				if (ep->sa.sa_family == AF_INET) { /* We must map the address */ 
-					memset(ptr.buf, 0, sz);
-					ptr.sin6->sin6_family = AF_INET6;
-					IN6_ADDR_V4MAP( &ptr.sin6->sin6_addr.s6_addr, ep->sin.sin_addr.s_addr );
-				} else {
-					memcpy(ptr.sin6, &ep->sin6, sz);
-				}
-				ptr.sin6->sin6_port = htons(port);
-			}
-		}
-		
-		if (!count) {
-			/* None of the addresses in the list came from configuration, we bind to default */
-			bind_default = 1;
-			goto redo;
-		}
-		
-		if (TRACE_BOOL(SCTP_LEVEL)) {
-			int i;
-			ptr.buf = sar.buf;
-			fd_log_debug("Calling sctp_bindx with the following address array:\n");
-			for (i = 0; i < count; i++) {
-				TRACE_DEBUG_sSA(FULL, "    - ", ptr.sa, NI_NUMERICHOST | NI_NUMERICSERV, "" );
-				ptr.buf += (ptr.sa->sa_family == AF_INET) ? sizeof(sSA4) : sizeof(sSA6) ;
-			}
-		}
-		
-		/* Bind to this array */
-		CHECK_SYS(  sctp_bindx(*sock, sar.sa, count, SCTP_BINDX_ADD_ADDR)  );
-		
-		/* We don't need sar anymore */
-		free(sar.buf);
-	}
-	
-	/* Now, the server is bound, set remaining sockopt */
-	CHECK_FCT( fd_setsockopt_postbind(*sock, bind_default) );
-	
-	/* Debug: show all local listening addresses */
-	if (TRACE_BOOL(SCTP_LEVEL)) {
-		sSA *sar;
-		union {
-			sSA	*sa;
-			uint8_t *buf;
-		} ptr;
-		int sz;
-		
-		CHECK_SYS(  sz = sctp_getladdrs(*sock, 0, &sar)  );
-		
-		fd_log_debug("SCTP server bound on :\n");
-		for (ptr.sa = sar; sz-- > 0; ptr.buf += (ptr.sa->sa_family == AF_INET) ? sizeof(sSA4) : sizeof(sSA6)) {
-			TRACE_DEBUG_sSA(FULL, "    - ", ptr.sa, NI_NUMERICHOST | NI_NUMERICSERV, "" );
-		}
-		sctp_freeladdrs(sar);
-	}
-
-	return 0;
-}
-
-/* Allow clients connections on server sockets */
-int fd_sctp_listen( int sock )
-{
-	TRACE_ENTRY("%d", sock);
-	CHECK_SYS( listen(sock, 5) );
-	return 0;
-}
-
-/* Create a client socket and connect to remote server */
-int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list )
-{
-	int family;
-	int count = 0;
-	size_t offset = 0, sz;
-	union {
-		uint8_t *buf;
-		sSA	*sa;
-	} sar;
-	union {
-		uint8_t *buf;
-		sSA	*sa;
-		sSA4	*sin;
-		sSA6	*sin6;
-	} ptr;
-	struct fd_list * li;
-	int ret;
-	
-	sar.buf = NULL;
-	
-	TRACE_ENTRY("%p %i %hu %p", sock, no_ip6, port, list);
-	CHECK_PARAMS( sock && list && (!FD_IS_LIST_EMPTY(list)) );
-	
-	if (no_ip6) {
-		family = AF_INET;
-	} else {
-		family = AF_INET6;
-	}
-	
-	/* Create the socket */
-	CHECK_SYS( *sock = socket(family, SOCK_STREAM, IPPROTO_SCTP) );
-	
-	/* Cleanup if we are cancelled */
-	pthread_cleanup_push(fd_cleanup_socket, sock);
-	
-	/* Set the socket options */
-	CHECK_FCT_DO( ret = fd_setsockopt_prebind(*sock), goto fail );
-	
-	/* Create the array of addresses for sctp_connectx */
-	for (li = list->next; li != list; li = li->next) {
-		struct fd_endpoint * ep = (struct fd_endpoint *) li;
-		
-		count++;
-		
-		/* Size of the new SA we are adding (sar may contain a mix of sockaddr_in and sockaddr_in6) */
-#ifndef SCTP_USE_MAPPED_ADDRESSES
-		if (ep->sa.sa_family == AF_INET6)
-#else /* SCTP_USE_MAPPED_ADDRESSES */
-		if (family == AF_INET6)
-#endif /* SCTP_USE_MAPPED_ADDRESSES */
-			sz = sizeof(sSA6);
-		else
-			sz = sizeof(sSA4);
-		
-		/* augment sar to contain the additional info */
-		CHECK_MALLOC_DO( sar.buf = realloc(sar.buf, offset + sz), { ret = ENOMEM; goto fail; }  );
-
-		ptr.buf = sar.buf + offset; /* place of the new SA */
-		offset += sz; /* update to end of sar */
-			
-		if (sz == sizeof(sSA4)) {
-			memcpy(ptr.buf, &ep->sin, sz);
-			ptr.sin->sin_port = htons(port);
-		} else {
-			if (ep->sa.sa_family == AF_INET) { /* We must map the address */ 
-				memset(ptr.buf, 0, sz);
-				ptr.sin6->sin6_family = AF_INET6;
-				IN6_ADDR_V4MAP( &ptr.sin6->sin6_addr.s6_addr, ep->sin.sin_addr.s_addr );
-			} else {
-				memcpy(ptr.sin6, &ep->sin6, sz);
-			}
-			ptr.sin6->sin6_port = htons(port);
-		}
-	}
-	
-	/* Try connecting */
-	TRACE_DEBUG(FULL, "Attempting SCTP connection (%d addresses attempted)...", count);
-	CHECK_SYS_DO( sctp_connectx(*sock, sar.sa, count), { ret = errno; goto fail; } );
-	free(sar.buf); sar.buf = NULL;
-	
-	/* Set the remaining sockopts */
-	CHECK_FCT_DO( ret = fd_setsockopt_postbind(*sock, 1), goto fail );
-	
-	/* Done! */
-	pthread_cleanup_pop(0);
-	return 0;
-	
-fail:
-	if (*sock > 0) {
-		shutdown(*sock, SHUT_RDWR);
-		*sock = -1;
-	}
-	free(sar.buf);
-	return ret;
-}
-
-/* Retrieve streams information from a connected association -- optionaly provide the primary address */
-int fd_sctp_get_str_info( int sock, uint16_t *in, uint16_t *out, sSS *primary )
-{
-	struct sctp_status status;
-	socklen_t sz = sizeof(status);
-	
-	TRACE_ENTRY("%d %p %p %p", sock, in, out, primary);
-	CHECK_PARAMS( (sock > 0) && in && out );
-	
-	/* Read the association parameters */
-	memset(&status, 0, sizeof(status));
-	CHECK_SYS(  getsockopt(sock, IPPROTO_SCTP, SCTP_STATUS, &status, &sz) );
-	if (sz != sizeof(status))
-	{
-		TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %zd", sz, sizeof(status));
-		return ENOTSUP;
-	}
-	if (TRACE_BOOL(SCTP_LEVEL)) {
-		fd_log_debug( "SCTP_STATUS : sstat_state                  : %i\n" , status.sstat_state);
-		fd_log_debug( "              sstat_rwnd  	          : %u\n" , status.sstat_rwnd);
-		fd_log_debug( "		     sstat_unackdata	          : %hu\n", status.sstat_unackdata);
-		fd_log_debug( "		     sstat_penddata 	          : %hu\n", status.sstat_penddata);
-		fd_log_debug( "		     sstat_instrms  	          : %hu\n", status.sstat_instrms);
-		fd_log_debug( "		     sstat_outstrms 	          : %hu\n", status.sstat_outstrms);
-		fd_log_debug( "		     sstat_fragmentation_point    : %u\n" , status.sstat_fragmentation_point);
-		fd_log_debug( "		     sstat_primary.spinfo_address : ");
-		sSA_DUMP_NODE_SERV(&status.sstat_primary.spinfo_address, NI_NUMERICHOST | NI_NUMERICSERV );
-		fd_log_debug( "\n" );
-		fd_log_debug( "		     sstat_primary.spinfo_state   : %d\n" , status.sstat_primary.spinfo_state);
-		fd_log_debug( "		     sstat_primary.spinfo_cwnd    : %u\n" , status.sstat_primary.spinfo_cwnd);
-		fd_log_debug( "		     sstat_primary.spinfo_srtt    : %u\n" , status.sstat_primary.spinfo_srtt);
-		fd_log_debug( "		     sstat_primary.spinfo_rto     : %u\n" , status.sstat_primary.spinfo_rto);
-		fd_log_debug( "		     sstat_primary.spinfo_mtu     : %u\n" , status.sstat_primary.spinfo_mtu);
-	}
-	
-	*in = status.sstat_instrms;
-	*out = status.sstat_outstrms;
-	
-	if (primary)
-		memcpy(primary, &status.sstat_primary.spinfo_address, sizeof(sSS));
-	
-	return 0;
-}
-
-/* Get the list of local endpoints of the socket */
-int fd_sctp_get_local_ep(int sock, struct fd_list * list)
-{
-	union {
-		sSA	*sa;
-		uint8_t	*buf;
-	} ptr;
-	
-	sSA * data;
-	int count;
-	
-	TRACE_ENTRY("%d %p", sock, list);
-	CHECK_PARAMS(list);
-	
-	/* Read the list on the socket */
-	CHECK_SYS( count = sctp_getladdrs(sock, 0, &data)  );
-	ptr.sa = data;
-	
-	while (count) {
-		socklen_t sl;
-		switch (ptr.sa->sa_family) {
-			case AF_INET:	sl = sizeof(sSA4); break;
-			case AF_INET6:	sl = sizeof(sSA6); break;
-			default:
-				TRACE_DEBUG(INFO, "Unkown address family returned in sctp_getladdrs: %d", ptr.sa->sa_family);
-		}
-				
-		CHECK_FCT( fd_ep_add_merge( list, ptr.sa, sl, EP_FL_LL ) );
-		ptr.buf += sl;
-		count --;
-	}
-	
-	/* Free the list */
-	sctp_freeladdrs(data);
-	
-	/* Now get the primary address, the add function will take care of merging with existing entry */
-	{
-		 
-		struct sctp_status status;
-		socklen_t sz = sizeof(status);
-		int ret;
-		
-		memset(&status, 0, sizeof(status));
-		/* Attempt to use SCTP_STATUS message to retrieve the primary address */
-		ret = getsockopt(sock, IPPROTO_SCTP, SCTP_STATUS, &status, &sz);
-		if (sz != sizeof(status))
-			ret = -1;
-		sz = sizeof(sSS);
-		if (ret < 0)
-		{
-			/* Fallback to getsockname -- not recommended by draft-ietf-tsvwg-sctpsocket-19#section-7.4 */
-			CHECK_SYS(getsockname(sock, (sSA *)&status.sstat_primary.spinfo_address, &sz));
-		}
-			
-		CHECK_FCT( fd_ep_add_merge( list, (sSA *)&status.sstat_primary.spinfo_address, sz, EP_FL_PRIMARY ) );
-	}
-	
-	return 0;
-}
-
-/* Get the list of remote endpoints of the socket */
-int fd_sctp_get_remote_ep(int sock, struct fd_list * list)
-{
-	union {
-		sSA	*sa;
-		uint8_t	*buf;
-	} ptr;
-	
-	sSA * data;
-	int count;
-	
-	TRACE_ENTRY("%d %p", sock, list);
-	CHECK_PARAMS(list);
-	
-	/* Read the list on the socket */
-	CHECK_SYS( count = sctp_getpaddrs(sock, 0, &data)  );
-	ptr.sa = data;
-	
-	while (count) {
-		socklen_t sl;
-		switch (ptr.sa->sa_family) {
-			case AF_INET:	sl = sizeof(sSA4); break;
-			case AF_INET6:	sl = sizeof(sSA6); break;
-			default:
-				TRACE_DEBUG(INFO, "Unkown address family returned in sctp_getpaddrs: %d", ptr.sa->sa_family);
-		}
-				
-		CHECK_FCT( fd_ep_add_merge( list, ptr.sa, sl, EP_FL_LL ) );
-		ptr.buf += sl;
-		count --;
-	}
-	
-	/* Free the list */
-	sctp_freepaddrs(data);
-	
-	/* Now get the primary address, the add function will take care of merging with existing entry */
-	{
-		sSS ss;
-		socklen_t sl = sizeof(sSS);
-	
-		CHECK_SYS(getpeername(sock, (sSA *)&ss, &sl));
-		CHECK_FCT( fd_ep_add_merge( list, (sSA *)&ss, sl, EP_FL_PRIMARY ) );
-	}
-	
-	/* Done! */
-	return 0;
-}
-
-/* Send a buffer over a specified stream */
-int fd_sctp_sendstr(int sock, uint16_t strid, uint8_t * buf, size_t len)
-{
-	struct msghdr mhdr;
-	struct iovec  iov;
-	struct {
-		struct cmsghdr 		hdr;
-		struct sctp_sndrcvinfo	sndrcv;
-	} anci;
-	ssize_t ret;
-	
-	TRACE_ENTRY("%d %hu %p %zd", sock, strid, buf, len);
-	
-	memset(&mhdr, 0, sizeof(mhdr));
-	memset(&iov,  0, sizeof(iov));
-	memset(&anci, 0, sizeof(anci));
-	
-	/* IO Vector: message data */
-	iov.iov_base = buf;
-	iov.iov_len  = len;
-	
-	/* Anciliary data: specify SCTP stream */
-	anci.hdr.cmsg_len   = sizeof(anci);
-	anci.hdr.cmsg_level = IPPROTO_SCTP;
-	anci.hdr.cmsg_type  = SCTP_SNDRCV;
-	anci.sndrcv.sinfo_stream = strid;
-	/* note : we could store other data also, for example in .sinfo_ppid for remote peer or in .sinfo_context for errors. */
-	
-	/* We don't use mhdr.msg_name here; it could be used to specify an address different from the primary */
-	
-	mhdr.msg_iov    = &iov;
-	mhdr.msg_iovlen = 1;
-	
-	mhdr.msg_control    = &anci;
-	mhdr.msg_controllen = sizeof(anci);
-	
-	TRACE_DEBUG(FULL, "Sending %db data on stream %hu of socket %d", len, strid, sock);
-	
-	CHECK_SYS( ret = sendmsg(sock, &mhdr, 0) );
-	ASSERT( ret == len ); /* There should not be partial delivery with sendmsg... */
-	
-	return 0;
-}
-
-/* Receive the next data from the socket, or next notification */
-int fd_sctp_recvmeta(int sock, uint16_t * strid, uint8_t ** buf, size_t * len, int *event)
-{
-	ssize_t 		 ret = 0;
-	struct msghdr 		 mhdr;
-	char   			 ancidata[ CMSG_BUF_LEN ];
-	struct iovec 		 iov;
-	uint8_t			*data = NULL;
-	size_t 			 bufsz = 0, datasize = 0;
-	size_t			 mempagesz = sysconf(_SC_PAGESIZE); /* We alloc buffer by memory pages for efficiency */
-	
-	TRACE_ENTRY("%d %p %p %p %p", sock, strid, buf, len, event);
-	CHECK_PARAMS( (sock > 0) && buf && len && event );
-	
-	/* Cleanup out parameters */
-	*buf = NULL;
-	*len = 0;
-	*event = 0;
-	
-	/* Prepare header for receiving message */
-	memset(&mhdr, 0, sizeof(mhdr));
-	mhdr.msg_iov    = &iov;
-	mhdr.msg_iovlen = 1;
-	mhdr.msg_control    = &ancidata;
-	mhdr.msg_controllen = sizeof(ancidata);
-	
-	/* We will loop while all data is not received. */
-incomplete:
-	if (datasize == bufsz) {
-		/* The buffer is full, enlarge it */
-		bufsz += mempagesz;
-		CHECK_MALLOC( data = realloc(data, bufsz) );
-	}
-	/* the new data will be received following the preceding */
-	memset(&iov,  0, sizeof(iov));
-	iov.iov_base = data + datasize ;
-	iov.iov_len  = bufsz - datasize;
-
-	/* Receive data from the socket */
-	pthread_cleanup_push(free, data);
-	ret = recvmsg(sock, &mhdr, 0);
-	pthread_cleanup_pop(0);
-	
-	/* Handle errors */
-	if (ret <= 0) { /* Socket is closed, or an error occurred */
-		CHECK_SYS_DO(ret, /* to log in case of error */);
-		free(data);
-		*event = FDEVP_CNX_ERROR;
-		return 0;
-	}
-	
-	/* Update the size of data we received */
-	datasize += ret;
-
-	/* SCTP provides an indication when we received a full record; loop if it is not the case */
-	if ( ! (mhdr.msg_flags & MSG_EOR) ) {
-		goto incomplete;
-	}
-	
-	TRACE_DEBUG(FULL, "Received %db data on socket %d", datasize, sock);
-	
-	/* Handle the case where the data received is a notification */
-	if (mhdr.msg_flags & MSG_NOTIFICATION) {
-		union sctp_notification * notif = (union sctp_notification *) data;
-		
-		switch (notif->sn_header.sn_type) {
-			
-			case SCTP_ASSOC_CHANGE:
-				TRACE_DEBUG(FULL, "Received SCTP_ASSOC_CHANGE notification");
-				TRACE_DEBUG(SCTP_LEVEL, "    state : %hu", notif->sn_assoc_change.sac_state);
-				TRACE_DEBUG(SCTP_LEVEL, "    error : %hu", notif->sn_assoc_change.sac_error);
-				TRACE_DEBUG(SCTP_LEVEL, "    instr : %hu", notif->sn_assoc_change.sac_inbound_streams);
-				TRACE_DEBUG(SCTP_LEVEL, "   outstr : %hu", notif->sn_assoc_change.sac_outbound_streams);
-				
-				*event = FDEVP_CNX_EP_CHANGE;
-				break;
-	
-			case SCTP_PEER_ADDR_CHANGE:
-				TRACE_DEBUG(FULL, "Received SCTP_PEER_ADDR_CHANGE notification");
-				TRACE_DEBUG_sSA(SCTP_LEVEL, "    intf_change : ", &(notif->sn_paddr_change.spc_aaddr), NI_NUMERICHOST | NI_NUMERICSERV, "" );
-				TRACE_DEBUG(SCTP_LEVEL, "          state : %d", notif->sn_paddr_change.spc_state);
-				TRACE_DEBUG(SCTP_LEVEL, "          error : %d", notif->sn_paddr_change.spc_error);
-				
-				*event = FDEVP_CNX_EP_CHANGE;
-				break;
-	
-			case SCTP_SEND_FAILED:
-				TRACE_DEBUG(FULL, "Received SCTP_SEND_FAILED notification");
-				TRACE_DEBUG(SCTP_LEVEL, "    len : %hu", notif->sn_send_failed.ssf_length);
-				TRACE_DEBUG(SCTP_LEVEL, "    err : %d",  notif->sn_send_failed.ssf_error);
-				
-				*event = FDEVP_CNX_ERROR;
-				break;
-			
-			case SCTP_REMOTE_ERROR:
-				TRACE_DEBUG(FULL, "Received SCTP_REMOTE_ERROR notification");
-				TRACE_DEBUG(SCTP_LEVEL, "    err : %hu", ntohs(notif->sn_remote_error.sre_error));
-				TRACE_DEBUG(SCTP_LEVEL, "    len : %hu", ntohs(notif->sn_remote_error.sre_length));
-				
-				*event = FDEVP_CNX_ERROR;
-				break;
-	
-			case SCTP_SHUTDOWN_EVENT:
-				TRACE_DEBUG(FULL, "Received SCTP_SHUTDOWN_EVENT notification");
-				
-				*event = FDEVP_CNX_ERROR;
-				break;
-			
-			default:	
-				TRACE_DEBUG(FULL, "Received unknown notification %d, assume error", notif->sn_header.sn_type);
-				*event = FDEVP_CNX_ERROR;
-		}
-		
-		free(data);
-		return 0;
-	}
-	
-	/* From this point, we have received a message */
-	*event = FDEVP_CNX_MSG_RECV;
-	*buf = data;
-	*len = datasize;
-	
-	if (strid) {
-		struct cmsghdr 		*hdr;
-		struct sctp_sndrcvinfo	*sndrcv;
-		
-		/* Handle the anciliary data */
-		for (hdr = CMSG_FIRSTHDR(&mhdr); hdr; hdr = CMSG_NXTHDR(&mhdr, hdr)) {
-
-			/* We deal only with anciliary data at SCTP level */
-			if (hdr->cmsg_level != IPPROTO_SCTP) {
-				TRACE_DEBUG(FULL, "Received some anciliary data at level %d, skipped", hdr->cmsg_level);
-				continue;
-			}
-			
-			/* Also only interested in SCTP_SNDRCV message for the moment */
-			if (hdr->cmsg_type != SCTP_SNDRCV) {
-				TRACE_DEBUG(FULL, "Anciliary block IPPROTO_SCTP / %d, skipped", hdr->cmsg_type);
-				continue;
-			}
-			
-			sndrcv = (struct sctp_sndrcvinfo *) CMSG_DATA(hdr);
-			if (TRACE_BOOL(SCTP_LEVEL)) {
-				fd_log_debug( "Anciliary block IPPROTO_SCTP / SCTP_SNDRCV\n");
-				fd_log_debug( "    sinfo_stream    : %hu\n", sndrcv->sinfo_stream);
-				fd_log_debug( "    sinfo_ssn       : %hu\n", sndrcv->sinfo_ssn);
-				fd_log_debug( "    sinfo_flags     : %hu\n", sndrcv->sinfo_flags);
-				/* fd_log_debug( "    sinfo_pr_policy : %hu\n", sndrcv->sinfo_pr_policy); */
-				fd_log_debug( "    sinfo_ppid      : %u\n" , sndrcv->sinfo_ppid);
-				fd_log_debug( "    sinfo_context   : %u\n" , sndrcv->sinfo_context);
-				/* fd_log_debug( "    sinfo_pr_value  : %u\n" , sndrcv->sinfo_pr_value); */
-				fd_log_debug( "    sinfo_tsn       : %u\n" , sndrcv->sinfo_tsn);
-				fd_log_debug( "    sinfo_cumtsn    : %u\n" , sndrcv->sinfo_cumtsn);
-			}
-
-			*strid = sndrcv->sinfo_stream;
-		}
-	}
-	
-	return 0;
-}
Index: eeDiameter/sctps.c
===================================================================
--- freeDiameter/sctps.c	(revision 29)
+++ 	(revision )
@@ -1,639 +1,0 @@
-/*********************************************************************************************************
-* Software License Agreement (BSD License)                                                               *
-* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
-*													 *
-* Copyright (c) 2009, WIDE Project and NICT								 *
-* All rights reserved.											 *
-* 													 *
-* Redistribution and use of this software in source and binary forms, with or without modification, are  *
-* permitted provided that the following conditions are met:						 *
-* 													 *
-* * Redistributions of source code must retain the above 						 *
-*   copyright notice, this list of conditions and the 							 *
-*   following disclaimer.										 *
-*    													 *
-* * Redistributions in binary form must reproduce the above 						 *
-*   copyright notice, this list of conditions and the 							 *
-*   following disclaimer in the documentation and/or other						 *
-*   materials provided with the distribution.								 *
-* 													 *
-* * Neither the name of the WIDE Project or NICT nor the 						 *
-*   names of its contributors may be used to endorse or 						 *
-*   promote products derived from this software without 						 *
-*   specific prior written permission of WIDE Project and 						 *
-*   NICT.												 *
-* 													 *
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
-* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
-* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
-* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
-* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
-*********************************************************************************************************/
-
-/* This file contains code for TLS over multi-stream SCTP wrapper implementation (GnuTLS does not support this) */
-/* See http://aaa.koganei.wide.ad.jp/blogs/index.php/waaad/2008/08/18/tls-over-sctp for history */
-
-#include "fD.h"
-#include "cnxctx.h"
-
-#include <netinet/sctp.h>
-#include <sys/uio.h>
-
-/*
-
-Architecture of this wrapper:
- - we have several fifo queues (1 per stream pairs).
- GnuTLS is configured to use custom push / pull functions:
- - the pull function retrieves the data from the fifo queue corresponding to a stream #.
- - the push function sends the data on a certain stream.
- We also have a demux thread that reads the socket and store received data in the appropriate fifo
- 
- We have one gnutls_session per stream pair, and as many streams that read the gnutls records and save incoming data to the target queue.
- 
-This complexity is required because we cannot read a socket for a given stream only; we can only get the next message and find its stream.
-*/
-
-
-
-/*************************************************************/
-/*                      threads                              */
-/*************************************************************/
-
-/* Demux received data and store in the appropriate fifo */
-static void * demuxer(void * arg)
-{
-	struct cnxctx * conn = arg;
-	uint8_t * buf;
-	size_t    bufsz;
-	int	  event;
-	uint16_t  strid;
-	
-	TRACE_ENTRY("%p", arg);
-	CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
-	
-	/* Set the thread name */
-	{
-		char buf[48];
-		snprintf(buf, sizeof(buf), "Demuxer (%d)", conn->cc_socket);
-		fd_log_threadname ( buf );
-	}
-	
-	ASSERT( conn->cc_proto == IPPROTO_SCTP );
-	ASSERT( Target_Queue(conn) );
-	ASSERT( conn->cc_sctps_data.array );
-	
-	do {
-		CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, &strid, &buf, &bufsz, &event), goto error );
-		switch (event) {
-			case FDEVP_CNX_MSG_RECV:
-				/* Demux this message in the appropriate fifo, another thread will pull, gnutls process, and send in target queue */
-				CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto error );
-				break;
-				
-			case FDEVP_CNX_EP_CHANGE:
-				/* Send this event to the target queue */
-				CHECK_FCT_DO( fd_event_send( Target_Queue(conn), event, bufsz, buf), goto error );
-				break;
-			
-			case FDEVP_CNX_ERROR:
-			default:
-				goto error;
-		}
-		
-	} while (conn->cc_loop);
-	
-out:
-	TRACE_DEBUG(FULL, "Thread terminated");	
-	return NULL;
-error:
-	CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
-	goto out;
-}
-
-/* Decrypt the data received in this stream pair and store it in the target queue */
-static void * decipher(void * arg)
-{
-	struct sctps_ctx * ctx = arg;
-	struct cnxctx 	 *cnx;
-	
-	TRACE_ENTRY("%p", arg);
-	CHECK_PARAMS_DO(ctx && ctx->raw_recv && ctx->parent, goto error);
-	cnx = ctx->parent;
-	ASSERT( Target_Queue(cnx) );
-	
-	/* Set the thread name */
-	{
-		char buf[48];
-		snprintf(buf, sizeof(buf), "Decipher (%hu@%d)", ctx->strid, cnx->cc_socket);
-		fd_log_threadname ( buf );
-	}
-	
-	CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */);
-error:
-	CHECK_FCT_DO( fd_event_send( Target_Queue(cnx), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
-	TRACE_DEBUG(FULL, "Thread terminated");	
-	return NULL;
-}
-
-/*************************************************************/
-/*                     push / pull                           */
-/*************************************************************/
-
-/* Send data over the connection, called by gnutls */
-static ssize_t sctps_push(gnutls_transport_ptr_t tr, const void * data, size_t len)
-{
-	struct sctps_ctx * ctx = (struct sctps_ctx *) tr;
-	
-	TRACE_ENTRY("%p %p %zd", tr, data, len);
-	CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } );
-	
-	CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent->cc_socket, ctx->strid, (uint8_t *)data, len), /* errno is already set */ return -1 );
-	
-	return len;
-}
-
-/* Retrieve data received on a stream and already demultiplexed */
-static ssize_t sctps_pull(gnutls_transport_ptr_t tr, void * buf, size_t len)
-{
-	struct sctps_ctx * ctx = (struct sctps_ctx *) tr;
-	size_t pulled = 0;
-	int emptied;
-	
-	TRACE_ENTRY("%p %p %zd", tr, buf, len);
-	CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; return -1; } );
-	
-	/* If we don't have data available now, pull new message from the fifo -- this is blocking */
-	if (!ctx->partial.buf) {
-		int ev;
-		CHECK_FCT_DO( errno = fd_event_get(ctx->raw_recv, &ev, &ctx->partial.bufsz, (void *)&ctx->partial.buf), return -1 );
-		ASSERT( ev == FDEVP_CNX_MSG_RECV );
-	}
-		
-	pulled = ctx->partial.bufsz - ctx->partial.offset;
-	if (pulled <= len) {
-		emptied = 1;
-	} else {
-		/* limit to the capacity of destination buffer */
-		emptied = 0;
-		pulled = len;
-	}
-
-	/* Store the data in the destination buffer */
-	memcpy(buf, ctx->partial.buf + ctx->partial.offset, pulled);
-
-	/* Free the buffer if we read all its content, and reset the partial structure */
-	if (emptied) {
-		free(ctx->partial.buf);
-		memset(&ctx->partial, 0, sizeof(ctx->partial));
-	} else {
-		ctx->partial.offset += pulled;
-	}
-
-	/* We are done */
-	return pulled;
-}
-
-/* Set the parameters of a session to use the appropriate fifo and stream information */
-static void set_sess_transport(gnutls_session_t session, struct sctps_ctx *ctx)
-{
-	/* Set the transport pointer passed to push & pull callbacks */
-	gnutls_transport_set_ptr( session, (gnutls_transport_ptr_t) ctx );
-	
-	/* Reset the low water value, since we don't use sockets */
-	gnutls_transport_set_lowat( session, 0 );
-	
-	/* Set the push and pull callbacks */
-	gnutls_transport_set_pull_function(session, sctps_pull);
-	gnutls_transport_set_push_function(session, sctps_push);
-
-	return;
-}
-
-/*************************************************************/
-/*               Session resuming support                    */
-/*************************************************************/
-
-struct sr_store {
-	struct fd_list	 list;	/* list of sr_data, ordered by key.size then key.data */
-	pthread_rwlock_t lock;
-	struct cnxctx   *parent;
-	/* Add another list to chain in a global list to implement a garbage collector on sessions */
-};
-
-/* Saved master session data for resuming sessions */
-struct sr_data {
-	struct fd_list	chain;
-	gnutls_datum_t	key;
-	gnutls_datum_t 	data;
-};
-
-/* The level at which we debug session resuming */
-#define SR_LEVEL (FULL + 1)
-
-/* Initialize the store area for a connection */
-static int store_init(struct cnxctx * conn)
-{
-	TRACE_ENTRY("%p", conn);
-	CHECK_PARAMS( conn && !conn->cc_sctps_data.sess_store );
-	
-	CHECK_MALLOC( conn->cc_sctps_data.sess_store = malloc(sizeof(struct sr_store)) );
-	memset(conn->cc_sctps_data.sess_store, 0, sizeof(struct sr_store));
-	
-	fd_list_init(&conn->cc_sctps_data.sess_store->list, NULL);
-	CHECK_POSIX( pthread_rwlock_init(&conn->cc_sctps_data.sess_store->lock, NULL) );
-	conn->cc_sctps_data.sess_store->parent = conn;
-	
-	return 0;
-}
-
-/* Destroy the store area for a connection, and all its content */
-static void store_destroy(struct cnxctx * conn)
-{
-	/* Del all list entries */
-	TRACE_ENTRY("%p", conn);
-	CHECK_PARAMS_DO( conn, return );
-	
-	if (!conn->cc_sctps_data.sess_store)
-		return;
-	
-	CHECK_POSIX_DO( pthread_rwlock_destroy(&conn->cc_sctps_data.sess_store->lock), /* continue */ );
-	
-	while (!FD_IS_LIST_EMPTY(&conn->cc_sctps_data.sess_store->list)) {
-		struct sr_data * sr = (struct sr_data *) conn->cc_sctps_data.sess_store->list.next;
-		fd_list_unlink( &sr->chain );
-		free(sr->key.data);
-		free(sr->data.data);
-		free(sr);
-	}
-	
-	free(conn->cc_sctps_data.sess_store);
-	conn->cc_sctps_data.sess_store = NULL;
-	return;
-}
-
-/* Search the position (or next if not found) of a key in a store */
-static struct fd_list * find_or_next(struct sr_store * sto, gnutls_datum_t key, int * match)
-{
-	struct fd_list * ret;
-	*match = 0;
-	
-	for (ret = sto->list.next; ret != &sto->list; ret = ret->next) {
-		int cmp = 0;
-		struct sr_data * sr = (struct sr_data *)ret;
-		
-		if ( key.size < sr->key.size )
-			break;
-		
-		if ( key.size > sr->key.size )
-			continue;
-		
-		/* Key sizes are equal */
-		cmp = memcmp( key.data, sr->key.data, key.size );
-		
-		if (cmp > 0)
-			continue;
-		
-		if (cmp == 0)
-			*match = 1;
-		
-		break;
-	}
-	
-	return ret;
-}
-
-/* Callbacks for the TLS server side of the connection, called during gnutls_handshake */
-static int sr_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data)
-{
-	struct sr_store * sto = (struct sr_store *)dbf;
-	struct fd_list * li;
-	struct sr_data * sr;
-	int match = 0;
-	int ret = 0;
-	
-	CHECK_PARAMS_DO( sto && key.data && data.data, return -1 );
-	
-	CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 );
-	TRACE_DEBUG_BUFFER(SR_LEVEL, "Session store [key ", key.data, key.size, "]");
-	
-	li = find_or_next(sto, key, &match);
-	if (match) {
-		sr = (struct sr_data *)li;
-		
-		/* Check the data is the same */
-		if ((data.size != sr->data.size) || memcmp(data.data, sr->data.data, data.size)) {
-			TRACE_DEBUG(SR_LEVEL, "GnuTLS tried to store a session with same key and different data!");
-			ret = -1;
-		} else {
-			TRACE_DEBUG(SR_LEVEL, "GnuTLS tried to store a session with same key and same data, skipped.");
-		}
-		goto out;
-	}
-	
-	/* Create a new entry */
-	CHECK_MALLOC_DO( sr = malloc(sizeof(struct sr_data)), { ret = -1; goto out; } );
-	memset(sr, 0, sizeof(struct sr_data));
-
-	fd_list_init(&sr->chain, sr);
-
-	CHECK_MALLOC_DO( sr->key.data = malloc(key.size), { ret = -1; goto out; } );
-	sr->key.size = key.size;
-	memcpy(sr->key.data, key.data, key.size);
-
-	CHECK_MALLOC_DO( sr->data.data = malloc(data.size), { ret = -1; goto out; } );
-	sr->data.size = data.size;
-	memcpy(sr->data.data, data.data, data.size);
-	
-	/* Save this new entry in the list, we are done */
-	fd_list_insert_before(li, &sr->chain);
-
-out:	
-	CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return -1 );
-	return ret;
-}
-
-static int sr_remove (void *dbf, gnutls_datum_t key)
-{
-	struct sr_store * sto = (struct sr_store *)dbf;
-	struct fd_list * li;
-	struct sr_data * sr;
-	int match = 0;
-	int ret = 0;
-	
-	CHECK_PARAMS_DO( sto && key.data, return -1 );
-	
-	CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 );
-	TRACE_DEBUG_BUFFER(SR_LEVEL, "Session delete [key ", key.data, key.size, "]");
-	
-	li = find_or_next(sto, key, &match);
-	if (match) {
-		sr = (struct sr_data *)li;
-		
-		/* Destroy this data */
-		fd_list_unlink(li);
-		free(sr->key.data);
-		free(sr->data.data);
-		free(sr);
-	} else {
-		/* It was not found */
-		ret = -1;
-	}
-	
-	CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return -1 );
-	return ret;
-}
-
-static gnutls_datum_t sr_fetch (void *dbf, gnutls_datum_t key)
-{
-	struct sr_store * sto = (struct sr_store *)dbf;
-	struct fd_list * li;
-	struct sr_data * sr;
-	int match = 0;
-	gnutls_datum_t res = { NULL, 0 };
-	gnutls_datum_t error = { NULL, 0 };
-
-	CHECK_PARAMS_DO( sto && key.data, return error );
-
-	CHECK_POSIX_DO( pthread_rwlock_rdlock(&sto->lock), return error );
-	TRACE_DEBUG_BUFFER(SR_LEVEL, "Session fetch [key ", key.data, key.size, "]");
-	
-	li = find_or_next(sto, key, &match);
-	if (match) {
-		sr = (struct sr_data *)li;
-		CHECK_MALLOC_DO(res.data = gnutls_malloc(sr->data.size), goto out );
-		res.size = sr->data.size;
-		memcpy(res.data, sr->data.data, res.size);
-	}
-out:	
-	TRACE_DEBUG(SR_LEVEL, "Fetched (%p, %d) from store %p", res.data, res.size, sto);
-	CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return error);
-	return res;
-}
-
-/* Set the session pointer in a session object */
-static void set_resume_callbacks(gnutls_session_t session, struct cnxctx * conn)
-{
-	TRACE_ENTRY("%p", conn);
-	
-	gnutls_db_set_retrieve_function(session, sr_fetch);
-	gnutls_db_set_remove_function  (session, sr_remove);
-	gnutls_db_set_store_function   (session, sr_store);
-	gnutls_db_set_ptr              (session, conn->cc_sctps_data.sess_store);
-	
-	return;
-}
-
-/* The handshake is made in parallel in several threads to speed up */
-static void * handshake_resume_th(void * arg)
-{
-	struct sctps_ctx * ctx = (struct sctps_ctx *) arg;
-	TRACE_ENTRY("%p", arg);
-	
-	/* Set the thread name */
-	{
-		char buf[48];
-		snprintf(buf, sizeof(buf), "Handshake resume (%hu@%d)", ctx->strid, ctx->parent->cc_socket);
-		fd_log_threadname ( buf );
-	}
-	
-	TRACE_DEBUG(FULL, "Starting TLS resumed handshake on stream %hu", ctx->strid);
-	CHECK_GNUTLS_DO( gnutls_handshake( ctx->session ), return NULL);
-			
-	if (TRACE_BOOL(FULL)) {
-		int resumed = gnutls_session_is_resumed(ctx->session);
-		if (resumed) {
-			fd_log_debug("Session was resumed successfully on stream %hu (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent));
-		} else {
-			fd_log_debug("Session was NOT resumed (full handshake) on stream %hu (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent));
-		}
-	}
-			
-	/* Finish */
-	return arg;
-}
-
-
-/*************************************************************/
-/*                     Exported functions                    */
-/*************************************************************/
-
-/* Initialize the wrapper for the connection */
-int fd_sctps_init(struct cnxctx * conn)
-{
-	uint16_t i;
-	
-	TRACE_ENTRY("%p", conn);
-	CHECK_PARAMS( conn && (conn->cc_sctp_para.pairs > 1) && (!conn->cc_sctps_data.array) );
-	
-	/* First, alloc the array and initialize the non-TLS data */
-	CHECK_MALLOC( conn->cc_sctps_data.array = calloc(conn->cc_sctp_para.pairs, sizeof(struct sctps_ctx))  );
-	for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
-		conn->cc_sctps_data.array[i].parent = conn;
-		conn->cc_sctps_data.array[i].strid  = i;
-		CHECK_FCT( fd_fifo_new(&conn->cc_sctps_data.array[i].raw_recv) );
-	}
-	
-	/* Set push/pull functions in the master session, using fifo in array[0] */
-	set_sess_transport(conn->cc_tls_para.session, &conn->cc_sctps_data.array[0]);
-	
-	/* For server side, we also initialize the resuming capabilities */
-	if (conn->cc_tls_para.mode == GNUTLS_SERVER) {
-		
-		/* Prepare the store for sessions data */
-		CHECK_FCT( store_init(conn) );
-		
-		/* Set the callbacks for resuming in the master session */
-		set_resume_callbacks(conn->cc_tls_para.session, conn);
-	}
-
-	/* Start the demux thread */
-	CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, demuxer, conn ) );
-	
-	return 0;
-}
-
-/* Handshake other streams, after full handshake on the master session */
-int fd_sctps_handshake_others(struct cnxctx * conn, char * priority, void * alt_creds)
-{
-	uint16_t i;
-	int errors = 0;
-	gnutls_datum_t 	master_data;
-	
-	TRACE_ENTRY("%p %p", conn, priority);
-	CHECK_PARAMS( conn && (conn->cc_sctp_para.pairs > 1) && conn->cc_sctps_data.array );
-
-	/* Server side: we set all the parameters, the resume callback will take care of resuming the session */
-	/* Client side: we duplicate the parameters of the master session, then set the transport pointer */
-	
-	/* For client side, retrieve the master session parameters */
-	if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
-		CHECK_GNUTLS_DO( gnutls_session_get_data2(conn->cc_tls_para.session, &master_data), return ENOMEM );
-	}
-	
-	/* Initialize the session objects and start the handshake in a separate thread */
-	for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
-		/* Set credentials and priority */
-		CHECK_FCT( fd_tls_prepare(&conn->cc_sctps_data.array[i].session, conn->cc_tls_para.mode, priority, alt_creds) );
-		
-		/* For the client, copy data from master session; for the server, set session resuming pointers */
-		if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
-			CHECK_GNUTLS_DO( gnutls_session_set_data(conn->cc_sctps_data.array[i].session, master_data.data, master_data.size), return ENOMEM );
-		} else {
-			set_resume_callbacks(conn->cc_sctps_data.array[i].session, conn);
-		}
-		
-		/* Set transport parameters */
-		set_sess_transport(conn->cc_sctps_data.array[i].session, &conn->cc_sctps_data.array[i]);
-		
-		/* Start the handshake thread */
-		CHECK_POSIX( pthread_create( &conn->cc_sctps_data.array[i].thr, NULL, handshake_resume_th, &conn->cc_sctps_data.array[i] ) );
-	}
-	
-	/* We can now release the memory of master session data if any */
-	if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
-		gnutls_free(master_data.data);
-	}
-	
-	/* Now wait for all handshakes to finish */
-	for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
-		void * ret;
-		CHECK_POSIX( pthread_join(conn->cc_sctps_data.array[i].thr, &ret) );
-		if (ret == NULL) {
-			errors++; /* Handshake failed on this stream */
-		}
-	}
-	
-	return errors ? ENOTCONN : 0;
-}
-
-/* Receive messages from all stream pairs */
-int fd_sctps_startthreads(struct cnxctx * conn)
-{
-	uint16_t i;
-	
-	TRACE_ENTRY("%p", conn);
-	CHECK_PARAMS( conn && conn->cc_sctps_data.array );
-	
-	for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
-		
-		/* Start the decipher thread */
-		CHECK_POSIX( pthread_create( &conn->cc_sctps_data.array[i].thr, NULL, decipher, &conn->cc_sctps_data.array[i] ) );
-	}
-	return 0;
-}
-
-/* Stop all receiver threads */
-void fd_sctps_stopthreads(struct cnxctx * conn)
-{
-	uint16_t i;
-	
-	TRACE_ENTRY("%p", conn);
-	CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return );
-	
-	for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
-		CHECK_FCT_DO( fd_thr_term(&conn->cc_sctps_data.array[i].thr), /* continue */ );
-	}
-	return;
-}
-
-static void * bye_th(void * arg)
-{
-	struct sctps_ctx * ctx = (struct sctps_ctx *) arg;
-	TRACE_ENTRY("%p", arg);
-	
-	/* Set the thread name */
-	{
-		char buf[48];
-		snprintf(buf, sizeof(buf), "gnutls_bye (%hu@%d)", ctx->strid, ctx->parent->cc_socket);
-		fd_log_threadname ( buf );
-	}
-	
-	CHECK_GNUTLS_DO( gnutls_bye(ctx->session, GNUTLS_SHUT_RDWR), /* Continue */ );
-			
-	/* Finish */
-	return arg;
-}
-
-
-
-/* Destroy a wrapper context */
-void fd_sctps_destroy(struct cnxctx * conn)
-{
-	uint16_t i;
-	
-	CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return );
-	
-	/* Terminate all receiving threads in case we did not do it yet */
-	fd_sctps_stopthreads(conn);
-	
-	/* End all TLS sessions, in parallel */
-	for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
-		CHECK_POSIX_DO( pthread_create( &conn->cc_sctps_data.array[i].thr, NULL, bye_th, &conn->cc_sctps_data.array[i] ), break );
-	}
-	for (--i; i > 0; --i) {
-		CHECK_POSIX_DO( pthread_join( conn->cc_sctps_data.array[i].thr, NULL ), continue );
-	}
-skip:	
-	/* Now, stop the demux thread */
-	CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
-	
-	/* Free remaining data in the array */
-	for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
-		fd_event_destroy( &conn->cc_sctps_data.array[i].raw_recv, free );
-		free(conn->cc_sctps_data.array[i].partial.buf);
-		if (i > 0)
-			gnutls_deinit(conn->cc_sctps_data.array[i].session);
-	}
-	
-	/* Free the array itself now */
-	free(conn->cc_sctps_data.array);
-	conn->cc_sctps_data.array = NULL;
-	
-	/* Delete the store of sessions */
-	store_destroy(conn);
-	
-	return ;
-}
Index: freeDiameter/server.c
===================================================================
--- freeDiameter/server.c	(revision 29)
+++ freeDiameter/server.c	(revision 20)
@@ -36,199 +36,149 @@
 #include "fD.h"
 
-/* Server (listening) part of the daemon */
-
-struct fd_list		FD_SERVERS = FD_LIST_INITIALIZER(FD_SERVERS);	/* The list of all server objects */
-/* We don't need to protect this list, it is only accessed from the main daemon thread. */
-
-/* Servers information */
+/* This file contains the server (listening) part of the daemon */
+
+struct fd_list		FD_SERVERS = FD_LIST_INITIALIZER(FD_SERVERS);	/* The list of all server sockets */
+/* We don't need to protect this list, it is only accessed from the main thread. */
+
+/* Server (listening socket) information */
 struct server {
 	struct fd_list	chain;		/* link in the FD_SERVERS list */
 
-	struct cnxctx *	conn;		/* server connection context (listening socket) */
+	int 		socket;		/* server socket, or <= 0 */
+	
 	int 		proto;		/* IPPROTO_TCP or IPPROTO_SCTP */
 	int 		secur;		/* TLS is started immediatly after connection ? */
 	
-	pthread_t	thr;		/* The thread listening for new connections */
-	int		status;		/* 0 : not created; 1 : running; 2 : terminated */
-	
-	struct fd_list	clients;	/* List of clients connected to this server, not yet identified */
-	pthread_mutex_t	clients_mtx;	/* Mutex to protect the list of clients */
+	pthread_t	serv_thr;	/* The thread listening for new connections */
+	int		serv_status;	/* 0 : not created; 1 : running; 2 : terminated */
+	
+	pthread_mutex_t	clients_mtx;	/* Mutex to protect the list of clients connected to the thread */
+	struct fd_list	clients;	/* The list of clients connecting to this server, which information is not yet known */
+	
+	char *		serv_name;	/* A string to identify this server */
 };
 
-/* Client information (connecting peer for which we don't have the CER yet) */
+/* Client (connected remote endpoint, not received CER yet) information */
 struct client {
 	struct fd_list	 chain;	/* link in the server's list of clients */
-	struct cnxctx	*conn;	/* Parameters of the connection */
-	struct timespec	 ts;	/* Deadline for receiving CER (after INCNX_TIMEOUT) */
-	pthread_t	 thr; 	/* connection state machine */
+	
+	struct cnxctx	*conn;	/* Parameters of the connection; sends its events to the ev fifo bellow */
+	
+	struct timespec	 ts;	/* Delay for receiving CER: INCNX_TIMEOUT */
+	struct fifo	*ev;	/* Events of the connection -- allowed: TIMEOUT, ERROR (cnx, tls), MSG_RCV (CER, other=>error) */
+	
+	pthread_t	 cli_thr; /* connection state machine (simplified PSM) */
 };
 
-
-/* Dump all servers information */
-void fd_servers_dump()
-{
-	struct fd_list * li, *cli;
-	
-	fd_log_debug("Dumping servers list :\n");
-	for (li = FD_SERVERS.next; li != &FD_SERVERS; li = li->next) {
-		struct server * s = (struct server *)li;
-		fd_log_debug("  Serv %p '%s': %s, %s, %s\n", 
-				s, fd_cnx_getid(s->conn), 
-				IPPROTO_NAME( s->proto ),
-				s->secur ? "Secur" : "NotSecur",
-				(s->status == 0) ? "Thread not created" :
-				((s->status == 1) ? "Thread running" :
-				((s->status == 2) ? "Thread terminated" :
-							  "Thread status unknown")));
-		/* Dump the client list of this server */
-		(void) pthread_mutex_lock(&s->clients_mtx);
-		for (cli = s->clients.next; cli != &s->clients; cli = cli->next) {
-			struct client * c = (struct client *)cli;
-			char bufts[128];
-			fd_log_debug("     Connected: '%s' (timeout: %s)\n",
-					fd_cnx_getid(c->conn),
-					fd_log_time(&c->ts, bufts, sizeof(bufts)));
+/* Parameter for the thread handling the new connected client, to avoid bloking the server thread */
+struct cli_fast {
+	struct server * serv;
+	int		sock;
+	sSS		ss;
+	socklen_t	sslen;
+};
+
+
+/* This thread is called when a new client had just connected */
+static void * handle_client_fast(void * arg)
+{
+	struct cli_fast * cf = arg;
+	struct client * c = NULL;
+	
+	/* Name the current thread */
+	ASSERT(arg);
+	{
+		char addr[128];
+		int offset = snprintf(addr, sizeof(addr), "Srv %d/Cli %d : ", cf->serv->socket, cf->sock);
+		int rc = getnameinfo((sSA *)&cf->ss, sizeof(sSS), addr + offset, sizeof(addr) - offset, NULL, 0, 0);
+		if (rc)
+			memcpy(addr + offset, gai_strerror(rc), sizeof(addr) - offset);
+		
+		if (TRACE_BOOL(INFO)) {
+			fd_log_debug( "New connection %s, sock %d, from '%s'\n", cf->serv->serv_name, cf->sock, addr + offset);
 		}
-		(void) pthread_mutex_unlock(&s->clients_mtx);
-	}
-}
-
-
-/* The state machine to handle incoming connection before the remote peer is identified */
-static void * client_sm(void * arg)
-{
-	struct client * c = arg;
-	struct server * s = NULL;
-	uint8_t       * buf = NULL;
-	size_t 		bufsz;
-	struct msg    * msg = NULL;
-	struct msg_hdr *hdr = NULL;
-	
-	TRACE_ENTRY("%p", c);
-	
-	CHECK_PARAMS_DO(c && c->conn && c->chain.head, goto fatal_error );
-	
-	s = c->chain.head->o;
-	
-	/* Name the current thread */
-	fd_log_threadname ( fd_cnx_getid(c->conn) );
-	
-	/* Handshake if we are a secure server port, or start clear otherwise */
-	if (s->secur) {
-		int ret = fd_cnx_handshake(c->conn, GNUTLS_SERVER, NULL, NULL);
-		if (ret != 0) {
-			if (TRACE_BOOL(INFO)) {
-				fd_log_debug("TLS handshake failed for client '%s', connection aborted.\n", fd_cnx_getid(c->conn));
-			}
-			goto cleanup;
-		}
-	} else {
-		CHECK_FCT_DO( fd_cnx_start_clear(c->conn, 0), goto cleanup );
-	}
-	
-	/* Set the timeout to receive the first message */
-	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &c->ts), goto fatal_error );
-	c->ts.tv_sec += INCNX_TIMEOUT;
-	
-	/* Receive the first Diameter message on the connection -- cleanup in case of timeout */
-	CHECK_FCT_DO( fd_cnx_receive(c->conn, &c->ts, &buf, &bufsz), goto cleanup );
-	
-	TRACE_DEBUG(FULL, "Received %zdb from new client '%s'", bufsz, fd_cnx_getid(c->conn));
-	
-	/* Try parsing this message */
-	CHECK_FCT_DO( fd_msg_parse_buffer( &buf, bufsz, &msg ), /* Parsing failed */ goto cleanup );
-	
-	/* We expect a CER, it must parse with our dictionary and rules */
-	CHECK_FCT_DO( fd_msg_parse_rules( msg, fd_g_config->cnf_dict, NULL ), /* Parsing failed -- trace details ? */ goto cleanup );
-	
-	if (TRACE_BOOL(FULL)) {
-		fd_log_debug("Received Diameter message from new client '%s':\n", fd_cnx_getid(c->conn));
-		fd_msg_dump_walk(FULL, msg);
-	}
-	
-	/* Now check we received a CER */
-	CHECK_FCT_DO( fd_msg_hdr ( msg, &hdr ), goto fatal_error );
-	CHECK_PARAMS_DO( (hdr->msg_appl == 0) && (hdr->msg_flags & CMD_FLAG_REQUEST) && (hdr->msg_code == CC_CAPABILITIES_EXCHANGE),
-		{ fd_log_debug("Connection '%s', expecting CER, received something else, closing...\n", fd_cnx_getid(c->conn)); goto cleanup; } );
-	
-	/* Finally, pass the information to the peers module which will handle it next */
-	pthread_cleanup_push((void *)fd_cnx_destroy, c->conn);
-	pthread_cleanup_push((void *)fd_msg_free, msg);
-	CHECK_FCT_DO( fd_peer_handle_newCER( &msg, &c->conn ), goto cleanup );
-	pthread_cleanup_pop(0);
-	pthread_cleanup_pop(0);
-	
-	/* The end, we cleanup the client structure */
-cleanup:
-	/* Unlink the client structure */
-	CHECK_POSIX_DO( pthread_mutex_lock(&s->clients_mtx), goto fatal_error );
-	fd_list_unlink( &c->chain );
-	CHECK_POSIX_DO( pthread_mutex_unlock(&s->clients_mtx), goto fatal_error );
-	
-	/* Destroy the connection object if present */
-	if (c->conn)
-		fd_cnx_destroy(c->conn);
-	
-	/* Cleanup the received buffer if any */
-	free(buf);
-	
-	/* Cleanup the parsed message if any */
-	if (msg) {
-		CHECK_FCT_DO( fd_msg_free(msg), /* continue */);
-	}
-	
-	/* Detach the thread, cleanup the client structure */
+	
+		fd_log_threadname ( addr );
+	}
+	
+	/* Create a client structure */
+	CHECK_MALLOC_DO( c = malloc(sizeof(struct client)), goto early_error );
+	memset(c, 0, sizeof(struct client));
+	fd_list_init(&c->chain, c);
+	c->cli_thr = pthread_self();
+	
+	/* Create the connection context */
+	CHECK_MALLOC_DO( c->conn = fd_cnx_init(cf->sock, cf->serv->proto), goto early_error );
+	
+	/* In case we are a secure server, handshake now */
+	if (cf->serv->secur) {
+		
+		TODO("Continue");
+	}
+	
+	/* Save the client in the list */
+	CHECK_POSIX_DO( pthread_mutex_lock( &cf->serv->clients_mtx ), goto early_error );
+	fd_list_insert_before(&cf->serv->clients, &c->chain);
+	CHECK_POSIX_DO( pthread_mutex_unlock( &cf->serv->clients_mtx ), goto error );
+	
+	
+	
+	
+early_error:
+	TRACE_DEBUG(INFO, "Thread is detaching to die");
 	pthread_detach(pthread_self());
+	shutdown(cf->sock, SHUT_RDWR);
+	free(cf);
 	free(c);
+error:	
+	TRACE_DEBUG(INFO, "Thread is terminating");
+	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), );
 	return NULL;
-	
-fatal_error:	/* This has effect to terminate the daemon */
-	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
-	return NULL;
-}
-
-/* The thread managing a server */
+}
+
+/* The thread for the server */
 static void * serv_th(void * arg)
 {
-	struct server *s = (struct server *)arg;
-	
-	CHECK_PARAMS_DO(s, goto error);
-	fd_log_threadname ( fd_cnx_getid(s->conn) );
-	s->status = 1;
+	struct server *sv = (struct server *)arg;
+	struct cli_fast cf;
+	
+	CHECK_PARAMS_DO(sv, goto error);
+	fd_log_threadname ( sv->serv_name );
+	sv->serv_status = 1;
+	
+	memset(&cf, 0, sizeof(struct cli_fast));
+	cf.serv = sv;
+	
 	
 	/* Accept incoming connections */
-	CHECK_FCT_DO( fd_cnx_serv_listen(s->conn), goto error );
+	CHECK_SYS_DO(  listen(sv->socket, 5), goto error );
 	
 	do {
-		struct client * c = NULL;
-		struct cnxctx * conn = NULL;
+		struct cli_fast * ncf;
+		pthread_t	  thr;
+		
+		/* Re-init socket size */
+		cf.sslen = sizeof(sSS);
 		
 		/* Wait for a new client */
-		CHECK_MALLOC_DO( conn = fd_cnx_serv_accept(s->conn), goto error );
+		CHECK_SYS_DO( cf.sock = accept(sv->socket, (sSA *)&cf.ss, &cf.sslen), goto error );
 		
 		TRACE_DEBUG(FULL, "New connection accepted");
 		
-		/* Create a client structure */
-		CHECK_MALLOC_DO( c = malloc(sizeof(struct client)), goto error );
-		memset(c, 0, sizeof(struct client));
-		fd_list_init(&c->chain, c);
-		c->conn = conn;
-		
-		/* Save the client in the list */
-		CHECK_POSIX_DO( pthread_mutex_lock( &s->clients_mtx ), goto error );
-		fd_list_insert_before(&s->clients, &c->chain);
-		CHECK_POSIX_DO( pthread_mutex_unlock( &s->clients_mtx ), goto error );
-
-		/* Start the client thread */
-		CHECK_POSIX_DO( pthread_create( &c->thr, NULL, client_sm, c ), goto error );
+		/* Create the copy for the client thread */
+		CHECK_MALLOC_DO( ncf = malloc(sizeof(struct cli_fast)), goto error );
+		memcpy(ncf, &cf, sizeof(struct cli_fast));
+		
+		/* Create the thread to handle the new incoming connection */
+		CHECK_POSIX_DO( pthread_create( &thr /* we don't use it, but NULL is not standard */, NULL, handle_client_fast, ncf), goto error );
 		
 	} while (1);
 	
 error:	
-	if (s)
-		s->status = 2;
+	if (sv)
+		sv->serv_status = 2;
 	/* Send error signal to the daemon */
 	TRACE_DEBUG(INFO, "An error occurred in server module! Thread is terminating...");
-	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
+	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), );
 
 	return NULL;
@@ -237,7 +187,14 @@
 
 /* Create a new server structure */
-static struct server * new_serv( int proto, int secur )
-{
+static struct server * new_serv( int proto, int secur, int socket )
+{
+	char buf[32];
+	char * sn = NULL;
 	struct server * new;
+	
+	/* Create the server debug name */
+	buf[sizeof(buf) - 1] = '\0';
+	snprintf(buf, sizeof(buf) - 1, "Serv %d (%s%s)", socket, IPPROTO_NAME( proto ),	secur ? "s" : "");
+	CHECK_MALLOC_DO( sn = strdup(buf), return NULL );
 	
 	/* New server structure */
@@ -246,4 +203,5 @@
 	memset(new, 0, sizeof(struct server));
 	fd_list_init(&new->chain, new);
+	new->socket = socket;
 	new->proto = proto;
 	new->secur = secur;
@@ -251,5 +209,29 @@
 	fd_list_init(&new->clients, new);
 	
+	new->serv_name = sn;
+	
 	return new;
+}
+
+/* Dump all servers information */
+void fd_servers_dump()
+{
+	struct fd_list * li;
+	
+	fd_log_debug("Dumping servers list :\n");
+	for (li = FD_SERVERS.next; li != &FD_SERVERS; li = li->next) {
+		struct server * sv = (struct server *)li;
+		fd_log_debug("  Serv '%s': %s(%d), %s, %s, %s\n", 
+				sv->serv_name, 
+				(sv->socket > 0) ? "Open" : "Closed", sv->socket,
+				IPPROTO_NAME( sv->proto ),
+				sv->secur ? "Secur" : "NotSecur",
+				(sv->serv_status == 0) ? "Thread not created" :
+				((sv->serv_status == 1) ? "Thread running" :
+				((sv->serv_status == 2) ? "Thread terminated" :
+							  "Thread status unknown")));
+		/* Dump the endpoints ? */
+		/* Dump the client list ? */
+	}
 }
 
@@ -257,7 +239,6 @@
 int fd_servers_start()
 {
-	struct server * s;
-	
-	int empty_conf_ep = FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints);
+	int  socket;
+	struct server * sv;
 	
 	/* SCTP */
@@ -268,19 +249,9 @@
 		
 		/* Create the server on default port */
-		CHECK_MALLOC( s = new_serv(IPPROTO_SCTP, 0) );
-		CHECK_MALLOC( s->conn = fd_cnx_serv_sctp(fd_g_config->cnf_port, FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints) ? NULL : &fd_g_config->cnf_endpoints) );
-		fd_list_insert_before( &FD_SERVERS, &s->chain );
-		CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
-		
-		/* Retrieve the list of endpoints if it was empty */
-		if (empty_conf_ep) {
-			(void) fd_cnx_getendpoints(s->conn, &fd_g_config->cnf_endpoints, NULL);
-		}
-		
-		/* Create the server on secure port */
-		CHECK_MALLOC( s = new_serv(IPPROTO_SCTP, 1) );
-		CHECK_MALLOC( s->conn = fd_cnx_serv_sctp(fd_g_config->cnf_port_tls, FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints) ? NULL : &fd_g_config->cnf_endpoints) );
-		fd_list_insert_before( &FD_SERVERS, &s->chain );
-		CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
+		CHECK_FCT( fd_sctp_create_bind_server( &socket, fd_g_config->cnf_port ) );
+		CHECK_MALLOC( sv = new_serv(IPPROTO_SCTP, 0, socket) );
+		
+		
+		
 		
 #endif /* DISABLE_SCTP */
@@ -290,55 +261,5 @@
 	if (!fd_g_config->cnf_flags.no_tcp) {
 		
-		if (empty_conf_ep) {
-			/* Bind TCP servers on [0.0.0.0] */
-			if (!fd_g_config->cnf_flags.no_ip4) {
-				
-				CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 0) );
-				CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port, AF_INET, NULL) );
-				fd_list_insert_before( &FD_SERVERS, &s->chain );
-				CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
-
-				CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 1) );
-				CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port_tls, AF_INET, NULL) );
-				fd_list_insert_before( &FD_SERVERS, &s->chain );
-				CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
-			}
-			/* Bind TCP servers on [::] */
-			if (!fd_g_config->cnf_flags.no_ip6) {
-				
-				CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 0) );
-				CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port, AF_INET6, NULL) );
-				fd_list_insert_before( &FD_SERVERS, &s->chain );
-				CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
-
-				CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 1) );
-				CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port_tls, AF_INET6, NULL) );
-				fd_list_insert_before( &FD_SERVERS, &s->chain );
-				CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
-			}
-		} else {
-			/* Create all endpoints -- check flags */
-			struct fd_list * li;
-			for (li = fd_g_config->cnf_endpoints.next; li != &fd_g_config->cnf_endpoints; li = li->next) {
-				struct fd_endpoint * ep = (struct fd_endpoint *)li;
-				sSA * sa = (sSA *) &ep->ss;
-				if (! (ep->flags & EP_FL_CONF))
-					continue;
-				if (fd_g_config->cnf_flags.no_ip4 && (sa->sa_family == AF_INET))
-					continue;
-				if (fd_g_config->cnf_flags.no_ip6 && (sa->sa_family == AF_INET6))
-					continue;
-				
-				CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 0) );
-				CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port, sa->sa_family, ep) );
-				fd_list_insert_before( &FD_SERVERS, &s->chain );
-				CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
-
-				CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 1) );
-				CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port_tls, sa->sa_family, ep) );
-				fd_list_insert_before( &FD_SERVERS, &s->chain );
-				CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
-			}
-		}
+		
 	}
 	
@@ -347,11 +268,6 @@
 
 /* Terminate all the servers */
-int fd_servers_stop()
-{
-	TODO("Not implemented");
-	
-	/* Loop on all servers */
-		/* cancel thread */
-		/* destroy server connection context */
-		/* cancel and destroy all clients */
-}
+void fd_servers_stop()
+{
+	
+}
Index: eeDiameter/tcp.c
===================================================================
--- freeDiameter/tcp.c	(revision 25)
+++ 	(revision )
@@ -1,165 +1,0 @@
-/*********************************************************************************************************
-* Software License Agreement (BSD License)                                                               *
-* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
-*													 *
-* Copyright (c) 2009, WIDE Project and NICT								 *
-* All rights reserved.											 *
-* 													 *
-* Redistribution and use of this software in source and binary forms, with or without modification, are  *
-* permitted provided that the following conditions are met:						 *
-* 													 *
-* * Redistributions of source code must retain the above 						 *
-*   copyright notice, this list of conditions and the 							 *
-*   following disclaimer.										 *
-*    													 *
-* * Redistributions in binary form must reproduce the above 						 *
-*   copyright notice, this list of conditions and the 							 *
-*   following disclaimer in the documentation and/or other						 *
-*   materials provided with the distribution.								 *
-* 													 *
-* * Neither the name of the WIDE Project or NICT nor the 						 *
-*   names of its contributors may be used to endorse or 						 *
-*   promote products derived from this software without 						 *
-*   specific prior written permission of WIDE Project and 						 *
-*   NICT.												 *
-* 													 *
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
-* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
-* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
-* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
-* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
-*********************************************************************************************************/
-
-#include "fD.h"
-#include "cnxctx.h"
-
-#include <netinet/tcp.h>
-#include <netinet/ip6.h>
-#include <sys/socket.h>
-
-/* Set the socket options for TCP sockets, before bind is called */
-static int fd_tcp_setsockopt(int family, int sk)
-{
-	int ret = 0;
-	int opt;
-	
-	/* Clear the NODELAY option in case it was set, as requested by rfc3539#section-3.2 */
-	/* Note that this is supposed to be the default, so we could probably remove this call ... */
-	opt = 0;
-	ret = setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
-	if (ret != 0) {
-		ret = errno;
-		TRACE_DEBUG(INFO, "Unable to set the socket TCP_NODELAY option: %s", strerror(ret));
-		return ret;
-	}
-	
-	/* Under Linux, we may also set the TCP_CONGESTION option to one of the following strings:
-	    - reno (default)
-	    - bic
-	    - cubic
-	    - highspeed
-	    - htcp
-	    - hybla
-	    - illinois
-	    - lp
-	    - scalable
-	    - vegas
-	    - veno
-	    - westwood
-	    - yeah
-	*/
-	
-	/* In case of v6 address, force the v6only option, we use a different socket for v4 */
-	#ifdef IPV6_V6ONLY
-	if (family == AF_INET6) {
-		opt = 1;
-		CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)));
-	}
-	#endif /* IPV6_V6ONLY */
-	
-	
-	/* There are also others sockopt that can be set, but nothing useful for us AFAICT */
-	
-	return 0;
-}
-
-/* Create a socket server and bind it */
-int fd_tcp_create_bind_server( int * sock, sSA * sa, socklen_t salen )
-{
-	TRACE_ENTRY("%p %p %d", sock, sa, salen);
-	
-	CHECK_PARAMS(  sock && sa  );
-	
-	/* Create the socket */
-	CHECK_SYS(  *sock = socket(sa->sa_family, SOCK_STREAM, IPPROTO_TCP)  );
-
-	/* Set the socket options */
-	CHECK_FCT(  fd_tcp_setsockopt(sa->sa_family, *sock)  );
-	
-	/* Bind the socket */
-	CHECK_SYS(  bind( *sock, sa, salen )  );
-			
-	/* We're done */
-	return 0;
-}
-
-/* Allow clients connections on server sockets */
-int fd_tcp_listen( int sock )
-{
-	TRACE_ENTRY("%d", sock);
-	CHECK_SYS( listen(sock, 5) );
-	return 0;
-}
-
-/* Create a client socket and connect to remote server */
-int fd_tcp_client( int *sock, sSA * sa, socklen_t salen )
-{
-	TRACE_ENTRY("%p %p %d", sock, sa, salen);
-	CHECK_PARAMS( sock && sa && salen );
-	
-	/* Create the socket */
-	CHECK_SYS(  *sock = socket(sa->sa_family, SOCK_STREAM, IPPROTO_TCP)  );
-	
-	/* Cleanup if we are cancelled */
-	pthread_cleanup_push(fd_cleanup_socket, sock);
-	
-	/* Set the socket options */
-	CHECK_FCT(  fd_tcp_setsockopt(sa->sa_family, *sock)  );
-	
-	TRACE_DEBUG_sSA(FULL, "Attempting TCP connection with peer: ", sa, NI_NUMERICHOST | NI_NUMERICSERV, "..." );
-	
-	/* Try connecting to the remote address */
-	CHECK_SYS( connect(*sock, sa, salen) );
-	
-	/* Done! */
-	pthread_cleanup_pop(0);
-	return 0;
-}
-
-
-/* Get the local name of a TCP socket -- would be nice if it did not return "0.0.0.0"... */
-int fd_tcp_get_local_ep(int sock, sSS * ss, socklen_t *sl)
-{
-	TRACE_ENTRY("%d %p %p", sock, ss, sl);
-	CHECK_PARAMS( ss && sl );
-	
-	*sl = sizeof(sSS);
-	CHECK_SYS(getsockname(sock, (sSA *)ss, sl));
-	
-	return 0;
-}
-
-/* Get the remote name of a TCP socket */
-int fd_tcp_get_remote_ep(int sock, sSS * ss, socklen_t *sl)
-{
-	TRACE_ENTRY("%d %p %p", sock, ss, sl);
-	CHECK_PARAMS( ss && sl );
-	
-	*sl = sizeof(sSS);
-	CHECK_SYS(getpeername(sock, (sSA *)ss, sl));
-	
-	return 0;
-}
Index: freeDiameter/tests/CMakeLists.txt
===================================================================
--- freeDiameter/tests/CMakeLists.txt	(revision 29)
+++ freeDiameter/tests/CMakeLists.txt	(revision 10)
@@ -18,5 +18,4 @@
 	testsess
 	testdisp
-	testcnx
 )
 
Index: eeDiameter/tests/testcnx.c
===================================================================
--- freeDiameter/tests/testcnx.c	(revision 30)
+++ 	(revision )
@@ -1,837 +1,0 @@
-/*********************************************************************************************************
-* Software License Agreement (BSD License)                                                               *
-* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
-*													 *
-* Copyright (c) 2009, WIDE Project and NICT								 *
-* All rights reserved.											 *
-* 													 *
-* Redistribution and use of this software in source and binary forms, with or without modification, are  *
-* permitted provided that the following conditions are met:						 *
-* 													 *
-* * Redistributions of source code must retain the above 						 *
-*   copyright notice, this list of conditions and the 							 *
-*   following disclaimer.										 *
-*    													 *
-* * Redistributions in binary form must reproduce the above 						 *
-*   copyright notice, this list of conditions and the 							 *
-*   following disclaimer in the documentation and/or other						 *
-*   materials provided with the distribution.								 *
-* 													 *
-* * Neither the name of the WIDE Project or NICT nor the 						 *
-*   names of its contributors may be used to endorse or 						 *
-*   promote products derived from this software without 						 *
-*   specific prior written permission of WIDE Project and 						 *
-*   NICT.												 *
-* 													 *
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
-* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
-* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
-* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
-* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
-*********************************************************************************************************/
-
-#include "tests.h"
-
-#ifndef TEST_PORT
-#define TEST_PORT	3868
-#endif /* TEST_PORT */
-
-#ifndef GNUTLS_DEFAULT_PRIORITY
-# define GNUTLS_DEFAULT_PRIORITY "NORMAL"
-#endif /* GNUTLS_DEFAULT_PRIORITY */
-
-#ifndef GNUTLS_DEFAULT_DHBITS
-# define GNUTLS_DEFAULT_DHBITS 1024
-#endif /* GNUTLS_DEFAULT_DHBITS */
-
-
-/* The cryptographic data */
-static char ca_data[] =		"-----BEGIN CERTIFICATE-----\n"
-				"MIIEqjCCA5KgAwIBAgIJANKgDwdlDYQDMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD\n"
-				"VQQGEwJKUDEOMAwGA1UECAwFVG9reW8xEDAOBgNVBAcMB0tvZ2FuZWkxDTALBgNV\n"
-				"BAoMBFdJREUxDzANBgNVBAsMBkFBQSBXRzEfMB0GA1UEAwwWY2hhdnJvdXguY293\n"
-				"YWRkaWN0Lm9yZzEiMCAGCSqGSIb3DQEJARYTc2RlY3VnaXNAbmljdC5nby5qcDAe\n"
-				"Fw0wOTEwMDUwODUxNDRaFw0xOTEwMDMwODUxNDRaMIGUMQswCQYDVQQGEwJKUDEO\n"
-				"MAwGA1UECAwFVG9reW8xEDAOBgNVBAcMB0tvZ2FuZWkxDTALBgNVBAoMBFdJREUx\n"
-				"DzANBgNVBAsMBkFBQSBXRzEfMB0GA1UEAwwWY2hhdnJvdXguY293YWRkaWN0Lm9y\n"
-				"ZzEiMCAGCSqGSIb3DQEJARYTc2RlY3VnaXNAbmljdC5nby5qcDCCASIwDQYJKoZI\n"
-				"hvcNAQEBBQADggEPADCCAQoCggEBAM5c6w4NnngTvGNWcJzbo0Kklp+kvUNQNgGu\n"
-				"myvz826qPp07HTSyJrIcgFnuYDR0Nd130Ot9u5osqpQhHTvolxDE87Tii8i3hJSj\n"
-				"TTY9K0ZwGb4AZ6QkuyMXS1jtOY657HqjpGZqT/2Syh0i7dM/hqSXFw0SPbyq+W1H\n"
-				"SVFWa1CTkPywFWAzwdr5WKah77uZ1dxWqgPgUdcZOiIQtLRp5n3fg40Nwso5YdwS\n"
-				"64+ebBX1pkhrCQ8AGc8O61Ep1JTXcO7jqQmPgzjiN+FeostI1Dp73S3MqleTAHjR\n"
-				"hqZ77VF7nkroMM9btMHJBaxnfwc2ewULUJwnuOiGWrvMq/9Z4J8CAwEAAaOB/DCB\n"
-				"+TAdBgNVHQ4EFgQUkqpVn7N3gmiJ7X5zQ2bki+7qv4UwgckGA1UdIwSBwTCBvoAU\n"
-				"kqpVn7N3gmiJ7X5zQ2bki+7qv4WhgZqkgZcwgZQxCzAJBgNVBAYTAkpQMQ4wDAYD\n"
-				"VQQIDAVUb2t5bzEQMA4GA1UEBwwHS29nYW5laTENMAsGA1UECgwEV0lERTEPMA0G\n"
-				"A1UECwwGQUFBIFdHMR8wHQYDVQQDDBZjaGF2cm91eC5jb3dhZGRpY3Qub3JnMSIw\n"
-				"IAYJKoZIhvcNAQkBFhNzZGVjdWdpc0BuaWN0LmdvLmpwggkA0qAPB2UNhAMwDAYD\n"
-				"VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAJy0XLk8j8YLSTt2/VMy9TAUx\n"
-				"esXUiZj0Ung+gkr7A1K0NnwYxDzG2adMhf13upHoydu2ErLMmD6F77x+QuY/q7nc\n"
-				"ZvO0tvcoAP6ToSDwiypU5dnTmnfkgwVwzFkNCi1sGRosEm8c/c/8MfK0I0nVdj1/\n"
-				"BIkIG7tTDVi9JvkWYl0UlSKWTZKrntVwCmscfC02DGb+GoLbO9+QmiNM5Y3yOYZ4\n"
-				"Pc7SSoKLL0rwJBmpPNs7boYsweeSuCAVu0shRfgC90odXcej2EN5ETfCuU1evXNW\n"
-				"5cA+zZsDK/nWJwxBaW0CxAHX579FElFWlK4+BnzhZRdDhmJDnN5dh4ekJGM6Lg==\n"
-				"-----END CERTIFICATE-----\n";
-				
-/* Client:
-				Certificate:
-				    Data:
-        				Version: 3 (0x2)
-        				Serial Number: 5 (0x5)
-        				Signature Algorithm: sha1WithRSAEncryption
-        				Issuer: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=chavroux.cowaddict.org/emailAddress=sdecugis@nict.go.jp
-        				Validity
-        				    Not Before: Oct 27 04:04:05 2009 GMT
-        				    Not After : Oct 25 04:04:05 2019 GMT
-        				Subject: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=client.test/emailAddress=client@test
-        				Subject Public Key Info:
-        				    Public Key Algorithm: rsaEncryption
-        				    RSA Public Key: (1024 bit)
-                				Modulus (1024 bit):
-                				    00:bd:eb:50:1e:9d:7a:cd:9d:bb:e7:bc:4e:38:4a:
-                				    b2:cc:9e:b4:89:77:01:ef:d1:c6:19:29:00:fe:ce:
-                				    3c:62:05:13:b1:8c:ff:31:7a:0f:c1:2e:4b:3c:0c:
-                				    40:1e:36:4e:76:da:0a:64:43:fc:1e:ea:0c:97:b2:
-                				    57:9c:9c:8c:90:bd:eb:23:7b:b8:b7:5c:03:ed:6f:
-                				    48:55:8a:88:08:38:c5:cd:33:b7:ab:a8:3a:6f:7f:
-                				    13:10:65:a5:50:b9:f4:8b:cc:2e:e9:79:58:a6:11:
-                				    f0:58:45:41:ef:36:b3:35:cb:14:ec:82:0c:ad:11:
-                				    6a:ea:64:ef:28:a2:6e:47:45
-                				Exponent: 65537 (0x10001)
-        				X509v3 extensions:
-        				    X509v3 Basic Constraints: 
-                				CA:FALSE
-        				    Netscape Comment: 
-                				OpenSSL Generated Certificate
-        				    X509v3 Subject Key Identifier: 
-                				BE:B3:89:4F:9D:8F:6C:20:C4:D0:3E:6A:05:11:82:50:54:49:70:A2
-        				    X509v3 Authority Key Identifier: 
-                				keyid:92:AA:55:9F:B3:77:82:68:89:ED:7E:73:43:66:E4:8B:EE:EA:BF:85
-
-				    Signature Algorithm: sha1WithRSAEncryption
-        				a3:88:f5:15:b5:ad:20:60:a1:85:19:3f:b9:5e:1e:be:31:7f:
-        				84:7a:c2:18:3a:63:6a:67:1f:46:86:4d:10:d6:1d:ad:a2:c8:
-        				0b:95:33:fa:e4:05:f4:b8:70:34:77:f7:85:6e:70:46:ac:39:
-        				54:a9:5f:ea:5e:d1:33:bb:c9:a3:42:81:41:90:25:b5:92:8b:
-        				e8:6e:3e:97:06:dd:9a:cc:29:61:34:5a:d3:1c:5d:ad:d1:a3:
-        				eb:6a:47:b4:d0:c2:17:89:e1:e2:2d:36:18:50:1a:e7:d4:fc:
-        				38:2e:47:0b:39:50:87:2f:aa:07:64:f8:9a:4d:47:01:da:10:
-        				d8:97:c7:a6:13:bc:0e:ca:63:c1:f2:09:fb:f8:6a:a4:5f:08:
-        				b5:ad:ed:4f:71:b9:89:7f:43:27:85:72:e7:8d:a8:4a:cc:f6:
-        				36:ca:8a:ae:82:b5:a8:42:41:99:87:84:7c:f0:90:fd:ca:96:
-        				37:a2:e0:d9:fa:dd:a4:c9:f1:50:b7:e5:e6:8f:af:83:8c:23:
-        				b6:20:cc:66:e3:08:60:13:02:8f:42:3a:07:91:a7:38:b2:72:
-        				16:fd:bd:a9:60:f0:e2:9f:23:f3:c0:99:e3:17:bc:00:7c:b3:
-        				89:9c:ea:fa:3e:f6:69:a1:98:c2:ec:46:da:70:b6:f9:c3:93:
-        				a7:fc:36:dd
-*/
-static char client_cert_data[] ="-----BEGIN CERTIFICATE-----\n"
-				"MIIDiTCCAnGgAwIBAgIBBTANBgkqhkiG9w0BAQUFADCBlDELMAkGA1UEBhMCSlAx\n"
-				"DjAMBgNVBAgMBVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURF\n"
-				"MQ8wDQYDVQQLDAZBQUEgV0cxHzAdBgNVBAMMFmNoYXZyb3V4LmNvd2FkZGljdC5v\n"
-				"cmcxIjAgBgkqhkiG9w0BCQEWE3NkZWN1Z2lzQG5pY3QuZ28uanAwHhcNMDkxMDI3\n"
-				"MDQwNDA1WhcNMTkxMDI1MDQwNDA1WjCBgTELMAkGA1UEBhMCSlAxDjAMBgNVBAgM\n"
-				"BVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURFMQ8wDQYDVQQL\n"
-				"DAZBQUEgV0cxFDASBgNVBAMMC2NsaWVudC50ZXN0MRowGAYJKoZIhvcNAQkBFgtj\n"
-				"bGllbnRAdGVzdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvetQHp16zZ27\n"
-				"57xOOEqyzJ60iXcB79HGGSkA/s48YgUTsYz/MXoPwS5LPAxAHjZOdtoKZEP8HuoM\n"
-				"l7JXnJyMkL3rI3u4t1wD7W9IVYqICDjFzTO3q6g6b38TEGWlULn0i8wu6XlYphHw\n"
-				"WEVB7zazNcsU7IIMrRFq6mTvKKJuR0UCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglg\n"
-				"hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O\n"
-				"BBYEFL6ziU+dj2wgxNA+agURglBUSXCiMB8GA1UdIwQYMBaAFJKqVZ+zd4Joie1+\n"
-				"c0Nm5Ivu6r+FMA0GCSqGSIb3DQEBBQUAA4IBAQCjiPUVta0gYKGFGT+5Xh6+MX+E\n"
-				"esIYOmNqZx9Ghk0Q1h2tosgLlTP65AX0uHA0d/eFbnBGrDlUqV/qXtEzu8mjQoFB\n"
-				"kCW1kovobj6XBt2azClhNFrTHF2t0aPrake00MIXieHiLTYYUBrn1Pw4LkcLOVCH\n"
-				"L6oHZPiaTUcB2hDYl8emE7wOymPB8gn7+GqkXwi1re1PcbmJf0MnhXLnjahKzPY2\n"
-				"yoqugrWoQkGZh4R88JD9ypY3ouDZ+t2kyfFQt+Xmj6+DjCO2IMxm4whgEwKPQjoH\n"
-				"kac4snIW/b2pYPDinyPzwJnjF7wAfLOJnOr6PvZpoZjC7EbacLb5w5On/Dbd\n"
-				"-----END CERTIFICATE-----\n";
-static char client_priv_data[] ="-----BEGIN RSA PRIVATE KEY-----\n"
-				"MIICXgIBAAKBgQC961AenXrNnbvnvE44SrLMnrSJdwHv0cYZKQD+zjxiBROxjP8x\n"
-				"eg/BLks8DEAeNk522gpkQ/we6gyXslecnIyQvesje7i3XAPtb0hViogIOMXNM7er\n"
-				"qDpvfxMQZaVQufSLzC7peVimEfBYRUHvNrM1yxTsggytEWrqZO8oom5HRQIDAQAB\n"
-				"AoGBAIYnsOLPby3LnC5n8AEHkyHDgdgQvsd/MSYYtuFHIZRD7dNfu+xhQru9TdvO\n"
-				"84Pj7K07/FczRuc3gUmu6wBv/UIP9To15RHZh+/n537nybGus5S4IYKVvap477To\n"
-				"0rQDf9ec27iw77gxb7moQ9Otuxwbv0h0Z+1EVLI8d8jHOq0BAkEA9YNr0R+7KXBS\n"
-				"48yT43g5HpOFkTZzNXWVdpSvYGneb56wslk5Eatp235I4uz/a7Rej5v99W0M3nSe\n"
-				"/AgHfYn75QJBAMYH/pBx/WkrLj+pPaARlNwInCIC5zUhr6B0IKCt2tvy5eyuc5sd\n"
-				"AoTFaU+cSI+ZqsRzY8jMKkonktxBg48oJ+ECQQCt4AtlqcFVkbVCm8pJGQXq/7Ni\n"
-				"qlthiwr1Vkv2TkQ4bPza8pGWT/3Cc2ePPyWN08n8jw+G11p72cAW4mDbqfN5AkEA\n"
-				"mNYKrkiLn+NnqlJf8W4gSUGL3uQGtYbuGRQHKnuDckWhFm39YzWcgAQsJvkjN1EN\n"
-				"7thvpsWLzfeE7ODTPGVtgQJATObxYJOt6rms3fAStwuXW3ET77TA1ja4XsUEe5Yu\n"
-				"JpcQOruJb9XwndqzNbL0dSUePb9gFiBCGKYOyreNTTRTmw==\n"
-				"-----END RSA PRIVATE KEY-----\n";
-				
-/* Server:
-				Certificate:
-				    Data:
-        				Version: 3 (0x2)
-        				Serial Number: 4 (0x4)
-        				Signature Algorithm: sha1WithRSAEncryption
-        				Issuer: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=chavroux.cowaddict.org/emailAddress=sdecugis@nict.go.jp
-        				Validity
-        				    Not Before: Oct 27 04:03:39 2009 GMT
-        				    Not After : Oct 25 04:03:39 2019 GMT
-        				Subject: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=serv.test/emailAddress=serv@test
-        				Subject Public Key Info:
-        				    Public Key Algorithm: rsaEncryption
-        				    RSA Public Key: (1024 bit)
-                				Modulus (1024 bit):
-                				    00:a6:f7:1c:a9:90:5b:fa:c8:f6:a3:04:0c:d0:8b:
-                				    45:c3:90:f7:2d:c2:c9:d7:bd:66:8a:7c:1c:51:89:
-                				    40:9e:cd:70:57:cb:00:47:a3:e8:76:8b:00:b3:c9:
-                				    c3:0d:b1:b9:2a:08:9f:52:92:82:d3:18:c1:d8:d1:
-                				    b8:1e:fd:71:fe:23:ec:19:e9:6d:9d:fd:ae:88:bc:
-                				    39:44:7a:37:ad:c6:88:d1:64:7c:b1:d4:3c:a9:30:
-                				    c4:de:51:02:c4:48:4f:25:3e:2f:93:ae:25:32:66:
-                				    9a:dc:f4:44:45:ff:7f:12:49:97:0d:01:8d:13:9a:
-                				    d3:8f:9e:2d:62:95:02:0a:c7
-                				Exponent: 65537 (0x10001)
-        				X509v3 extensions:
-        				    X509v3 Basic Constraints: 
-                				CA:FALSE
-        				    Netscape Comment: 
-                				OpenSSL Generated Certificate
-        				    X509v3 Subject Key Identifier: 
-                				0C:33:C4:7F:39:D0:34:FF:F8:61:A1:46:8B:49:1D:A3:57:B3:4D:58
-        				    X509v3 Authority Key Identifier: 
-                				keyid:92:AA:55:9F:B3:77:82:68:89:ED:7E:73:43:66:E4:8B:EE:EA:BF:85
-
-				    Signature Algorithm: sha1WithRSAEncryption
-        				87:f5:49:a6:04:f9:98:9a:f1:1a:68:ce:06:ae:4c:0c:08:eb:
-        				ba:98:e7:3f:df:22:7f:35:88:1d:b7:8a:f3:89:a3:68:0d:53:
-        				45:eb:23:a1:dd:6b:dc:b0:80:58:0c:10:0b:49:74:ea:a8:b6:
-        				8c:2e:c6:73:dc:7a:74:c7:59:3e:79:5a:d2:5c:15:0b:f1:d8:
-        				19:37:2a:c0:22:75:10:3f:4c:e9:a1:e0:eb:b2:9e:09:70:3d:
-        				2a:4c:fe:9c:99:36:4b:aa:6c:e1:8b:9c:aa:e1:29:1f:49:6b:
-        				14:db:12:ae:cf:68:4a:dd:03:e1:3b:ad:79:b4:54:84:1d:bb:
-        				ac:45:c4:85:f1:03:65:65:96:23:ae:e7:97:3c:5c:db:ce:55:
-        				34:5d:c3:73:ec:cd:f6:0f:a5:81:5f:c2:ab:a3:42:fa:36:7f:
-        				83:ef:db:0f:cd:62:0b:ea:d9:4f:73:35:68:5f:23:d5:0a:be:
-        				ff:7f:23:9a:af:0d:a5:f8:3e:3a:f0:63:1c:e1:d2:96:81:cf:
-        				7b:5a:6b:d0:9b:67:56:9e:aa:a9:e8:f1:6c:fb:54:2b:1a:f4:
-        				ef:16:5a:be:1d:a9:c8:d6:cc:f7:42:8c:fe:83:2c:84:8c:80:
-        				fb:1c:88:f6:35:1c:ae:43:72:fa:68:30:9c:25:8b:db:2c:84:
-        				87:76:9d:b9
-*/
-static char server_cert_data[] ="-----BEGIN CERTIFICATE-----\n"
-				"MIIDhDCCAmygAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBlDELMAkGA1UEBhMCSlAx\n"
-				"DjAMBgNVBAgMBVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURF\n"
-				"MQ8wDQYDVQQLDAZBQUEgV0cxHzAdBgNVBAMMFmNoYXZyb3V4LmNvd2FkZGljdC5v\n"
-				"cmcxIjAgBgkqhkiG9w0BCQEWE3NkZWN1Z2lzQG5pY3QuZ28uanAwHhcNMDkxMDI3\n"
-				"MDQwMzM5WhcNMTkxMDI1MDQwMzM5WjB9MQswCQYDVQQGEwJKUDEOMAwGA1UECAwF\n"
-				"VG9reW8xEDAOBgNVBAcMB0tvZ2FuZWkxDTALBgNVBAoMBFdJREUxDzANBgNVBAsM\n"
-				"BkFBQSBXRzESMBAGA1UEAwwJc2Vydi50ZXN0MRgwFgYJKoZIhvcNAQkBFglzZXJ2\n"
-				"QHRlc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKb3HKmQW/rI9qMEDNCL\n"
-				"RcOQ9y3Cyde9Zop8HFGJQJ7NcFfLAEej6HaLALPJww2xuSoIn1KSgtMYwdjRuB79\n"
-				"cf4j7BnpbZ39roi8OUR6N63GiNFkfLHUPKkwxN5RAsRITyU+L5OuJTJmmtz0REX/\n"
-				"fxJJlw0BjROa04+eLWKVAgrHAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4\n"
-				"QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQM\n"
-				"M8R/OdA0//hhoUaLSR2jV7NNWDAfBgNVHSMEGDAWgBSSqlWfs3eCaIntfnNDZuSL\n"
-				"7uq/hTANBgkqhkiG9w0BAQUFAAOCAQEAh/VJpgT5mJrxGmjOBq5MDAjrupjnP98i\n"
-				"fzWIHbeK84mjaA1TResjod1r3LCAWAwQC0l06qi2jC7Gc9x6dMdZPnla0lwVC/HY\n"
-				"GTcqwCJ1ED9M6aHg67KeCXA9Kkz+nJk2S6ps4YucquEpH0lrFNsSrs9oSt0D4Tut\n"
-				"ebRUhB27rEXEhfEDZWWWI67nlzxc285VNF3Dc+zN9g+lgV/Cq6NC+jZ/g+/bD81i\n"
-				"C+rZT3M1aF8j1Qq+/38jmq8Npfg+OvBjHOHSloHPe1pr0JtnVp6qqejxbPtUKxr0\n"
-				"7xZavh2pyNbM90KM/oMshIyA+xyI9jUcrkNy+mgwnCWL2yyEh3aduQ==\n"
-				"-----END CERTIFICATE-----\n";
-static char server_priv_data[] ="-----BEGIN RSA PRIVATE KEY-----\n"
-				"MIICXQIBAAKBgQCm9xypkFv6yPajBAzQi0XDkPctwsnXvWaKfBxRiUCezXBXywBH\n"
-				"o+h2iwCzycMNsbkqCJ9SkoLTGMHY0bge/XH+I+wZ6W2d/a6IvDlEejetxojRZHyx\n"
-				"1DypMMTeUQLESE8lPi+TriUyZprc9ERF/38SSZcNAY0TmtOPni1ilQIKxwIDAQAB\n"
-				"AoGAZv3Ddm0P79CLIt9asEFY1VvUvSuMqkGwwPfx1/HcJJkBFYapM4fN22G/Gyf3\n"
-				"47ifSWhsLtklTeXVnVMwSh14dJaJQuSEnaFnUUWfjiRbEAXZnMFwAIiaszEZbPap\n"
-				"NUNpcGl06FZrphYAMkjOVUfjCjfOZDAvL4JGpo271Zx4l0ECQQDYoFFQpBCPx0PK\n"
-				"TWUmvatXI/Amo94XkGfofbdeeI8PiAJBO5UI6rmjjIVwsJwO9dQb/IlP1/OnBeJv\n"
-				"p9YW5uixAkEAxVAOKu7mpGu0Q/K2iEUUYDX9YHf253kgkdIDF4iZk4Tcecjoxuru\n"
-				"fIWu9dMtyDVV+HT2X4cNEnO1/oS3kJII9wJBAJkdwDwiqz4lV6o/yFZ4zAoc8dsu\n"
-				"CoZXYMq5SYox5tTQit928OHLn4mVgqBjhPsiEVnyx0+zUZpmE2ZemHm5nxECQHfE\n"
-				"FBVzVYRP6+eil7E3XRrZKqc3qiLunxpkA4RxYebtKnaxwLmdOI1VB9InEQ8JcNmT\n"
-				"BUkOzJx6p+mJ3XJfchkCQQDWmbMYYJajsjlS4YpdUUj7cBSotA6vtkNVHFr0/ak/\n"
-				"S+tLkMNuruaInWizK+BKYTIJLlQDf5u5NTrw41vye5Hv\n"
-				"-----END RSA PRIVATE KEY-----\n";
-
-/* Expired:
-				Certificate:
-				    Data:
-        				Version: 3 (0x2)
-        				Serial Number: 6 (0x6)
-        				Signature Algorithm: sha1WithRSAEncryption
-        				Issuer: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=chavroux.cowaddict.org/emailAddress=sdecugis@nict.go.jp
-        				Validity
-        				    Not Before: Oct 27 04:06:35 2009 GMT
-        				    Not After : Oct 28 04:06:35 2009 GMT
-        				Subject: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=expired.test/emailAddress=expired@test
-        				Subject Public Key Info:
-        				    Public Key Algorithm: rsaEncryption
-        				    RSA Public Key: (1024 bit)
-                				Modulus (1024 bit):
-                				    00:e3:17:15:54:85:dc:cf:c7:a0:32:4a:49:7d:55:
-                				    75:9b:29:15:db:7e:87:17:d9:0e:65:44:53:d7:19:
-                				    37:27:c7:c6:fe:c6:dc:72:2b:dc:86:1a:ff:24:6c:
-                				    63:3f:75:9c:0a:14:e1:70:06:79:d4:b9:26:d4:68:
-                				    4c:28:38:ba:34:60:56:02:3d:94:55:4a:1f:4e:5a:
-                				    f0:a5:71:4c:3e:71:69:39:ad:bc:aa:55:35:fb:73:
-                				    5b:5f:6c:30:71:8e:8a:b6:a5:06:cc:ee:dd:29:c7:
-                				    52:0d:a7:9c:0f:a1:ba:52:11:e2:1b:b9:74:6b:08:
-                				    87:11:d2:ec:a9:ac:63:63:4f
-                				Exponent: 65537 (0x10001)
-        				X509v3 extensions:
-        				    X509v3 Basic Constraints: 
-                				CA:FALSE
-        				    Netscape Comment: 
-                				OpenSSL Generated Certificate
-        				    X509v3 Subject Key Identifier: 
-                				1C:AF:66:42:5B:AD:AA:A5:9B:D9:AE:3A:C1:5A:AC:2F:CC:CE:22:6C
-        				    X509v3 Authority Key Identifier: 
-                				keyid:92:AA:55:9F:B3:77:82:68:89:ED:7E:73:43:66:E4:8B:EE:EA:BF:85
-
-				    Signature Algorithm: sha1WithRSAEncryption
-        				60:8f:55:55:59:82:0f:64:cb:b8:11:c8:44:ce:bf:69:07:0d:
-        				be:c2:34:be:42:6a:78:15:39:9f:be:8a:17:d6:43:42:c9:7c:
-        				f1:6d:5d:aa:c3:1b:4d:b0:f0:b6:73:46:2a:87:cd:55:56:a3:
-        				6d:cc:de:a8:28:6a:53:85:9e:e5:68:b7:3c:f5:72:13:7b:d0:
-        				21:f2:91:49:35:e0:37:1e:28:19:d5:1b:cc:e1:32:1e:7f:b0:
-        				86:df:43:a4:47:0f:29:0b:eb:51:60:9a:f5:ca:50:f4:2d:59:
-        				cd:fc:50:9d:29:ed:45:98:de:a2:5c:d1:b5:7a:34:ad:7a:73:
-        				48:8b:a2:9b:89:8e:4a:2e:2a:04:19:d6:62:6a:0d:f0:96:f2:
-        				f0:d0:22:77:3b:7f:b1:2a:f4:3b:17:47:5e:38:07:09:65:ad:
-        				1d:ea:46:69:6a:96:b6:6b:3b:5c:cc:6e:30:d7:cb:53:69:59:
-        				c2:63:78:2b:03:d4:d4:f7:17:29:99:9a:43:ff:78:0a:af:42:
-        				c5:b3:8d:09:38:5b:30:70:28:c1:97:ab:fd:7f:87:9a:ec:f2:
-        				97:44:ff:f5:b9:41:30:d1:c6:32:98:69:34:c4:39:30:6f:e2:
-        				d3:b2:70:97:66:ee:41:f5:ae:0f:09:f0:ed:60:96:67:a9:8a:
-        				cd:d6:95:f2
-*/
-static char expired_cert_data[]="-----BEGIN CERTIFICATE-----\n"
-				"MIIDizCCAnOgAwIBAgIBBjANBgkqhkiG9w0BAQUFADCBlDELMAkGA1UEBhMCSlAx\n"
-				"DjAMBgNVBAgMBVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURF\n"
-				"MQ8wDQYDVQQLDAZBQUEgV0cxHzAdBgNVBAMMFmNoYXZyb3V4LmNvd2FkZGljdC5v\n"
-				"cmcxIjAgBgkqhkiG9w0BCQEWE3NkZWN1Z2lzQG5pY3QuZ28uanAwHhcNMDkxMDI3\n"
-				"MDQwNjM1WhcNMDkxMDI4MDQwNjM1WjCBgzELMAkGA1UEBhMCSlAxDjAMBgNVBAgM\n"
-				"BVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURFMQ8wDQYDVQQL\n"
-				"DAZBQUEgV0cxFTATBgNVBAMMDGV4cGlyZWQudGVzdDEbMBkGCSqGSIb3DQEJARYM\n"
-				"ZXhwaXJlZEB0ZXN0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjFxVUhdzP\n"
-				"x6AySkl9VXWbKRXbfocX2Q5lRFPXGTcnx8b+xtxyK9yGGv8kbGM/dZwKFOFwBnnU\n"
-				"uSbUaEwoOLo0YFYCPZRVSh9OWvClcUw+cWk5rbyqVTX7c1tfbDBxjoq2pQbM7t0p\n"
-				"x1INp5wPobpSEeIbuXRrCIcR0uyprGNjTwIDAQABo3sweTAJBgNVHRMEAjAAMCwG\n"
-				"CWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV\n"
-				"HQ4EFgQUHK9mQlutqqWb2a46wVqsL8zOImwwHwYDVR0jBBgwFoAUkqpVn7N3gmiJ\n"
-				"7X5zQ2bki+7qv4UwDQYJKoZIhvcNAQEFBQADggEBAGCPVVVZgg9ky7gRyETOv2kH\n"
-				"Db7CNL5CangVOZ++ihfWQ0LJfPFtXarDG02w8LZzRiqHzVVWo23M3qgoalOFnuVo\n"
-				"tzz1chN70CHykUk14DceKBnVG8zhMh5/sIbfQ6RHDykL61FgmvXKUPQtWc38UJ0p\n"
-				"7UWY3qJc0bV6NK16c0iLopuJjkouKgQZ1mJqDfCW8vDQInc7f7Eq9DsXR144Bwll\n"
-				"rR3qRmlqlrZrO1zMbjDXy1NpWcJjeCsD1NT3FymZmkP/eAqvQsWzjQk4WzBwKMGX\n"
-				"q/1/h5rs8pdE//W5QTDRxjKYaTTEOTBv4tOycJdm7kH1rg8J8O1glmepis3WlfI=\n"
-				"-----END CERTIFICATE-----\n";
-static char expired_priv_data[]="-----BEGIN RSA PRIVATE KEY-----\n"
-				"MIICXgIBAAKBgQDjFxVUhdzPx6AySkl9VXWbKRXbfocX2Q5lRFPXGTcnx8b+xtxy\n"
-				"K9yGGv8kbGM/dZwKFOFwBnnUuSbUaEwoOLo0YFYCPZRVSh9OWvClcUw+cWk5rbyq\n"
-				"VTX7c1tfbDBxjoq2pQbM7t0px1INp5wPobpSEeIbuXRrCIcR0uyprGNjTwIDAQAB\n"
-				"AoGASwPoDui9XYHTIGm7xwRA+kVjLAOq+qy//aHJlEeHGcP7r1PfpHNqwH4QhGat\n"
-				"jlv6dLYbFld9TVDwS8A8UBkVIPLWnCysd5tF2A4C5akx6ouW6HliW/JheYrgl8AV\n"
-				"PVeR3bm91UbnpC0ABVlw87jp1Ovyr60Suo4jsoJz+CyTa2ECQQD0LJWpnwn1jIlR\n"
-				"DGkLi7F3E70JJcdhTWzBjGFD+Na+/2ZO0MKLhK+O1WUkKa0oi+e5P1JOnGIpTI8c\n"
-				"BJOO415RAkEA7hauapYuqGI/auSPH8/nFB5z1G94RTxo2a5THKcG5MqS/8N3ubFj\n"
-				"i2PPS0lEYVjqoHEsZUsMnDmXp6KDKMAfnwJBAIp+T1UqM8fmsmwaEerOjRXxSCNM\n"
-				"Hk5+T9Vn/jNDjOpAipLhrbbcx4bIWtmsGd8Jm6Fi3RhhcvvhxLorjlZZeEECQQCf\n"
-				"IaPD88sNmlUewdLzhUbCiLQMadCuHflKfRxpyy1tYAQuVFxCTdDlynkzra25ju+K\n"
-				"+vmcXjP4evnk/lbBtt+rAkEAgOr4Apgs3nMppngPV5yFx0NDqH2n8PlEAM1Il4Qs\n"
-				"IuuK18v0KwlUGAfEEmCiNh1e1qkLmD0CnI2QjYAjcLQUhw==\n"
-				"-----END RSA PRIVATE KEY-----\n";
-
-struct fd_list eps = FD_LIST_INITIALIZER(eps);
-
-struct connect_flags {
-	int	proto;
-};
-
-void * connect_thr(void * arg)
-{
-	struct connect_flags * cf = arg;
-	struct cnxctx * cnx = NULL;
-	
-	fd_log_threadname ( "testcnx:connect" );
-	
-	/* Connect to the server */
-	switch (cf->proto) {
-		case IPPROTO_TCP:
-			{
-				struct fd_endpoint * ep = (struct fd_endpoint *)(eps.next);
-				cnx = fd_cnx_cli_connect_tcp( &ep->sa, sSSlen(&ep->ss) );
-				CHECK( 1, cnx ? 1 : 0 );
-			}
-			break;
-#ifndef DISABLE_SCTP
-		case IPPROTO_SCTP:
-			{
-				cnx = fd_cnx_cli_connect_sctp(0, TEST_PORT, &eps);
-				CHECK( 1, cnx ? 1 : 0 );
-			}
-			break;
-#endif /* DISABLE_SCTP */
-		default:
-			CHECK( 0, 1 );
-	}
-	
-	/* exit */
-	return cnx;
-}
-
-struct handshake_flags {
-	struct cnxctx * cnx;
-	gnutls_certificate_credentials_t	creds;
-	int ret;
-};
-
-void * handshake_thr(void * arg)
-{
-	struct handshake_flags * hf = arg;
-	fd_log_threadname ( "testcnx:handshake" );
-	hf->ret = fd_cnx_handshake(hf->cnx, GNUTLS_CLIENT, NULL, hf->creds);
-	return NULL;
-}
-	
-void * destroy_thr(void * arg)
-{
-	struct cnxctx * cnx = arg;
-	fd_log_threadname ( "testcnx:destroy" );
-	fd_cnx_destroy(cnx);
-	return NULL;
-}
-	
-/* Main test routine */
-int main(int argc, char *argv[])
-{
-	gnutls_datum_t ca 		= { ca_data, 		sizeof(ca_data) 	  };
-	gnutls_datum_t server_cert 	= { server_cert_data, 	sizeof(server_cert_data)  };
-	gnutls_datum_t server_priv 	= { server_priv_data, 	sizeof(server_priv_data)  };
-	gnutls_datum_t client_cert	= { client_cert_data, 	sizeof(client_cert_data)  };
-	gnutls_datum_t client_priv 	= { client_priv_data, 	sizeof(client_priv_data)  };
-	gnutls_datum_t expired_cert 	= { expired_cert_data, 	sizeof(expired_cert_data) };
-	gnutls_datum_t expired_priv 	= { expired_priv_data, 	sizeof(expired_priv_data) };
-	
-	struct cnxctx * listener;
-#ifndef DISABLE_SCTP
-	struct cnxctx * listener_sctp;
-#endif /* DISABLE_SCTP */
-	struct cnxctx * server_side;
-	struct cnxctx * client_side;
-	pthread_t thr;
-	int ret, i;
-	uint8_t * cer_buf;
-	size_t 	  cer_sz;
-	uint8_t * rcv_buf;
-	size_t 	  rcv_sz;
-	
-	/* First, initialize the daemon modules */
-	INIT_FD();
-	
-	/* Set the CA parameter in the config */
-	CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( fd_g_config->cnf_sec_data.credentials,
-									 &ca,
-									 GNUTLS_X509_FMT_PEM), );
-	CHECK( 1, ret );
-	
-	/* Set the server credentials (in config) */
-	CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( fd_g_config->cnf_sec_data.credentials,
-									&server_cert,
-									&server_priv,
-									GNUTLS_X509_FMT_PEM), );
-	CHECK( GNUTLS_E_SUCCESS, ret );
-	
-	/* Set the default priority */
-	CHECK_GNUTLS_DO( ret = gnutls_priority_init( &fd_g_config->cnf_sec_data.prio_cache, GNUTLS_DEFAULT_PRIORITY, NULL), );
-	CHECK( GNUTLS_E_SUCCESS, ret );
-	
-	/* Set default DH params */
-	CHECK_GNUTLS_DO( ret = gnutls_dh_params_generate2( fd_g_config->cnf_sec_data.dh_cache, GNUTLS_DEFAULT_DHBITS), );
-	CHECK( GNUTLS_E_SUCCESS, ret );
-	
-	/* Initialize the server addresses */
-	{
-		struct addrinfo hints, *ai, *aip;
-		memset(&hints, 0, sizeof(hints));
-		hints.ai_flags  = AI_NUMERICSERV;
-		hints.ai_family = AF_INET;
-		CHECK( 0, getaddrinfo("localhost", _stringize(TEST_PORT), &hints, &ai) );
-		aip = ai;
-		while (aip) {
-			CHECK( 0, fd_ep_add_merge( &eps, aip->ai_addr, aip->ai_addrlen, EP_FL_DISC ));
-			aip = aip->ai_next;
-		};
-		freeaddrinfo(ai);
-	}
-	
-	/* Start the server(s) */
-	{
-		/* TCP server */
-		listener = fd_cnx_serv_tcp(TEST_PORT, 0, (struct fd_endpoint *)(eps.next));
-		CHECK( 1, listener ? 1 : 0 );
-		
-		/* Accept incoming clients */
-		CHECK( 0, fd_cnx_serv_listen(listener));
-
-#ifndef DISABLE_SCTP
-		/* SCTP server */
-		listener_sctp = fd_cnx_serv_sctp(TEST_PORT, &eps);
-		CHECK( 1, listener_sctp ? 1 : 0 );
-		
-		/* Accept incoming clients */
-		CHECK( 0, fd_cnx_serv_listen(listener_sctp));
-#endif /* DISABLE_SCTP */
-
-	}	
-	
-	/* Initialize the CER message */
-	{
-		struct msg * cer;
-		struct dict_object * model = NULL;
-		struct avp * oh;
-		union avp_value value;
-
-		/* Find the CER dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &model, ENOENT ) );
-
-		/* Create the instance */
-		CHECK( 0, fd_msg_new ( model, 0, &cer ) );
-		
-		/* Now find the Origin-Host dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &model, ENOENT ) );
-
-		/* Create the instance */
-		CHECK( 0, fd_msg_avp_new ( model, 0, &oh ) );
-		value.os.data = "Client.side";
-		value.os.len = strlen(value.os.data);
-		CHECK( 0, fd_msg_avp_setvalue ( oh, &value ) );
-		
-		/* Add the AVP */
-		CHECK( 0, fd_msg_avp_add( cer, MSG_BRW_LAST_CHILD, oh) );
-
-		#if 1
-		/* For debug: dump the object */
-		fd_log_debug("Dumping CER\n");
-		fd_msg_dump_walk(0, cer);
-		#endif
-			
-		CHECK( 0, fd_msg_bufferize( cer, &cer_buf, &cer_sz ) );
-		CHECK( 0, fd_msg_free(cer) );
-	}
-	
-	/* Simple TCP client / server test (no TLS) */
-	{
-		struct connect_flags cf;
-		
-		memset(&cf, 0, sizeof(cf));
-		cf.proto = IPPROTO_TCP;
-		
-		/* Start the client thread */
-		CHECK( 0, pthread_create(&thr, 0, connect_thr, &cf) );
-
-		/* Accept the connection of the client */
-		server_side = fd_cnx_serv_accept(listener);
-		CHECK( 1, server_side ? 1 : 0 );
-		CHECK( 0, fd_cnx_start_clear(server_side, 0) );
-		
-		/* Retrieve the client connection object */
-		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
-		CHECK( 1, client_side ? 1 : 0 );
-		CHECK( 0, fd_cnx_start_clear(client_side, 0) );
-		
-		/* Send a message and receive it */
-		CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
-		CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
-		CHECK( cer_sz, rcv_sz );
-		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		
-		/* Do it in the other direction */
-		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
-		CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
-		CHECK( cer_sz, rcv_sz );
-		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		
-		/* Now close the connection */
-		fd_cnx_destroy(client_side);
-		fd_cnx_destroy(server_side);
-	}
-		
-#ifndef DISABLE_SCTP
-	/* Simple SCTP client / server test (no TLS) */
-	{
-		struct connect_flags cf;
-		
-		memset(&cf, 0, sizeof(cf));
-		cf.proto = IPPROTO_SCTP;
-		
-		/* Start the client thread */
-		CHECK( 0, pthread_create(&thr, 0, connect_thr, &cf) );
-
-		/* Accept the connection of the client */
-		server_side = fd_cnx_serv_accept(listener_sctp);
-		CHECK( 1, server_side ? 1 : 0 );
-		
-		/* Retrieve the client connection object */
-		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
-		CHECK( 1, client_side ? 1 : 0 );
-		
-		CHECK( 0, fd_cnx_start_clear(server_side, 1) );
-		
-		/* Send a message and receive it */
-		CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
-		CHECK( EINVAL, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
-		CHECK( 0, fd_cnx_start_clear(client_side, 0) );
-		CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
-		CHECK( cer_sz, rcv_sz );
-		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		
-		/* Do it in the other direction */
-		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
-		CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
-		CHECK( cer_sz, rcv_sz );
-		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		
-		/* Do it one more time to use another stream */
-		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
-		CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
-		CHECK( cer_sz, rcv_sz );
-		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		
-		/* Now close the connection */
-		fd_cnx_destroy(client_side);
-		fd_cnx_destroy(server_side);
-	}
-#endif /* DISABLE_SCTP */
-	
-	/* TCP Client / server emulating old Diameter behavior (handshake after 1 message exchange) */
-	{
-		struct connect_flags cf;
-		struct handshake_flags hf;
-		
-		memset(&cf, 0, sizeof(cf));
-		cf.proto = IPPROTO_TCP;
-		
-		memset(&hf, 0, sizeof(hf));
-		
-		/* Initialize remote certificate */
-		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
-		CHECK( GNUTLS_E_SUCCESS, ret );
-		/* Set the CA */
-		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
-		CHECK( 1, ret );
-		/* Set the key */
-		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
-		CHECK( GNUTLS_E_SUCCESS, ret );
-		
-		/* Start the client thread */
-		CHECK( 0, pthread_create(&thr, 0, connect_thr, &cf) );
-
-		/* Accept the connection of the client */
-		server_side = fd_cnx_serv_accept(listener);
-		CHECK( 1, server_side ? 1 : 0 );
-		
-		/* Retrieve the client connection object */
-		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
-		CHECK( 1, client_side ? 1 : 0 );
-		hf.cnx = client_side;
-		
-		/* In legacy Diameter, we exchange first one message (CER / CEA) */
-		
-		CHECK( 0, fd_cnx_start_clear(server_side, 0) );
-		CHECK( 0, fd_cnx_start_clear(client_side, 0) );
-		
-		/* Send a message and receive it */
-		CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
-		CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
-		CHECK( cer_sz, rcv_sz );
-		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		
-		/* And the supposed reply */
-		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
-		CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
-		CHECK( cer_sz, rcv_sz );
-		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		
-		/* At this point in legacy Diameter we start the handshake */
-		CHECK( 0, pthread_create(&thr, 0, handshake_thr, &hf) );
-		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) );
-		CHECK( 0, pthread_join(thr, NULL) );
-		CHECK( 0, hf.ret );
-		
-		/* Send a few TLS protected message, and replies */
-		for (i = 0; i < 10; i++) {
-			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
-			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
-			CHECK( cer_sz, rcv_sz );
-			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-
-			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
-			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
-			CHECK( cer_sz, rcv_sz );
-			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		}
-		
-		
-		/* Now close the connection */
-		CHECK( 0, pthread_create(&thr, 0, destroy_thr, client_side) );
-		fd_cnx_destroy(server_side);
-		CHECK( 0, pthread_join(thr, NULL) );
-		
-		/* Free the credentials */
-		gnutls_certificate_free_keys(hf.creds);
-		gnutls_certificate_free_cas(hf.creds);
-		gnutls_certificate_free_credentials(hf.creds);
-	}
-		
-#ifndef DISABLE_SCTP
-	/* SCTP Client / server emulating old Diameter behavior (handshake after 1 message exchange) */
-	{
-		struct connect_flags cf;
-		struct handshake_flags hf;
-		
-		memset(&cf, 0, sizeof(cf));
-		cf.proto = IPPROTO_SCTP;
-		
-		memset(&hf, 0, sizeof(hf));
-		
-		/* Initialize remote certificate */
-		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
-		CHECK( GNUTLS_E_SUCCESS, ret );
-		/* Set the CA */
-		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
-		CHECK( 1, ret );
-		/* Set the key */
-		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
-		CHECK( GNUTLS_E_SUCCESS, ret );
-		
-		/* Start the client thread */
-		CHECK( 0, pthread_create(&thr, 0, connect_thr, &cf) );
-
-		/* Accept the connection of the client */
-		server_side = fd_cnx_serv_accept(listener_sctp);
-		CHECK( 1, server_side ? 1 : 0 );
-		
-		/* Retrieve the client connection object */
-		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
-		CHECK( 1, client_side ? 1 : 0 );
-		hf.cnx = client_side;
-		
-		/* In legacy Diameter, we exchange first one message (CER / CEA) */
-		
-		CHECK( 0, fd_cnx_start_clear(server_side, 0) );
-		CHECK( 0, fd_cnx_start_clear(client_side, 0) );
-		
-		/* Send a message and receive it */
-		CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
-		CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
-		CHECK( cer_sz, rcv_sz );
-		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		
-		/* And the supposed reply */
-		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
-		CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
-		CHECK( cer_sz, rcv_sz );
-		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		
-		/* At this point in legacy Diameter we start the handshake */
-		CHECK( 0, pthread_create(&thr, 0, handshake_thr, &hf) );
-		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) );
-		CHECK( 0, pthread_join(thr, NULL) );
-		CHECK( 0, hf.ret );
-		
-		/* Send a few TLS protected message, and replies */
-		for (i = 0; i < 100; i++) {
-			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
-			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
-			CHECK( cer_sz, rcv_sz );
-			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-
-			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
-			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
-			CHECK( cer_sz, rcv_sz );
-			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		}
-		
-		
-		/* Now close the connection */
-		CHECK( 0, pthread_create(&thr, 0, destroy_thr, client_side) );
-		fd_cnx_destroy(server_side);
-		CHECK( 0, pthread_join(thr, NULL) );
-		
-		/* Free the credentials */
-		gnutls_certificate_free_keys(hf.creds);
-		gnutls_certificate_free_cas(hf.creds);
-		gnutls_certificate_free_credentials(hf.creds);
-	}
-#endif /* DISABLE_SCTP */
-	
-	/* TCP Client / server emulating new Diameter behavior (handshake at connection directly) */
-	{
-		struct connect_flags cf;
-		struct handshake_flags hf;
-		int i;
-		
-		memset(&cf, 0, sizeof(cf));
-		cf.proto = IPPROTO_TCP;
-		
-		memset(&hf, 0, sizeof(hf));
-		
-		/* Initialize remote certificate */
-		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
-		CHECK( GNUTLS_E_SUCCESS, ret );
-		/* Set the CA */
-		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
-		CHECK( 1, ret );
-		/* Set the key */
-		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
-		CHECK( GNUTLS_E_SUCCESS, ret );
-		
-		/* Start the client thread */
-		CHECK( 0, pthread_create(&thr, 0, connect_thr, &cf) );
-
-		/* Accept the connection of the client */
-		server_side = fd_cnx_serv_accept(listener);
-		CHECK( 1, server_side ? 1 : 0 );
-		
-		/* Retrieve the client connection object */
-		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
-		CHECK( 1, client_side ? 1 : 0 );
-		hf.cnx = client_side;
-		
-		/* Start the handshake directly */
-		CHECK( 0, pthread_create(&thr, 0, handshake_thr, &hf) );
-		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) );
-		CHECK( 0, pthread_join(thr, NULL) );
-		CHECK( 0, hf.ret );
-		
-		/* Send a few TLS protected message, and replies */
-		for (i = 0; i < 10; i++) {
-			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
-			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
-			CHECK( cer_sz, rcv_sz );
-			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-
-			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
-			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
-			CHECK( cer_sz, rcv_sz );
-			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
-		}
-		
-		/* Now close the connection */
-		CHECK( 0, pthread_create(&thr, 0, destroy_thr, client_side) );
-		fd_cnx_destroy(server_side);
-		CHECK( 0, pthread_join(thr, NULL) );
-		
-		/* Free the credentials */
-		gnutls_certificate_free_keys(hf.creds);
-		gnutls_certificate_free_cas(hf.creds);
-		gnutls_certificate_free_credentials(hf.creds);
-	}
-	
-	/* That's all for the tests yet */
-	PASSTEST();
-} 
-	
Index: freeDiameter/tests/tests.h
===================================================================
--- freeDiameter/tests/tests.h	(revision 29)
+++ freeDiameter/tests/tests.h	(revision 10)
@@ -46,9 +46,8 @@
 #include <pthread.h>
 #include <errno.h>
-#include <gcrypt.h>
 
 /* Test timeout duration, unless -n is passed on the command line */
 #ifndef TEST_TIMEOUT
-#define TEST_TIMEOUT	30	/* in seconds */
+#define TEST_TIMEOUT	5	/* 5 seconds */
 #endif /* TEST_TIMEOUT */
 
@@ -79,7 +78,4 @@
 struct fd_config * fd_g_config = &conf;
 
-/* gcrypt functions to support posix threads */
-GCRY_THREAD_OPTION_PTHREAD_IMPL;
-
 /* Define the standard check routines */
 #define CHECK( _val, _assert ){				\
@@ -103,14 +99,11 @@
 
 /* Minimum inits */
-#define INIT_FD() {								\
-	memset(fd_g_config, 0, sizeof(struct fd_config));			\
-	CHECK( 0, fd_lib_init() );						\
-	fd_log_threadname(basename(__FILE__));					\
-	(void) gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);	\
-	(void) gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);			\
-	CHECK( 0, gnutls_global_init());					\
-	CHECK( 0, fd_conf_init() );						\
-	CHECK( 0, fd_dict_base_protocol(fd_g_config->cnf_dict) );		\
-	parse_cmdline(argc, argv);						\
+#define INIT_FD() {						\
+	memset(fd_g_config, 0, sizeof(struct fd_config));	\
+	CHECK( 0, fd_lib_init() );				\
+	fd_log_threadname(basename(__FILE__));			\
+	CHECK( 0, fd_conf_init() );				\
+	CHECK( 0, fd_dict_base_protocol(fd_g_config->cnf_dict) );	\
+	parse_cmdline(argc, argv);				\
 }
 
Index: include/freeDiameter/CMakeLists.txt
===================================================================
--- include/freeDiameter/CMakeLists.txt	(revision 24)
+++ include/freeDiameter/CMakeLists.txt	(revision 17)
@@ -10,9 +10,5 @@
 
 # Disable SCTP support completly ?
-OPTION(DISABLE_SCTP "Disable SCTP support?" OFF)
-IF (NOT DISABLE_SCTP)
-	OPTION(DEBUG_SCTP "Verbose SCTP (for debug)?" OFF)
-	OPTION(SCTP_USE_MAPPED_ADDRESSES "Use v6-mapped v4 addresses in SCTP (workaround some SCTP limitations)?" OFF)
-ENDIF (NOT DISABLE_SCTP)
+OPTION(DISABLE_SCTP "Disable SCTP support?")
 
 # Find TODO items in the code easily ?
Index: include/freeDiameter/freeDiameter-host.h.in
===================================================================
--- include/freeDiameter/freeDiameter-host.h.in	(revision 24)
+++ include/freeDiameter/freeDiameter-host.h.in	(revision 13)
@@ -45,6 +45,4 @@
 
 #cmakedefine DISABLE_SCTP
-#cmakedefine DEBUG_SCTP
-#cmakedefine SCTP_USE_MAPPED_ADDRESSES
 #cmakedefine ERRORS_ON_TODO
 #cmakedefine DEBUG
Index: include/freeDiameter/freeDiameter.h
===================================================================
--- include/freeDiameter/freeDiameter.h	(revision 25)
+++ include/freeDiameter/freeDiameter.h	(revision 20)
@@ -118,20 +118,14 @@
 struct fd_endpoint {
 	struct fd_list  chain;	/* link in cnf_endpoints list */
-	
-	union {
-		sSS		ss;	/* the socket information. List is always ordered by ss value (memcmp) -- see fd_ep_add_merge */
-		sSA4		sin;
-		sSA6		sin6;
-		sSA		sa;
-	};
-	
-#define	EP_FL_CONF	(1 << 0)	/* This endpoint is statically configured in a configuration file */
-#define	EP_FL_DISC	(1 << 1)	/* This endpoint was resolved from the Diameter Identity or other DNS query */
-#define	EP_FL_ADV	(1 << 2)	/* This endpoint was advertized in Diameter CER/CEA exchange */
-#define	EP_FL_LL	(1 << 3)	/* Lower layer mechanism provided this endpoint */
-#define	EP_FL_PRIMARY	(1 << 4)	/* This endpoint is primary in a multihomed SCTP association */
-	uint32_t	flags;		/* Additional information about the endpoint */
-		
-	/* To add: a validity timestamp for DNS records ? How do we retrieve this lifetime from DNS ? */
+	sSS		ss;	/* the socket information. List is always ordered by ss value (memcmp) */
+	struct {
+		unsigned conf : 1; /* This endpoint is statically configured in a configuration file */
+		unsigned disc : 1; /* This endpoint was resolved from the Diameter Identity or other DNS query */
+		unsigned adv  : 1; /* This endpoint was advertized in Diameter CER/CEA exchange */
+		unsigned ll   : 1; /* Lower layer mechanism provided this endpoint */
+		
+		/* To add: a validity timestamp for DNS records ? How do we retrieve this lifetime from DNS ? */
+
+	}		meta;	/* Additional information about the endpoint */
 };
 
@@ -152,11 +146,31 @@
 struct fd_event {
 	int	 code; /* codespace depends on the queue */
-	size_t 	 size;
 	void    *data;
 };
 
-/* Daemon's codespace: 1000->1999 */
+static __inline__ int fd_event_send(struct fifo *queue, int code, void * data)
+{
+	struct fd_event * ev;
+	CHECK_MALLOC( ev = malloc(sizeof(struct fd_event)) );
+	ev->code = code;
+	ev->data = data;
+	CHECK_FCT( fd_fifo_post(queue, &ev) );
+	return 0;
+}
+static __inline__ int fd_event_get(struct fifo *queue, int *code, void ** data)
+{
+	struct fd_event * ev;
+	CHECK_FCT( fd_fifo_get(queue, &ev) );
+	if (code)
+		*code = ev->code;
+	if (data)
+		*data = ev->data;
+	free(ev);
+	return 0;
+}
+
+/* Events codespace for fd_g_config->cnf_main_ev */
 enum {
-	 FDEV_TERMINATE	= 1000	/* request to terminate */
+	 FDEV_TERMINATE = 1000	/* request to terminate */
 	,FDEV_DUMP_DICT		/* Dump the content of the dictionary */
 	,FDEV_DUMP_EXT		/* Dump state of extensions */
@@ -166,63 +180,4 @@
 	,FDEV_DUMP_PEERS	/* Dump the list of peers */
 };
-
-static __inline__ int fd_event_send(struct fifo *queue, int code, size_t datasz, void * data)
-{
-	struct fd_event * ev;
-	CHECK_MALLOC( ev = malloc(sizeof(struct fd_event)) );
-	ev->code = code;
-	ev->size = datasz;
-	ev->data = data;
-	CHECK_FCT( fd_fifo_post(queue, &ev) );
-	return 0;
-}
-static __inline__ int fd_event_get(struct fifo *queue, int *code, size_t *datasz, void ** data)
-{
-	struct fd_event * ev;
-	CHECK_FCT( fd_fifo_get(queue, &ev) );
-	if (code)
-		*code = ev->code;
-	if (datasz)
-		*datasz = ev->size;
-	if (data)
-		*data = ev->data;
-	free(ev);
-	return 0;
-}
-static __inline__ int fd_event_timedget(struct fifo *queue, struct timespec * timeout, int timeoutcode, int *code, size_t *datasz, void ** data)
-{
-	struct fd_event * ev;
-	int ret = 0;
-	ret = fd_fifo_timedget(queue, &ev, timeout);
-	if (ret == ETIMEDOUT) {
-		if (code)
-			*code = timeoutcode;
-		if (datasz)
-			*datasz = 0;
-		if (data)
-			*data = NULL;
-	} else {
-		CHECK_FCT( ret );
-		if (code)
-			*code = ev->code;
-		if (datasz)
-			*datasz = ev->size;
-		if (data)
-			*data = ev->data;
-		free(ev);
-	}
-	return 0;
-}
-static __inline__ void fd_event_destroy(struct fifo **queue, void (*free_cb)(void * data))
-{
-	struct fd_event * ev;
-	/* Purge all events, and free the associated data if any */
-	while (fd_fifo_tryget( *queue, &ev ) == 0) {
-		(*free_cb)(ev->data);
-		free(ev);
-	}
-	CHECK_FCT_DO( fd_fifo_del(queue), /* continue */ );
-	return ;
-}  
 const char * fd_ev_str(int event); /* defined in freeDiameter/main.c */
 
@@ -301,4 +256,5 @@
 	/* Additional parameters */
 	uint32_t 	pi_lft;		/* lifetime of this peer when inactive (see pi_flags.exp definition) */
+	uint16_t	pi_streams; 	/* number of streams for SCTP. 0 = default */
 	uint16_t	pi_port; 	/* port to connect to. 0: default. */
 	int		pi_tctimer; 	/* use this value for TcTimer instead of global, if != 0 */
@@ -315,5 +271,4 @@
 	struct fd_list	pi_apps;	/* applications advertised by the remote peer, except relay (pi_flags.relay) */
 	struct {
-		char			*priority;	/* In case the default priority is not appropriate */
 		/* This is inspired from http://www.gnu.org/software/gnutls/manual/gnutls.html#ex_003ax509_002dinfo */
 		const gnutls_datum_t 	*cert_list; 	/* The (valid) credentials that the peer has presented */
@@ -505,13 +460,3 @@
 
 
-/***************************************/
-/*   Endpoints lists helpers           */
-/***************************************/
-
-int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t flags );
-int fd_ep_filter( struct fd_list * list, uint32_t flags );
-int fd_ep_clearflags( struct fd_list * list, uint32_t flags );
-
-
-
 #endif /* _FREEDIAMETER_H */
Index: include/freeDiameter/libfreeDiameter.h
===================================================================
--- include/freeDiameter/libfreeDiameter.h	(revision 29)
+++ include/freeDiameter/libfreeDiameter.h	(revision 20)
@@ -120,15 +120,14 @@
  *
  * PARAMETERS:
- *  ts	 	: The timestamp to log, or NULL for "now"
  *  buf 	: An array where the time must be stored
  *  len		: size of the buffer
  *
  * DESCRIPTION: 
- *  Writes the timestamp (in human readable format) in a buffer. 
+ *  Writes the current timestamp (in human readable format) in a buffer. 
  *
  * RETURN VALUE:
  *  pointer to buf.
  */
-char * fd_log_time ( struct timespec * ts, char * buf, size_t len );
+char * fd_log_time ( char * buf, size_t len );
 
 
@@ -174,5 +173,5 @@
 		fd_log_debug("\t | tid:%-20s\t%s\tin %s@%s:%d\n"								\
 			  "\t%s|%*s" format "\n",  										\
-					__thn, fd_log_time(NULL, __buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,	\
+					__thn, fd_log_time(__buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,	\
 					(level < FULL)?"@":" ",level, "", ## args); 						\
 	}															\
@@ -181,5 +180,5 @@
 /* Helper for function entry -- for very detailed trace of the execution */
 #define TRACE_ENTRY(_format,_args... ) \
-	TRACE_DEBUG(FCTS, "[enter] %s(" _format ") {" #_args "}", __PRETTY_FUNCTION__, ##_args );
+	TRACE_DEBUG(FCTS, "->%s (" #_args ") = (" _format ") >", __PRETTY_FUNCTION__, ##_args );
 
 /* Helper for debugging by adding traces -- for debuging a specific location of the code */
@@ -329,46 +328,12 @@
 			flag);					\
 	  if (__rc)						\
-	  	fd_log_debug("%s", (char *)gai_strerror(__rc));	\
+	  	fd_log_debug((char *)gai_strerror(__rc));	\
 	  else							\
-	  	fd_log_debug("%s", &__addrbuf[0]);		\
+	  	fd_log_debug(&__addrbuf[0]);			\
 	} else {						\
 		fd_log_debug("(NULL / ANY)");			\
 	}							\
 }
-/* Same but with the port (service) also */
-#define sSA_DUMP_NODE_SERV( sa, flag ) {				\
-	sSA * __sa = (sSA *)(sa);					\
-	char __addrbuf[INET6_ADDRSTRLEN];				\
-	char __servbuf[32];						\
-	if (__sa) {							\
-	  int __rc = getnameinfo(__sa, 					\
-	  		sizeof(sSS),					\
-			__addrbuf,					\
-			sizeof(__addrbuf),				\
-			__servbuf,					\
-			sizeof(__servbuf),				\
-			flag);						\
-	  if (__rc)							\
-	  	fd_log_debug("%s", (char *)gai_strerror(__rc));		\
-	  else								\
-	  	fd_log_debug("[%s]:%s", &__addrbuf[0],&__servbuf[0]);	\
-	} else {							\
-		fd_log_debug("(NULL / ANY)");				\
-	}								\
-}
-/* Inside a debug trace */
-#define TRACE_DEBUG_sSA(level, prefix, sa, flags, suffix ) {										\
-	if ( TRACE_BOOL(level) ) {												\
-		char __buf[25];													\
-		char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");					\
-		fd_log_debug("\t | tid:%-20s\t%s\tin %s@%s:%d\n"								\
-			  "\t%s|%*s" prefix ,  											\
-					__thn, fd_log_time(NULL, __buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,\
-					(level < FULL)?"@":" ",level, ""); 							\
-		sSA_DUMP_NODE_SERV( sa, flags );										\
-		fd_log_debug(suffix "\n");											\
-	}															\
-}
-
+/* if needed, add sSA_DUMP_SERVICE */
 
 /* A l4 protocol name (TCP / SCTP) */
@@ -425,24 +390,4 @@
 	(    ((ts1)->tv_sec  < (ts2)->tv_sec ) 	\
 	  || (((ts1)->tv_sec  == (ts2)->tv_sec ) && ((ts1)->tv_nsec < (ts2)->tv_nsec) ))
-
-
-/* Trace a binary buffer content */
-#define TRACE_DEBUG_BUFFER(level, prefix, buf, bufsz, suffix ) {								\
-	if ( TRACE_BOOL(level) ) {												\
-		int __i;													\
-		size_t __sz = (size_t)(bufsz);											\
-		uint8_t * __buf = (uint8_t *)(buf);										\
-		char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");					\
-		fd_log_debug("\t | tid:%-20s\t%s\tin %s@%s:%d\n"								\
-			  "\t%s|%*s" prefix ,  											\
-					__thn, fd_log_time(NULL, __buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,\
-					(level < FULL)?"@":" ",level, ""); 							\
-		for (__i = 0; __i < __sz; __i++) {										\
-			fd_log_debug("%02.2hhx", __buf[__i]);									\
-		}														\
-		fd_log_debug(suffix "\n");											\
-	}															\
-}
-
 
 
@@ -470,5 +415,5 @@
 	
 	if (th_ret != NULL) {
-		TRACE_DEBUG(ANNOYING, "The thread returned the following value: %p (ignored)", th_ret);
+		TRACE_DEBUG(FULL, "The thread returned the following value: %p (ignored)", th_ret);
 	}
 	
@@ -494,12 +439,4 @@
 	free(buffer);
 }
-static __inline__ void fd_cleanup_socket(void * sockptr)
-{
-	if (sockptr) {
-		shutdown(*(int *)sockptr, SHUT_RDWR);
-		*(int *)sockptr = 0;
-	}
-}
-
 
 /*============================================================*/
@@ -528,7 +465,4 @@
 void fd_list_insert_after  ( struct fd_list * ref, struct fd_list * item );
 void fd_list_insert_before ( struct fd_list * ref, struct fd_list * item );
-
-/* Move a list at the end of another */
-void fd_list_move_end(struct fd_list * ref, struct fd_list * senti);
 
 /* Insert an item in an ordered list -- ordering function provided. If duplicate object found, EEXIST and it is returned in ref_duplicate */
@@ -2408,21 +2342,4 @@
 
 /*
- * FUNCTION:	fd_fifo_move
- *
- * PARAMETERS:
- *  old		: Location of a FIFO that is to be emptied and deleted.
- *  new		: A FIFO that will receive the old data.
- *  loc_update	: if non NULL, a place to store the pointer to new FIFO atomically with the move.
- *
- * DESCRIPTION: 
- *  Delete a queue and move its content to another one atomically.
- *
- * RETURN VALUE:
- *  0		: The queue has been destroyed successfully.
- *  EINVAL 	: A parameter is invalid.
- */
-int fd_fifo_move ( struct fifo ** old, struct fifo * new, struct fifo ** loc_update );
-
-/*
  * FUNCTION:	fd_fifo_length
  *
Index: libfreeDiameter/fifo.c
===================================================================
--- libfreeDiameter/fifo.c	(revision 25)
+++ libfreeDiameter/fifo.c	(revision 14)
@@ -136,9 +136,8 @@
 }
 
-/* Delete a queue. It must be empty. */ 
+/* Delete a queue. It must be unused. */ 
 int fd_fifo_del ( struct fifo  ** queue )
 {
 	struct fifo * q;
-	int loops = 0;
 	
 	TRACE_ENTRY( "%p", queue );
@@ -150,24 +149,16 @@
 	CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
 	
-	if ((q->count != 0) || (q->data != NULL)) {
-		TRACE_DEBUG(INFO, "The queue cannot be destroyed (%d, %p)", q->count, q->data);
+	if ((q->count != 0) || (q->thrs != 0) || (q->data != NULL)) {
+		TRACE_DEBUG(INFO, "The queue cannot be destroyed (%d, %d, %p)", q->count, q->thrs, q->data);
 		CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ), /* no fallback */  );
 		return EINVAL;
 	}
 	
+	/* sanity check */
+	ASSERT(FD_IS_LIST_EMPTY(&q->list));
+	
 	/* Ok, now invalidate the queue */
 	q->eyec = 0xdead;
 	
-	while (q->thrs) {
-		CHECK_POSIX(  pthread_cond_signal(&q->cond)  );
-		CHECK_POSIX(  pthread_mutex_unlock( &q->mtx ));
-		pthread_yield();
-		CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
-		ASSERT( ++loops < 10 ); /* detect infinite loops */
-	}
-	
-	/* sanity check */
-	ASSERT(FD_IS_LIST_EMPTY(&q->list));
-	
 	/* And destroy it */
 	CHECK_POSIX(  pthread_mutex_unlock( &q->mtx )  );
@@ -179,57 +170,4 @@
 	free(q);
 	*queue = NULL;
-	
-	return 0;
-}
-
-/* Move the content of old into new, and update loc_update atomically */
-int fd_fifo_move ( struct fifo ** old, struct fifo * new, struct fifo ** loc_update )
-{
-	struct fifo * q;
-	int loops = 0;
-	
-	TRACE_ENTRY("%p %p %p", old, new, loc_update);
-	CHECK_PARAMS( old && CHECK_FIFO( *old ) && CHECK_FIFO( new ));
-	
-	q = *old;
-	CHECK_PARAMS( ! q->data );
-	if (new->high) {
-		TODO("Implement support for thresholds in fd_fifo_move...");
-	}
-	
-	/* Update loc_update */
-	*old = NULL;
-	if (loc_update)
-		*loc_update = new;
-	
-	/* Lock the queues */
-	CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
-	CHECK_POSIX(  pthread_mutex_lock( &new->mtx )  );
-	
-	/* Any waiting thread on the old queue returns an error */
-	q->eyec = 0xdead;
-	while (q->thrs) {
-		CHECK_POSIX(  pthread_cond_signal(&q->cond)  );
-		CHECK_POSIX(  pthread_mutex_unlock( &q->mtx ));
-		pthread_yield();
-		CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
-		ASSERT( ++loops < 10 ); /* detect infinite loops */
-	}
-	
-	/* Move all data from old to new */
-	fd_list_move_end( &new->list, &q->list );
-	if (q->count && (!new->count)) {
-		CHECK_POSIX(  pthread_cond_signal(&new->cond)  );
-	}
-	new->count += q->count;
-	
-	/* Destroy old */
-	CHECK_POSIX(  pthread_mutex_unlock( &q->mtx )  );
-	CHECK_POSIX(  pthread_cond_destroy( &q->cond )  );
-	CHECK_POSIX(  pthread_mutex_destroy( &q->mtx )  );
-	free(q);
-	
-	/* Unlock new, we're done */
-	CHECK_POSIX(  pthread_mutex_unlock( &new->mtx )  );
 	
 	return 0;
@@ -441,11 +379,4 @@
 awaken:
 	/* Check queue status */
-	if (!CHECK_FIFO( queue )) {
-		/* The queue is being destroyed */
-		CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-		TRACE_DEBUG(FULL, "The queue is being destroyed -> EPIPE");
-		return EPIPE;
-	}
-		
 	if (queue->count > 0) {
 		/* There are items in the queue, so pick the first one */
Index: libfreeDiameter/lists.c
===================================================================
--- libfreeDiameter/lists.c	(revision 25)
+++ libfreeDiameter/lists.c	(revision 14)
@@ -70,22 +70,4 @@
 	ASSERT(ref->head != item);
 	list_insert_after(ref, item);
-}
-
-/* Move all elements of list senti at the end of list ref */
-void fd_list_move_end(struct fd_list * ref, struct fd_list * senti)
-{
-	ASSERT(ref->head == ref);
-	ASSERT(senti->head == senti);
-	
-	if (senti->next == senti)
-		return;
-	
-	senti->next->prev = ref->prev;
-	ref->prev->next   = senti->next;
-	senti->prev->next = ref;
-	ref->prev         = senti->prev;
-	senti->prev = senti;
-	senti->next = senti;
-	
 }
 
Index: libfreeDiameter/log.c
===================================================================
--- libfreeDiameter/log.c	(revision 22)
+++ libfreeDiameter/log.c	(revision 2)
@@ -87,6 +87,6 @@
 }
 
-/* Write time into a buffer */
-char * fd_log_time ( struct timespec * ts, char * buf, size_t len )
+/* Write current time into a buffer */
+char * fd_log_time ( char * buf, size_t len )
 {
 	int ret;
@@ -96,15 +96,12 @@
 	
 	/* Get current time */
-	if (!ts) {
-		ret = clock_gettime(CLOCK_REALTIME, &tp);
-		if (ret != 0) {
-			snprintf(buf, len, "%s", strerror(ret));
-			return buf;
-		}
-		ts = &tp;
+	ret = clock_gettime(CLOCK_REALTIME, &tp);
+	if (ret != 0) {
+		snprintf(buf, len, "%s", strerror(ret));
+		return buf;
 	}
 	
-	offset += strftime(buf + offset, len - offset, "%D,%T", localtime_r( &ts->tv_sec , &tm ));
-	offset += snprintf(buf + offset, len - offset, ".%6.6ld", ts->tv_nsec / 1000);
+	offset += strftime(buf + offset, len - offset, "%D,%T", localtime_r( &tp.tv_sec , &tm ));
+	offset += snprintf(buf + offset, len - offset, ".%6.6ld", tp.tv_nsec / 1000);
 
 	return buf;
