Index: freeDiameter/cnxctx.c
===================================================================
--- freeDiameter/cnxctx.c	(revision 23)
+++ freeDiameter/cnxctx.c	(revision 24)
@@ -174,7 +174,13 @@
 	return NULL;
 }
-#ifndef DISABLE_SCTP
+
+/* 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;
@@ -201,6 +207,6 @@
 	fd_cnx_destroy(cnx);
 	return NULL;
-}
 #endif /* DISABLE_SCTP */
+}
 
 /* Allow clients to connect on the server socket */
@@ -239,10 +245,11 @@
 	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 - new client [", fd_cnx_getid(serv));
-		sSA_DUMP_NODE( &ss, AI_NUMERICHOST );
-		fd_log_debug("] connected.\n");
+		fd_log_debug("%s : accepted new client [", fd_cnx_getid(serv));
+		sSA_DUMP_NODE( &ss, NI_NUMERICHOST );
+		fd_log_debug("].\n");
 	}
 	
@@ -259,23 +266,25 @@
 		/* Numeric values for debug */
 		rc = getnameinfo((sSA *)&ss, sizeof(sSS), addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV);
-		if (rc)
+		if (rc) {
 			snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
-		
-		snprintf(cli->cc_id, sizeof(cli->cc_id), "Client %s [%s]:%s (%d) / serv (%d)", 
+			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);
 		
-		/* Textual value for log messages */
-		rc = getnameinfo((sSA *)&ss, sizeof(sSS), cli->cc_remid, sizeof(cli->cc_remid), NULL, 0, NI_NUMERICHOST);
+		/* 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 */
-#ifndef DISABLE_SCTP
 	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 ), goto error );
+		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;
@@ -291,10 +300,119 @@
 }
 
-/* Client side: connect to a remote server */
-struct cnxctx * fd_cnx_cli_connect(int proto, const sSA * sa,  socklen_t addrlen)
-{
-
-	TODO("...");
+/* 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) */
+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;
+	
+	/* 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));
+	}
+	
+	if (TRACE_BOOL(INFO)) {
+		fd_log_debug("Connection established to server '");
+		sSA_DUMP_NODE_SERV( &primary, NI_NUMERICSERV);
+		fd_log_debug("' (SCTP:%d).\n", sock);
+	}
+	
+	return cnx;
+
+error:
+	fd_cnx_destroy(cnx);
+	return NULL;
+#endif /* DISABLE_SCTP */
 }
 
@@ -415,5 +533,5 @@
 				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, 0, 0, 0, 1 ));
+				CHECK_FCT(fd_ep_add_merge( local, (sSA *)&ss, sl, EP_FL_LL | EP_FL_PRIMARY));
 			}
 			break;
@@ -441,5 +559,5 @@
 				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, 0, 0, 0, 1 ));
+				CHECK_FCT(fd_ep_add_merge( remote, (sSA *)&ss, sl, EP_FL_LL | EP_FL_PRIMARY ));
 			}
 			break;
@@ -528,6 +646,2 @@
 	return;
 }
-
-
-
-
