Navigation


Changeset 22:0b3b46da2c12 in freeDiameter for freeDiameter/server.c


Ignore:
Timestamp:
Oct 19, 2009, 6:43:09 PM (15 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Progress on server code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/server.c

    r21 r22  
    3636#include "fD.h"
    3737
    38 /* This file contains the server (listening) part of the daemon */
    39 
    40 struct fd_list          FD_SERVERS = FD_LIST_INITIALIZER(FD_SERVERS);   /* The list of all server sockets */
    41 /* We don't need to protect this list, it is only accessed from the main thread. */
    42 
    43 /* Server (listening socket) information */
     38/* Server (listening) part of the daemon */
     39
     40struct fd_list          FD_SERVERS = FD_LIST_INITIALIZER(FD_SERVERS);   /* The list of all server objects */
     41/* We don't need to protect this list, it is only accessed from the main daemon thread. */
     42
     43/* Servers information */
    4444struct server {
    4545        struct fd_list  chain;          /* link in the FD_SERVERS list */
    4646
    47         int             socket;         /* server socket, or <= 0 */
    48        
     47        struct cnxctx * conn;           /* server connection context (listening socket) */
    4948        int             proto;          /* IPPROTO_TCP or IPPROTO_SCTP */
    5049        int             secur;          /* TLS is started immediatly after connection ? */
    5150       
    52         pthread_t       serv_thr;       /* The thread listening for new connections */
    53         int             serv_status;    /* 0 : not created; 1 : running; 2 : terminated */
    54        
    55         pthread_mutex_t clients_mtx;    /* Mutex to protect the list of clients connected to the thread */
    56         struct fd_list  clients;        /* The list of clients connecting to this server, which information is not yet known */
    57        
    58         char *          serv_name;      /* A string to identify this server */
     51        pthread_t       thr;            /* The thread listening for new connections */
     52        int             status;         /* 0 : not created; 1 : running; 2 : terminated */
     53       
     54        struct fd_list  clients;        /* List of clients connected to this server, not yet identified */
     55        pthread_mutex_t clients_mtx;    /* Mutex to protect the list of clients */
    5956};
    6057
    61 /* Client (connected remote endpoint, not received CER yet) information */
     58/* Client information (connecting peer for which we don't have the CER yet) */
    6259struct client {
    6360        struct fd_list   chain; /* link in the server's list of clients */
    64         struct cnxctx   *conn;  /* Parameters of the connection; sends its events to the ev fifo bellow */
    65         struct timespec  ts;    /* Delay for receiving CER: INCNX_TIMEOUT */
    66         pthread_t        cli_thr; /* connection state machine (simplified PSM) */
     61        struct cnxctx   *conn;  /* Parameters of the connection */
     62        struct timespec  ts;    /* Deadline for receiving CER (after INCNX_TIMEOUT) */
     63        pthread_t        thr;   /* connection state machine */
    6764};
    6865
    69 /* Parameter for the thread handling the new connected client, to avoid bloking the server thread */
    70 struct cli_fast {
    71         struct server * serv;
    72         int             sock;
    73         sSS             ss;
    74         socklen_t       sslen;
    75 };
    76 
    77 
    78 static void * client_simple_psm(void * arg)
     66
     67/* Dump all servers information */
     68void fd_servers_dump()
     69{
     70        struct fd_list * li, *cli;
     71       
     72        fd_log_debug("Dumping servers list :\n");
     73        for (li = FD_SERVERS.next; li != &FD_SERVERS; li = li->next) {
     74                struct server * s = (struct server *)li;
     75                fd_log_debug("  Serv %p '%s': %s, %s, %s\n",
     76                                s, fd_cnx_getid(s->conn),
     77                                IPPROTO_NAME( s->proto ),
     78                                s->secur ? "Secur" : "NotSecur",
     79                                (s->status == 0) ? "Thread not created" :
     80                                ((s->status == 1) ? "Thread running" :
     81                                ((s->status == 2) ? "Thread terminated" :
     82                                                          "Thread status unknown")));
     83                /* Dump the client list of this server */
     84                (void) pthread_mutex_lock(&s->clients_mtx);
     85                for (cli = s->clients.next; cli != &s->clients; cli = cli->next) {
     86                        struct client * c = (struct client *)cli;
     87                        char bufts[128];
     88                        fd_log_debug("     Connected: '%s' (timeout: %s)\n",
     89                                        fd_cnx_getid(c->conn),
     90                                        fd_log_time(&c->ts, bufts, sizeof(bufts)));
     91                }
     92                (void) pthread_mutex_unlock(&s->clients_mtx);
     93        }
     94}
     95
     96
     97/* The state machine to handle incoming connection before the remote peer is identified */
     98static void * client_sm(void * arg)
    7999{
    80100        struct client * c = arg;
     
    88108       
    89109        /* Name the current thread */
    90         {
    91                 char addr[128];
    92                 snprintf(addr, sizeof(addr), "Srv %d/Cli %s", s->socket, fd_cnx_getremoteid(c->conn));
    93                 fd_log_threadname ( addr );
     110        fd_log_threadname ( fd_cnx_getid(c->conn) );
     111       
     112        /* Handshake if we are a secure server port, or start clear otherwise */
     113        if (s->secur) {
     114                int ret = fd_cnx_handshake(c->conn, GNUTLS_SERVER, NULL);
     115                if (ret != 0) {
     116                        if (TRACE_BOOL(INFO)) {
     117                                fd_log_debug("TLS handshake failed for client '%s', connection aborted.\n", fd_cnx_getid(c->conn));
     118                        }
     119                        goto cleanup;
     120                }
     121        } else {
     122                CHECK_FCT_DO( fd_cnx_start_clear(c->conn), goto cleanup );
    94123        }
    95124       
     
    104133        TODO("Message == CER : ");
    105134        TODO("Search matching peer");
    106         TODO("...");
    107        
    108         /* The end: we have freed the client structure already */
    109         TODO("Unlink the client structure");
    110         TODO(" pthread_detach(c->cli_thr); ");
    111         TODO(" free(c); ");
     135        TODO("Send event to the peer");
     136       
     137        /* The end */
     138cleanup:
     139        /* Unlink the client structure */
     140        CHECK_POSIX_DO( pthread_mutex_lock(&s->clients_mtx), goto fatal_error );
     141        fd_list_unlink( &c->chain );
     142        CHECK_POSIX_DO( pthread_mutex_unlock(&s->clients_mtx), goto fatal_error );
     143       
     144        /* Destroy the connection object if present */
     145        if (c->conn)
     146                fd_cnx_destroy(c->conn);
     147       
     148        /* Detach the thread, cleanup the client structure */
     149        pthread_detach(pthread_self());
     150        free(c);
    112151        return NULL;
    113152       
     
    117156}
    118157
    119 /* This thread is called when a new client had just connected */
    120 static void * handle_client_fast(void * arg)
    121 {
    122         struct cli_fast * cf = arg;
    123         struct client * c = NULL;
    124        
    125         /* Name the current thread */
    126         ASSERT(arg);
    127         {
    128                 char addr[128];
    129                 int offset = snprintf(addr, sizeof(addr), "Srv %d/CliFast %d : ", cf->serv->socket, cf->sock);
    130                 int rc = getnameinfo((sSA *)&cf->ss, sizeof(sSS), addr + offset, sizeof(addr) - offset, NULL, 0, 0);
    131                 if (rc)
    132                         memcpy(addr + offset, gai_strerror(rc), sizeof(addr) - offset);
    133                
    134                 fd_log_threadname ( addr );
    135        
    136                 if (TRACE_BOOL(INFO)) {
    137                         fd_log_debug( "New connection %s, sock %d, from '%s'\n", cf->serv->serv_name, cf->sock, addr + offset);
    138                 }
    139         }
    140        
    141         /* Create a client structure */
    142         CHECK_MALLOC_DO( c = malloc(sizeof(struct client)), goto fatal_error );
    143         memset(c, 0, sizeof(struct client));
    144         fd_list_init(&c->chain, c);
    145        
    146         /* Create the connection context */
    147         CHECK_MALLOC_DO( c->conn = fd_cnx_init(cf->sock, cf->serv->proto), goto fatal_error );
    148        
    149         /* In case we are a secure server, handshake now */
    150         if (cf->serv->secur) {
    151                 CHECK_FCT_DO( fd_cnx_handshake(c->conn, GNUTLS_CLIENT), goto cleanup );
    152         }
    153        
    154        
    155         /* Save the client in the list */
    156         CHECK_POSIX_DO( pthread_mutex_lock( &cf->serv->clients_mtx ), goto fatal_error );
    157         fd_list_insert_before(&cf->serv->clients, &c->chain);
    158         CHECK_POSIX_DO( pthread_mutex_unlock( &cf->serv->clients_mtx ), goto fatal_error );
    159        
    160         /* Start the client thread */
    161         CHECK_POSIX_DO( pthread_create( &c->cli_thr, NULL, client_simple_psm, c ), goto fatal_error );
    162        
    163         /* We're done here */
    164         free(cf);
    165         return NULL;
    166        
    167 cleanup:        /* Clean all objects and return (minor error on the connection)*/
    168         if (c && c->conn) {
    169                 TODO( "Free the c->conn object & gnutls data" );
    170         }
    171        
    172         return NULL;   
    173        
    174 fatal_error:    /* This has effect to terminate the daemon */
    175         CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), );
    176         free(cf);
    177         free(c);
    178         return NULL;
    179 }
    180 
    181 /* The thread for the server */
     158/* The thread managing a server */
    182159static void * serv_th(void * arg)
    183160{
    184         struct server *sv = (struct server *)arg;
    185         struct cli_fast cf;
    186         pthread_attr_t  attr;
    187        
    188         CHECK_PARAMS_DO(sv, goto error);
    189         fd_log_threadname ( sv->serv_name );
    190         sv->serv_status = 1;
    191        
    192         memset(&cf, 0, sizeof(struct cli_fast));
    193         cf.serv = sv;
    194        
    195         CHECK_POSIX_DO( pthread_attr_init(&attr), goto error );
    196         CHECK_POSIX_DO( pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED), goto error );
     161        struct server *s = (struct server *)arg;
     162       
     163        CHECK_PARAMS_DO(s, goto error);
     164        fd_log_threadname ( fd_cnx_getid(s->conn) );
     165        s->status = 1;
    197166       
    198167        /* Accept incoming connections */
    199         CHECK_SYS_DO(  listen(sv->socket, 5), goto error );
     168        CHECK_FCT_DO( fd_cnx_serv_listen(s->conn), goto error );
    200169       
    201170        do {
    202                 struct cli_fast * ncf;
    203                 pthread_t         thr;
    204                
    205                 /* Re-init socket size */
    206                 cf.sslen = sizeof(sSS);
     171                struct client * c = NULL;
     172                struct cnxctx * conn = NULL;
    207173               
    208174                /* Wait for a new client */
    209                 CHECK_SYS_DO( cf.sock = accept(sv->socket, (sSA *)&cf.ss, &cf.sslen), goto error );
     175                CHECK_MALLOC_DO( conn = fd_cnx_serv_accept(s->conn), goto error );
    210176               
    211177                TRACE_DEBUG(FULL, "New connection accepted");
    212178               
    213                 /* Create the copy for the client thread */
    214                 CHECK_MALLOC_DO( ncf = malloc(sizeof(struct cli_fast)), goto error );
    215                 memcpy(ncf, &cf, sizeof(struct cli_fast));
    216                
    217                 /* Create the thread to handle the new incoming connection */
    218                 CHECK_POSIX_DO( pthread_create( &thr, &attr, handle_client_fast, ncf), goto error );
     179                /* Create a client structure */
     180                CHECK_MALLOC_DO( c = malloc(sizeof(struct client)), goto error );
     181                memset(c, 0, sizeof(struct client));
     182                fd_list_init(&c->chain, c);
     183                c->conn = conn;
     184               
     185                /* Save the client in the list */
     186                CHECK_POSIX_DO( pthread_mutex_lock( &s->clients_mtx ), goto error );
     187                fd_list_insert_before(&s->clients, &c->chain);
     188                CHECK_POSIX_DO( pthread_mutex_unlock( &s->clients_mtx ), goto error );
     189
     190                /* Start the client thread */
     191                CHECK_POSIX_DO( pthread_create( &c->thr, NULL, client_sm, c ), goto error );
    219192               
    220193        } while (1);
    221194       
    222195error: 
    223         if (sv)
    224                 sv->serv_status = 2;
     196        if (s)
     197                s->status = 2;
    225198        /* Send error signal to the daemon */
    226199        TRACE_DEBUG(INFO, "An error occurred in server module! Thread is terminating...");
     
    232205
    233206/* Create a new server structure */
    234 static struct server * new_serv( int proto, int secur, int socket )
    235 {
    236         char buf[32];
    237         char * sn = NULL;
     207static struct server * new_serv( int proto, int secur )
     208{
    238209        struct server * new;
    239        
    240         /* Create the server debug name */
    241         buf[sizeof(buf) - 1] = '\0';
    242         snprintf(buf, sizeof(buf) - 1, "Serv %d (%s%s)", socket, IPPROTO_NAME( proto ), secur ? "s" : "");
    243         CHECK_MALLOC_DO( sn = strdup(buf), return NULL );
    244210       
    245211        /* New server structure */
     
    248214        memset(new, 0, sizeof(struct server));
    249215        fd_list_init(&new->chain, new);
    250         new->socket = socket;
    251216        new->proto = proto;
    252217        new->secur = secur;
     
    254219        fd_list_init(&new->clients, new);
    255220       
    256         new->serv_name = sn;
    257        
    258221        return new;
    259 }
    260 
    261 /* Dump all servers information */
    262 void fd_servers_dump()
    263 {
    264         struct fd_list * li;
    265        
    266         fd_log_debug("Dumping servers list :\n");
    267         for (li = FD_SERVERS.next; li != &FD_SERVERS; li = li->next) {
    268                 struct server * sv = (struct server *)li;
    269                 fd_log_debug("  Serv '%s': %s(%d), %s, %s, %s\n",
    270                                 sv->serv_name,
    271                                 (sv->socket > 0) ? "Open" : "Closed", sv->socket,
    272                                 IPPROTO_NAME( sv->proto ),
    273                                 sv->secur ? "Secur" : "NotSecur",
    274                                 (sv->serv_status == 0) ? "Thread not created" :
    275                                 ((sv->serv_status == 1) ? "Thread running" :
    276                                 ((sv->serv_status == 2) ? "Thread terminated" :
    277                                                           "Thread status unknown")));
    278                 /* Dump the client list */
    279                 TODO("Dump client list");
    280         }
    281222}
    282223
     
    284225int fd_servers_start()
    285226{
    286         int  socket;
    287         struct server * sv;
     227        struct server * s;
     228       
     229        int empty_conf_ep = FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints);
    288230       
    289231        /* SCTP */
     
    294236               
    295237                /* Create the server on default port */
    296                 CHECK_FCT( fd_sctp_create_bind_server( &socket, fd_g_config->cnf_port ) );
    297                 CHECK_MALLOC( sv = new_serv(IPPROTO_SCTP, 0, socket) );
    298                 TODO("Link");
    299                 TODO("Start thread");
     238                CHECK_MALLOC( s = new_serv(IPPROTO_SCTP, 0) );
     239                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) );
     240                fd_list_insert_before( &FD_SERVERS, &s->chain );
     241                CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
     242               
     243                /* Retrieve the list of endpoints if it was empty */
     244                if (empty_conf_ep) {
     245                        (void) fd_cnx_getendpoints(s->conn, &fd_g_config->cnf_endpoints, NULL);
     246                }
    300247               
    301248                /* Create the server on secure port */
     249                CHECK_MALLOC( s = new_serv(IPPROTO_SCTP, 1) );
     250                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) );
     251                fd_list_insert_before( &FD_SERVERS, &s->chain );
     252                CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
    302253               
    303254#endif /* DISABLE_SCTP */
     
    307258        if (!fd_g_config->cnf_flags.no_tcp) {
    308259               
    309                 if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) {
    310                         /* if not no_IP : create server for 0.0.0.0 */
    311                         /* if not no_IP6 : create server for :: */
     260                if (empty_conf_ep) {
     261                        /* Bind TCP servers on [0.0.0.0] */
     262                        if (!fd_g_config->cnf_flags.no_ip4) {
     263                               
     264                                CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 0) );
     265                                CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port, AF_INET, NULL) );
     266                                fd_list_insert_before( &FD_SERVERS, &s->chain );
     267                                CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
     268
     269                                CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 1) );
     270                                CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port_tls, AF_INET, NULL) );
     271                                fd_list_insert_before( &FD_SERVERS, &s->chain );
     272                                CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
     273                        }
     274                        /* Bind TCP servers on [::] */
     275                        if (!fd_g_config->cnf_flags.no_ip6) {
     276                               
     277                                CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 0) );
     278                                CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port, AF_INET6, NULL) );
     279                                fd_list_insert_before( &FD_SERVERS, &s->chain );
     280                                CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
     281
     282                                CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 1) );
     283                                CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port_tls, AF_INET6, NULL) );
     284                                fd_list_insert_before( &FD_SERVERS, &s->chain );
     285                                CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
     286                        }
    312287                } else {
    313288                        /* Create all endpoints -- check flags */
     289                        struct fd_list * li;
     290                        for (li = fd_g_config->cnf_endpoints.next; li != &fd_g_config->cnf_endpoints; li = li->next) {
     291                                struct fd_endpoint * ep = (struct fd_endpoint *)li;
     292                                sSA * sa = (sSA *) &ep->ss;
     293                                if (! ep->meta.conf)
     294                                        continue;
     295                                if (fd_g_config->cnf_flags.no_ip4 && (sa->sa_family == AF_INET))
     296                                        continue;
     297                                if (fd_g_config->cnf_flags.no_ip6 && (sa->sa_family == AF_INET6))
     298                                        continue;
     299                               
     300                                CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 0) );
     301                                CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port, sa->sa_family, ep) );
     302                                fd_list_insert_before( &FD_SERVERS, &s->chain );
     303                                CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
     304
     305                                CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 1) );
     306                                CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port_tls, sa->sa_family, ep) );
     307                                fd_list_insert_before( &FD_SERVERS, &s->chain );
     308                                CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
     309                        }
    314310                }
    315311        }
     
    319315
    320316/* Terminate all the servers */
    321 void fd_servers_stop()
    322 {
     317int fd_servers_stop()
     318{
     319        TODO("Not implemented");
     320       
    323321        /* Loop on all servers */
    324322                /* cancel thread */
    325                 /* shutdown the socket */
    326                 /* empty list of clients (stop them) */
    327 }
     323                /* destroy server connection context */
     324                /* cancel and destroy all clients */
     325}
Note: See TracChangeset for help on using the changeset viewer.