Changeset 22:0b3b46da2c12 in freeDiameter for freeDiameter/server.c
- Timestamp:
- Oct 19, 2009, 6:43:09 PM (15 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
freeDiameter/server.c
r21 r22 36 36 #include "fD.h" 37 37 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 40 struct 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 */ 44 44 struct server { 45 45 struct fd_list chain; /* link in the FD_SERVERS list */ 46 46 47 int socket; /* server socket, or <= 0 */ 48 47 struct cnxctx * conn; /* server connection context (listening socket) */ 49 48 int proto; /* IPPROTO_TCP or IPPROTO_SCTP */ 50 49 int secur; /* TLS is started immediatly after connection ? */ 51 50 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 */ 59 56 }; 60 57 61 /* Client (connected remote endpoint, not received CER yet) information*/58 /* Client information (connecting peer for which we don't have the CER yet) */ 62 59 struct client { 63 60 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; /* De lay 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 */ 67 64 }; 68 65 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 */ 68 void 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 */ 98 static void * client_sm(void * arg) 79 99 { 80 100 struct client * c = arg; … … 88 108 89 109 /* 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 ); 94 123 } 95 124 … … 104 133 TODO("Message == CER : "); 105 134 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 */ 138 cleanup: 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); 112 151 return NULL; 113 152 … … 117 156 } 118 157 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 */ 182 159 static void * serv_th(void * arg) 183 160 { 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; 197 166 198 167 /* 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 ); 200 169 201 170 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; 207 173 208 174 /* 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 ); 210 176 211 177 TRACE_DEBUG(FULL, "New connection accepted"); 212 178 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 ); 219 192 220 193 } while (1); 221 194 222 195 error: 223 if (s v)224 s v->serv_status = 2;196 if (s) 197 s->status = 2; 225 198 /* Send error signal to the daemon */ 226 199 TRACE_DEBUG(INFO, "An error occurred in server module! Thread is terminating..."); … … 232 205 233 206 /* 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; 207 static struct server * new_serv( int proto, int secur ) 208 { 238 209 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 );244 210 245 211 /* New server structure */ … … 248 214 memset(new, 0, sizeof(struct server)); 249 215 fd_list_init(&new->chain, new); 250 new->socket = socket;251 216 new->proto = proto; 252 217 new->secur = secur; … … 254 219 fd_list_init(&new->clients, new); 255 220 256 new->serv_name = sn;257 258 221 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 }281 222 } 282 223 … … 284 225 int fd_servers_start() 285 226 { 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); 288 230 289 231 /* SCTP */ … … 294 236 295 237 /* 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 } 300 247 301 248 /* 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 ) ); 302 253 303 254 #endif /* DISABLE_SCTP */ … … 307 258 if (!fd_g_config->cnf_flags.no_tcp) { 308 259 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 } 312 287 } else { 313 288 /* 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 } 314 310 } 315 311 } … … 319 315 320 316 /* Terminate all the servers */ 321 void fd_servers_stop() 322 { 317 int fd_servers_stop() 318 { 319 TODO("Not implemented"); 320 323 321 /* Loop on all servers */ 324 322 /* 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.