Mercurial > hg > freeDiameter
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);