changeset 21:bef197f6826f

Backup before week-end, cnxctx and server in progress
author Sebastien Decugis <sdecugis@nict.go.jp>
date Thu, 08 Oct 2009 20:05:16 +0900
parents 277ec00d793e
children 0b3b46da2c12
files doc/freediameter.conf.sample freeDiameter/cnxctx.c freeDiameter/fD.h freeDiameter/server.c libfreeDiameter/fifo.c
diffstat 5 files changed, 219 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/doc/freediameter.conf.sample	Wed Oct 07 19:31:39 2009 +0900
+++ b/doc/freediameter.conf.sample	Thu Oct 08 20:05:16 2009 +0900
@@ -213,7 +213,7 @@
 LoadExtension = "extensions/dict_eap.fdx";
 ConnectPeer = "jules.nautilus6.org" ;
 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_Cred = "/etc/openssl-ca/clients/certs/test.cert" , "/etc/openssl-ca/clients/privkeys/test.key.pem";
 TLS_CA = "/etc/openssl-ca/public-www/cacert.pem";
 # TLS_CRL = "/etc/openssl-ca/public-www/crl.pem";
 
--- a/freeDiameter/cnxctx.c	Wed Oct 07 19:31:39 2009 +0900
+++ b/freeDiameter/cnxctx.c	Thu Oct 08 20:05:16 2009 +0900
@@ -35,7 +35,44 @@
 
 #include "fD.h"
 
-/* Initialize a connection context */
+/* The connection context structure */
+struct cnxctx {
+	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 ? */
+	
+	struct fifo *	cc_events;	/* Events occuring on the connection */
+	pthread_t	cc_mgr;		/* manager thread for the connection */
+	struct fifo *	cc_incoming;	/* FIFO queue of messages received on the connection */
+	
+	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;
+};
+
+
+/* Initialize a context structure from a socket */
 struct cnxctx * fd_cnx_init(int sock, int proto)
 {
 	struct cnxctx * conn = NULL;
@@ -65,7 +102,15 @@
 	return conn;
 }
 
-/* TLS handshake the connection */
+/* Start receving messages in clear (no TLS) on the connection */
+int fd_cnx_start_clear(struct cnxctx * conn)
+{
+	
+	TODO("...");
+	return ENOTSUP;
+}
+
+/* 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)
 {
 	TRACE_ENTRY( "%p %d", conn, mode);
@@ -141,3 +186,59 @@
 	
 	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)
+{
+	
+	TODO("...");
+	return ENOTSUP;
+}
+
+/* Get the list of endpoints (IP addresses) of the remote peer on this object */
+int fd_cnx_getendpoints(struct cnxctx * conn, struct fd_list * senti)
+{
+	
+	TODO("...");
+	return ENOTSUP;
+}
+
+
+/* Get a string describing the remote peer address (ip address or fqdn) */
+char * fd_cnx_getremoteid(struct cnxctx * conn)
+{
+	
+	TODO("...");
+	return NULL;
+}
+
+
+/* Receive next message. if timeout is not NULL, wait only until timeout */
+int fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned char **buf, size_t * len)
+{
+	
+	TODO("...");
+	return ENOTSUP;
+}
+
+
+/* Send a message */
+int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
+{
+	
+	TODO("...");
+	return ENOTSUP;
+}
+
+
+/* Destroy a conn structure, and shutdown the socket */
+void fd_cnx_destroy(struct cnxctx * conn)
+{
+	
+	TODO("...");
+	return;
+}
+
+
+
+
--- a/freeDiameter/fD.h	Wed Oct 07 19:31:39 2009 +0900
+++ b/freeDiameter/fD.h	Thu Oct 08 20:05:16 2009 +0900
@@ -172,39 +172,6 @@
 	struct msg	*req;	/* A request that was sent and not yet answered. */
 };
 
-/* 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();
@@ -232,7 +199,14 @@
 
 /* Connection contexts */
 struct cnxctx * fd_cnx_init(int sock, int proto);
+int fd_cnx_start_clear(struct cnxctx * conn);
 int fd_cnx_handshake(struct cnxctx * conn, int mode);
+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 * senti);
+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_send(struct cnxctx * conn, unsigned char * buf, size_t len);
+void fd_cnx_destroy(struct cnxctx * conn);
 
 /* SCTP */
 #ifndef DISABLE_SCTP
--- a/freeDiameter/server.c	Wed Oct 07 19:31:39 2009 +0900
+++ b/freeDiameter/server.c	Thu Oct 08 20:05:16 2009 +0900
@@ -61,12 +61,8 @@
 /* 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; 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) */
 };
 
@@ -79,6 +75,47 @@
 };
 
 
+static void * client_simple_psm(void * arg)
+{
+	struct client * c = arg;
+	struct server * s = 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 */
+	{
+		char addr[128];
+		snprintf(addr, sizeof(addr), "Srv %d/Cli %s", s->socket, fd_cnx_getremoteid(c->conn));
+		fd_log_threadname ( addr );
+	}
+	
+	/* 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;
+	
+	TODO("receive message until c->ts");
+	
+	TODO("Timeout => close");
+	TODO("Message != CER => close");
+	TODO("Message == CER : ");
+	TODO("Search matching peer");
+	TODO("...");
+	
+	/* The end: we have freed the client structure already */
+	TODO("Unlink the client structure");
+	TODO(" pthread_detach(c->cli_thr); ");
+	TODO(" free(c); ");
+	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, NULL), );
+	return NULL;
+}
+
 /* This thread is called when a new client had just connected */
 static void * handle_client_fast(void * arg)
 {
@@ -89,50 +126,55 @@
 	ASSERT(arg);
 	{
 		char addr[128];
-		int offset = snprintf(addr, sizeof(addr), "Srv %d/Cli %d : ", cf->serv->socket, cf->sock);
+		int offset = snprintf(addr, sizeof(addr), "Srv %d/CliFast %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);
 		
+		fd_log_threadname ( addr );
+	
 		if (TRACE_BOOL(INFO)) {
 			fd_log_debug( "New connection %s, sock %d, from '%s'\n", cf->serv->serv_name, cf->sock, addr + offset);
 		}
-	
-		fd_log_threadname ( addr );
 	}
 	
 	/* Create a client structure */
-	CHECK_MALLOC_DO( c = malloc(sizeof(struct client)), goto early_error );
+	CHECK_MALLOC_DO( c = malloc(sizeof(struct client)), goto fatal_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 );
+	CHECK_MALLOC_DO( c->conn = fd_cnx_init(cf->sock, cf->serv->proto), goto fatal_error );
 	
 	/* In case we are a secure server, handshake now */
 	if (cf->serv->secur) {
-		
-		TODO("Continue");
+		CHECK_FCT_DO( fd_cnx_handshake(c->conn, GNUTLS_CLIENT), goto cleanup );
 	}
 	
-	/* 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 );
-	
-	
 	
+	/* Save the client in the list */
+	CHECK_POSIX_DO( pthread_mutex_lock( &cf->serv->clients_mtx ), goto fatal_error );
+	fd_list_insert_before(&cf->serv->clients, &c->chain);
+	CHECK_POSIX_DO( pthread_mutex_unlock( &cf->serv->clients_mtx ), goto fatal_error );
 	
-early_error:
-	TRACE_DEBUG(INFO, "Thread is detaching to die");
-	pthread_detach(pthread_self());
-	shutdown(cf->sock, SHUT_RDWR);
+	/* Start the client thread */
+	CHECK_POSIX_DO( pthread_create( &c->cli_thr, NULL, client_simple_psm, c ), goto fatal_error );
+	
+	/* We're done here */
+	free(cf);
+	return NULL;
+	
+cleanup:	/* Clean all objects and return (minor error on the connection)*/
+	if (c && c->conn) {
+		TODO( "Free the c->conn object & gnutls data" );
+	}
+	
+	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, NULL), );
 	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;
 }
 
@@ -141,6 +183,7 @@
 {
 	struct server *sv = (struct server *)arg;
 	struct cli_fast cf;
+	pthread_attr_t	attr;
 	
 	CHECK_PARAMS_DO(sv, goto error);
 	fd_log_threadname ( sv->serv_name );
@@ -149,6 +192,8 @@
 	memset(&cf, 0, sizeof(struct cli_fast));
 	cf.serv = sv;
 	
+	CHECK_POSIX_DO( pthread_attr_init(&attr), goto error );
+	CHECK_POSIX_DO( pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED), goto error );
 	
 	/* Accept incoming connections */
 	CHECK_SYS_DO(  listen(sv->socket, 5), goto error );
@@ -170,7 +215,7 @@
 		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 );
+		CHECK_POSIX_DO( pthread_create( &thr, &attr, handle_client_fast, ncf), goto error );
 		
 	} while (1);
 	
@@ -230,8 +275,8 @@
 				((sv->serv_status == 1) ? "Thread running" :
 				((sv->serv_status == 2) ? "Thread terminated" :
 							  "Thread status unknown")));
-		/* Dump the endpoints ? */
-		/* Dump the client list ? */
+		/* Dump the client list */
+		TODO("Dump client list");
 	}
 }
 
@@ -250,9 +295,10 @@
 		/* Create the server on default port */
 		CHECK_FCT( fd_sctp_create_bind_server( &socket, fd_g_config->cnf_port ) );
 		CHECK_MALLOC( sv = new_serv(IPPROTO_SCTP, 0, socket) );
-		
+		TODO("Link");
+		TODO("Start thread");
 		
-		
+		/* Create the server on secure port */
 		
 #endif /* DISABLE_SCTP */
 	}
@@ -260,7 +306,12 @@
 	/* TCP */
 	if (!fd_g_config->cnf_flags.no_tcp) {
 		
-		
+		if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) {
+			/* if not no_IP : create server for 0.0.0.0 */
+			/* if not no_IP6 : create server for :: */
+		} else {
+			/* Create all endpoints -- check flags */
+		}
 	}
 	
 	return 0;
@@ -269,5 +320,8 @@
 /* Terminate all the servers */
 void fd_servers_stop()
 {
-	
+	/* Loop on all servers */
+		/* cancel thread */
+		/* shutdown the socket */
+		/* empty list of clients (stop them) */
 }
--- a/libfreeDiameter/fifo.c	Wed Oct 07 19:31:39 2009 +0900
+++ b/libfreeDiameter/fifo.c	Thu Oct 08 20:05:16 2009 +0900
@@ -135,10 +135,11 @@
 	
 }
 
-/* Delete a queue. It must be unused. */ 
+/* Delete a queue. It must be empty. */ 
 int fd_fifo_del ( struct fifo  ** queue )
 {
 	struct fifo * q;
+	int loops = 0;
 	
 	TRACE_ENTRY( "%p", queue );
 
@@ -148,18 +149,26 @@
 	
 	CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
 	
-	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);
+	/* Ok, now invalidate the queue */
+	q->eyec = 0xdead;
+	
+	if ((q->count != 0) || (q->data != NULL)) {
+		TRACE_DEBUG(INFO, "The queue cannot be destroyed (%d, %p)", q->count, q->data);
 		CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ), /* no fallback */  );
 		return EINVAL;
 	}
 	
+	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));
 	
-	/* Ok, now invalidate the queue */
-	q->eyec = 0xdead;
-	
 	/* And destroy it */
 	CHECK_POSIX(  pthread_mutex_unlock( &q->mtx )  );
 	
@@ -378,6 +387,13 @@
 	
 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 */
 		*item = mq_pop(queue);
"Welcome to our mercurial repository"