Navigation


source: freeDiameter/freeDiameter/server.c @ 20:277ec00d793e

Last change on this file since 20:277ec00d793e was 20:277ec00d793e, checked in by Sebastien Decugis <sdecugis@nict.go.jp>, 12 years ago

Backup before typhoon... Progress on server side

File size: 8.7 KB
Line 
1/*********************************************************************************************************
2* Software License Agreement (BSD License)                                                               *
3* Author: Sebastien Decugis <sdecugis@nict.go.jp>                                                        *
4*                                                                                                        *
5* Copyright (c) 2009, WIDE Project and NICT                                                              *
6* All rights reserved.                                                                                   *
7*                                                                                                        *
8* Redistribution and use of this software in source and binary forms, with or without modification, are  *
9* permitted provided that the following conditions are met:                                              *
10*                                                                                                        *
11* * Redistributions of source code must retain the above                                                 *
12*   copyright notice, this list of conditions and the                                                    *
13*   following disclaimer.                                                                                *
14*                                                                                                        *
15* * Redistributions in binary form must reproduce the above                                              *
16*   copyright notice, this list of conditions and the                                                    *
17*   following disclaimer in the documentation and/or other                                               *
18*   materials provided with the distribution.                                                            *
19*                                                                                                        *
20* * Neither the name of the WIDE Project or NICT nor the                                                 *
21*   names of its contributors may be used to endorse or                                                  *
22*   promote products derived from this software without                                                  *
23*   specific prior written permission of WIDE Project and                                                *
24*   NICT.                                                                                                *
25*                                                                                                        *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
32* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
33* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
34*********************************************************************************************************/
35
36#include "fD.h"
37
38/* This file contains the server (listening) part of the daemon */
39
40struct 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 */
44struct server {
45        struct fd_list  chain;          /* link in the FD_SERVERS list */
46
47        int             socket;         /* server socket, or <= 0 */
48       
49        int             proto;          /* IPPROTO_TCP or IPPROTO_SCTP */
50        int             secur;          /* TLS is started immediatly after connection ? */
51       
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 */
59};
60
61/* Client (connected remote endpoint, not received CER yet) information */
62struct client {
63        struct fd_list   chain; /* link in the server's list of clients */
64       
65        struct cnxctx   *conn;  /* Parameters of the connection; sends its events to the ev fifo bellow */
66       
67        struct timespec  ts;    /* Delay for receiving CER: INCNX_TIMEOUT */
68        struct fifo     *ev;    /* Events of the connection -- allowed: TIMEOUT, ERROR (cnx, tls), MSG_RCV (CER, other=>error) */
69       
70        pthread_t        cli_thr; /* connection state machine (simplified PSM) */
71};
72
73/* Parameter for the thread handling the new connected client, to avoid bloking the server thread */
74struct cli_fast {
75        struct server * serv;
76        int             sock;
77        sSS             ss;
78        socklen_t       sslen;
79};
80
81
82/* This thread is called when a new client had just connected */
83static void * handle_client_fast(void * arg)
84{
85        struct cli_fast * cf = arg;
86        struct client * c = NULL;
87       
88        /* Name the current thread */
89        ASSERT(arg);
90        {
91                char addr[128];
92                int offset = snprintf(addr, sizeof(addr), "Srv %d/Cli %d : ", cf->serv->socket, cf->sock);
93                int rc = getnameinfo((sSA *)&cf->ss, sizeof(sSS), addr + offset, sizeof(addr) - offset, NULL, 0, 0);
94                if (rc)
95                        memcpy(addr + offset, gai_strerror(rc), sizeof(addr) - offset);
96               
97                if (TRACE_BOOL(INFO)) {
98                        fd_log_debug( "New connection %s, sock %d, from '%s'\n", cf->serv->serv_name, cf->sock, addr + offset);
99                }
100       
101                fd_log_threadname ( addr );
102        }
103       
104        /* Create a client structure */
105        CHECK_MALLOC_DO( c = malloc(sizeof(struct client)), goto early_error );
106        memset(c, 0, sizeof(struct client));
107        fd_list_init(&c->chain, c);
108        c->cli_thr = pthread_self();
109       
110        /* Create the connection context */
111        CHECK_MALLOC_DO( c->conn = fd_cnx_init(cf->sock, cf->serv->proto), goto early_error );
112       
113        /* In case we are a secure server, handshake now */
114        if (cf->serv->secur) {
115               
116                TODO("Continue");
117        }
118       
119        /* Save the client in the list */
120        CHECK_POSIX_DO( pthread_mutex_lock( &cf->serv->clients_mtx ), goto early_error );
121        fd_list_insert_before(&cf->serv->clients, &c->chain);
122        CHECK_POSIX_DO( pthread_mutex_unlock( &cf->serv->clients_mtx ), goto error );
123       
124       
125       
126       
127early_error:
128        TRACE_DEBUG(INFO, "Thread is detaching to die");
129        pthread_detach(pthread_self());
130        shutdown(cf->sock, SHUT_RDWR);
131        free(cf);
132        free(c);
133error: 
134        TRACE_DEBUG(INFO, "Thread is terminating");
135        CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), );
136        return NULL;
137}
138
139/* The thread for the server */
140static void * serv_th(void * arg)
141{
142        struct server *sv = (struct server *)arg;
143        struct cli_fast cf;
144       
145        CHECK_PARAMS_DO(sv, goto error);
146        fd_log_threadname ( sv->serv_name );
147        sv->serv_status = 1;
148       
149        memset(&cf, 0, sizeof(struct cli_fast));
150        cf.serv = sv;
151       
152       
153        /* Accept incoming connections */
154        CHECK_SYS_DO(  listen(sv->socket, 5), goto error );
155       
156        do {
157                struct cli_fast * ncf;
158                pthread_t         thr;
159               
160                /* Re-init socket size */
161                cf.sslen = sizeof(sSS);
162               
163                /* Wait for a new client */
164                CHECK_SYS_DO( cf.sock = accept(sv->socket, (sSA *)&cf.ss, &cf.sslen), goto error );
165               
166                TRACE_DEBUG(FULL, "New connection accepted");
167               
168                /* Create the copy for the client thread */
169                CHECK_MALLOC_DO( ncf = malloc(sizeof(struct cli_fast)), goto error );
170                memcpy(ncf, &cf, sizeof(struct cli_fast));
171               
172                /* Create the thread to handle the new incoming connection */
173                CHECK_POSIX_DO( pthread_create( &thr /* we don't use it, but NULL is not standard */, NULL, handle_client_fast, ncf), goto error );
174               
175        } while (1);
176       
177error: 
178        if (sv)
179                sv->serv_status = 2;
180        /* Send error signal to the daemon */
181        TRACE_DEBUG(INFO, "An error occurred in server module! Thread is terminating...");
182        CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), );
183
184        return NULL;
185}
186
187
188/* Create a new server structure */
189static struct server * new_serv( int proto, int secur, int socket )
190{
191        char buf[32];
192        char * sn = NULL;
193        struct server * new;
194       
195        /* Create the server debug name */
196        buf[sizeof(buf) - 1] = '\0';
197        snprintf(buf, sizeof(buf) - 1, "Serv %d (%s%s)", socket, IPPROTO_NAME( proto ), secur ? "s" : "");
198        CHECK_MALLOC_DO( sn = strdup(buf), return NULL );
199       
200        /* New server structure */
201        CHECK_MALLOC_DO( new = malloc(sizeof(struct server)), return NULL );
202       
203        memset(new, 0, sizeof(struct server));
204        fd_list_init(&new->chain, new);
205        new->socket = socket;
206        new->proto = proto;
207        new->secur = secur;
208        CHECK_POSIX_DO( pthread_mutex_init(&new->clients_mtx, NULL), return NULL );
209        fd_list_init(&new->clients, new);
210       
211        new->serv_name = sn;
212       
213        return new;
214}
215
216/* Dump all servers information */
217void fd_servers_dump()
218{
219        struct fd_list * li;
220       
221        fd_log_debug("Dumping servers list :\n");
222        for (li = FD_SERVERS.next; li != &FD_SERVERS; li = li->next) {
223                struct server * sv = (struct server *)li;
224                fd_log_debug("  Serv '%s': %s(%d), %s, %s, %s\n", 
225                                sv->serv_name, 
226                                (sv->socket > 0) ? "Open" : "Closed", sv->socket,
227                                IPPROTO_NAME( sv->proto ),
228                                sv->secur ? "Secur" : "NotSecur",
229                                (sv->serv_status == 0) ? "Thread not created" :
230                                ((sv->serv_status == 1) ? "Thread running" :
231                                ((sv->serv_status == 2) ? "Thread terminated" :
232                                                          "Thread status unknown")));
233                /* Dump the endpoints ? */
234                /* Dump the client list ? */
235        }
236}
237
238/* Start all the servers */
239int fd_servers_start()
240{
241        int  socket;
242        struct server * sv;
243       
244        /* SCTP */
245        if (!fd_g_config->cnf_flags.no_sctp) {
246#ifdef DISABLE_SCTP
247                ASSERT(0);
248#else /* DISABLE_SCTP */
249               
250                /* Create the server on default port */
251                CHECK_FCT( fd_sctp_create_bind_server( &socket, fd_g_config->cnf_port ) );
252                CHECK_MALLOC( sv = new_serv(IPPROTO_SCTP, 0, socket) );
253               
254               
255               
256               
257#endif /* DISABLE_SCTP */
258        }
259       
260        /* TCP */
261        if (!fd_g_config->cnf_flags.no_tcp) {
262               
263               
264        }
265       
266        return 0;
267}
268
269/* Terminate all the servers */
270void fd_servers_stop()
271{
272       
273}
Note: See TracBrowser for help on using the repository browser.