comparison freeDiameter/sctps.c @ 29:5ba91682f0bc

Added a test for cnxctx (tbc) and fixed some bugs
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 28 Oct 2009 15:19:50 +0900
parents b3a1773e9f46
children 26685c67d387
comparison
equal deleted inserted replaced
28:3628f7d2ba88 29:5ba91682f0bc
70 size_t bufsz; 70 size_t bufsz;
71 int event; 71 int event;
72 uint16_t strid; 72 uint16_t strid;
73 73
74 TRACE_ENTRY("%p", arg); 74 TRACE_ENTRY("%p", arg);
75
76 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out); 75 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
76
77 /* Set the thread name */
78 {
79 char buf[48];
80 snprintf(buf, sizeof(buf), "Demuxer (%d)", conn->cc_socket);
81 fd_log_threadname ( buf );
82 }
83
77 ASSERT( conn->cc_proto == IPPROTO_SCTP ); 84 ASSERT( conn->cc_proto == IPPROTO_SCTP );
78 ASSERT( conn->cc_tls == 1 );
79 ASSERT( Target_Queue(conn) ); 85 ASSERT( Target_Queue(conn) );
80 ASSERT( conn->cc_sctps_data.array ); 86 ASSERT( conn->cc_sctps_data.array );
81 87
82 do { 88 do {
83 CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, &strid, &buf, &bufsz, &event), goto error ); 89 CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, &strid, &buf, &bufsz, &event), goto error );
112 { 118 {
113 struct sctps_ctx * ctx = arg; 119 struct sctps_ctx * ctx = arg;
114 struct cnxctx *cnx; 120 struct cnxctx *cnx;
115 121
116 TRACE_ENTRY("%p", arg); 122 TRACE_ENTRY("%p", arg);
117
118 CHECK_PARAMS_DO(ctx && ctx->raw_recv && ctx->parent, goto error); 123 CHECK_PARAMS_DO(ctx && ctx->raw_recv && ctx->parent, goto error);
119 cnx = ctx->parent; 124 cnx = ctx->parent;
120 ASSERT( Target_Queue(cnx) ); 125 ASSERT( Target_Queue(cnx) );
126
127 /* Set the thread name */
128 {
129 char buf[48];
130 snprintf(buf, sizeof(buf), "Decipher (%hu@%d)", ctx->strid, cnx->cc_socket);
131 fd_log_threadname ( buf );
132 }
121 133
122 CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */); 134 CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */);
123 error: 135 error:
124 CHECK_FCT_DO( fd_event_send( Target_Queue(cnx), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */); 136 CHECK_FCT_DO( fd_event_send( Target_Queue(cnx), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
125 TRACE_DEBUG(FULL, "Thread terminated"); 137 TRACE_DEBUG(FULL, "Thread terminated");
206 218
207 struct sr_store { 219 struct sr_store {
208 struct fd_list list; /* list of sr_data, ordered by key.size then key.data */ 220 struct fd_list list; /* list of sr_data, ordered by key.size then key.data */
209 pthread_rwlock_t lock; 221 pthread_rwlock_t lock;
210 struct cnxctx *parent; 222 struct cnxctx *parent;
223 /* Add another list to chain in a global list to implement a garbage collector on sessions */
211 }; 224 };
212 225
213 /* Saved master session data for resuming sessions */ 226 /* Saved master session data for resuming sessions */
214 struct sr_data { 227 struct sr_data {
215 struct fd_list chain; 228 struct fd_list chain;
216 gnutls_datum_t key; 229 gnutls_datum_t key;
217 gnutls_datum_t data; 230 gnutls_datum_t data;
218 }; 231 };
219 232
220 /* The level at which we debug session resuming */ 233 /* The level at which we debug session resuming */
221 #define SR_LEVEL FULL 234 #define SR_LEVEL (FULL + 1)
222 235
223 /* Initialize the store area for a connection */ 236 /* Initialize the store area for a connection */
224 static int store_init(struct cnxctx * conn) 237 static int store_init(struct cnxctx * conn)
225 { 238 {
226 TRACE_ENTRY("%p", conn); 239 TRACE_ENTRY("%p", conn);
300 struct sr_data * sr; 313 struct sr_data * sr;
301 int match = 0; 314 int match = 0;
302 int ret = 0; 315 int ret = 0;
303 316
304 CHECK_PARAMS_DO( sto && key.data && data.data, return -1 ); 317 CHECK_PARAMS_DO( sto && key.data && data.data, return -1 );
305 TRACE_DEBUG_BUFFER(SR_LEVEL, "Session store [key ", key.data, key.size < 16 ? key.size : 16, "]");
306 318
307 CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 ); 319 CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 );
320 TRACE_DEBUG_BUFFER(SR_LEVEL, "Session store [key ", key.data, key.size, "]");
308 321
309 li = find_or_next(sto, key, &match); 322 li = find_or_next(sto, key, &match);
310 if (match) { 323 if (match) {
311 sr = (struct sr_data *)li; 324 sr = (struct sr_data *)li;
312 325
313 /* Check the data is the same */ 326 /* Check the data is the same */
314 if ((data.size != sr->data.size) || memcmp(data.data, sr->data.data, data.size)) { 327 if ((data.size != sr->data.size) || memcmp(data.data, sr->data.data, data.size)) {
315 TRACE_DEBUG(INFO, "GnuTLS tried to store a session with same key and different data!"); 328 TRACE_DEBUG(SR_LEVEL, "GnuTLS tried to store a session with same key and different data!");
316 ret = -1; 329 ret = -1;
330 } else {
331 TRACE_DEBUG(SR_LEVEL, "GnuTLS tried to store a session with same key and same data, skipped.");
317 } 332 }
318 goto out; 333 goto out;
319 } 334 }
320 335
321 /* Create a new entry */ 336 /* Create a new entry */
347 struct sr_data * sr; 362 struct sr_data * sr;
348 int match = 0; 363 int match = 0;
349 int ret = 0; 364 int ret = 0;
350 365
351 CHECK_PARAMS_DO( sto && key.data, return -1 ); 366 CHECK_PARAMS_DO( sto && key.data, return -1 );
352 TRACE_DEBUG_BUFFER(SR_LEVEL, "Session delete [key ", key.data, key.size < 16 ? key.size : 16, "]");
353 367
354 CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 ); 368 CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 );
369 TRACE_DEBUG_BUFFER(SR_LEVEL, "Session delete [key ", key.data, key.size, "]");
355 370
356 li = find_or_next(sto, key, &match); 371 li = find_or_next(sto, key, &match);
357 if (match) { 372 if (match) {
358 sr = (struct sr_data *)li; 373 sr = (struct sr_data *)li;
359 374
379 int match = 0; 394 int match = 0;
380 gnutls_datum_t res = { NULL, 0 }; 395 gnutls_datum_t res = { NULL, 0 };
381 gnutls_datum_t error = { NULL, 0 }; 396 gnutls_datum_t error = { NULL, 0 };
382 397
383 CHECK_PARAMS_DO( sto && key.data, return error ); 398 CHECK_PARAMS_DO( sto && key.data, return error );
384 TRACE_DEBUG_BUFFER(SR_LEVEL, "Session fetch [key ", key.data, key.size < 16 ? key.size : 16, "]");
385 399
386 CHECK_POSIX_DO( pthread_rwlock_rdlock(&sto->lock), return error ); 400 CHECK_POSIX_DO( pthread_rwlock_rdlock(&sto->lock), return error );
401 TRACE_DEBUG_BUFFER(SR_LEVEL, "Session fetch [key ", key.data, key.size, "]");
387 402
388 li = find_or_next(sto, key, &match); 403 li = find_or_next(sto, key, &match);
389 if (match) { 404 if (match) {
390 sr = (struct sr_data *)li; 405 sr = (struct sr_data *)li;
391 CHECK_MALLOC_DO(res.data = gnutls_malloc(sr->data.size), goto out ); 406 CHECK_MALLOC_DO(res.data = gnutls_malloc(sr->data.size), goto out );
392 res.size = sr->data.size; 407 res.size = sr->data.size;
393 memcpy(res.data, sr->data.data, res.size); 408 memcpy(res.data, sr->data.data, res.size);
394 } 409 }
395 out: 410 out:
411 TRACE_DEBUG(SR_LEVEL, "Fetched (%p, %d) from store %p", res.data, res.size, sto);
396 CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return error); 412 CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return error);
397 return res; 413 return res;
398 } 414 }
399 415
400 /* Set the session pointer in a session object */ 416 /* Set the session pointer in a session object */
414 static void * handshake_resume_th(void * arg) 430 static void * handshake_resume_th(void * arg)
415 { 431 {
416 struct sctps_ctx * ctx = (struct sctps_ctx *) arg; 432 struct sctps_ctx * ctx = (struct sctps_ctx *) arg;
417 TRACE_ENTRY("%p", arg); 433 TRACE_ENTRY("%p", arg);
418 434
435 /* Set the thread name */
436 {
437 char buf[48];
438 snprintf(buf, sizeof(buf), "Handshake resume (%hu@%d)", ctx->strid, ctx->parent->cc_socket);
439 fd_log_threadname ( buf );
440 }
441
419 TRACE_DEBUG(FULL, "Starting TLS resumed handshake on stream %hu", ctx->strid); 442 TRACE_DEBUG(FULL, "Starting TLS resumed handshake on stream %hu", ctx->strid);
420 CHECK_GNUTLS_DO( gnutls_handshake( ctx->session ), return NULL); 443 CHECK_GNUTLS_DO( gnutls_handshake( ctx->session ), return NULL);
421 444
422 /* We can trace success of resuming handshake by using gnutls_session_is_resumed */ 445 if (TRACE_BOOL(FULL)) {
446 int resumed = gnutls_session_is_resumed(ctx->session);
447 if (resumed) {
448 fd_log_debug("Session was resumed successfully on stream %hu (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent));
449 } else {
450 fd_log_debug("Session was NOT resumed (full handshake) on stream %hu (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent));
451 }
452 }
423 453
424 /* Finish */ 454 /* Finish */
425 return arg; 455 return arg;
426 } 456 }
427 457
464 494
465 return 0; 495 return 0;
466 } 496 }
467 497
468 /* Handshake other streams, after full handshake on the master session */ 498 /* Handshake other streams, after full handshake on the master session */
469 int fd_sctps_handshake_others(struct cnxctx * conn, char * priority) 499 int fd_sctps_handshake_others(struct cnxctx * conn, char * priority, void * alt_creds)
470 { 500 {
471 uint16_t i; 501 uint16_t i;
472 int errors = 0; 502 int errors = 0;
473 gnutls_datum_t master_data; 503 gnutls_datum_t master_data;
474 504
484 } 514 }
485 515
486 /* Initialize the session objects and start the handshake in a separate thread */ 516 /* Initialize the session objects and start the handshake in a separate thread */
487 for (i = 1; i < conn->cc_sctp_para.pairs; i++) { 517 for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
488 /* Set credentials and priority */ 518 /* Set credentials and priority */
489 CHECK_FCT( fd_tls_prepare(&conn->cc_sctps_data.array[i].session, conn->cc_tls_para.mode, priority) ); 519 CHECK_FCT( fd_tls_prepare(&conn->cc_sctps_data.array[i].session, conn->cc_tls_para.mode, priority, alt_creds) );
490 520
491 /* For the client, copy data from master session; for the server, set session resuming pointers */ 521 /* For the client, copy data from master session; for the server, set session resuming pointers */
492 if (conn->cc_tls_para.mode == GNUTLS_CLIENT) { 522 if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
493 CHECK_GNUTLS_DO( gnutls_session_set_data(conn->cc_sctps_data.array[i].session, master_data.data, master_data.size), return ENOMEM ); 523 CHECK_GNUTLS_DO( gnutls_session_set_data(conn->cc_sctps_data.array[i].session, master_data.data, master_data.size), return ENOMEM );
494 } else { 524 } else {
547 CHECK_FCT_DO( fd_thr_term(&conn->cc_sctps_data.array[i].thr), /* continue */ ); 577 CHECK_FCT_DO( fd_thr_term(&conn->cc_sctps_data.array[i].thr), /* continue */ );
548 } 578 }
549 return; 579 return;
550 } 580 }
551 581
582 static void * bye_th(void * arg)
583 {
584 struct sctps_ctx * ctx = (struct sctps_ctx *) arg;
585 TRACE_ENTRY("%p", arg);
586
587 /* Set the thread name */
588 {
589 char buf[48];
590 snprintf(buf, sizeof(buf), "gnutls_bye (%hu@%d)", ctx->strid, ctx->parent->cc_socket);
591 fd_log_threadname ( buf );
592 }
593
594 CHECK_GNUTLS_DO( gnutls_bye(ctx->session, GNUTLS_SHUT_RDWR), /* Continue */ );
595
596 /* Finish */
597 return arg;
598 }
599
600
601
552 /* Destroy a wrapper context */ 602 /* Destroy a wrapper context */
553 void fd_sctps_destroy(struct cnxctx * conn) 603 void fd_sctps_destroy(struct cnxctx * conn)
554 { 604 {
555 uint16_t i; 605 uint16_t i;
556 606
557 CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return ); 607 CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return );
558 608
559 /* Terminate all receiving threads in case we did not do it yet */ 609 /* Terminate all receiving threads in case we did not do it yet */
560 fd_sctps_stopthreads(conn); 610 fd_sctps_stopthreads(conn);
561 611
562 /* End all TLS sessions -- maybe we should do it in parallel ? */ 612 /* End all TLS sessions, in parallel */
563 for (i = 0; i < conn->cc_sctp_para.pairs; i++) { 613 for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
564 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctps_data.array[i].session, GNUTLS_SHUT_RDWR), /* Continue */ ); 614 CHECK_POSIX_DO( pthread_create( &conn->cc_sctps_data.array[i].thr, NULL, bye_th, &conn->cc_sctps_data.array[i] ), break );
565 } 615 }
566 616 for (--i; i > 0; --i) {
617 CHECK_POSIX_DO( pthread_join( conn->cc_sctps_data.array[i].thr, NULL ), continue );
618 }
619 skip:
567 /* Now, stop the demux thread */ 620 /* Now, stop the demux thread */
568 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ ); 621 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
569 622
570 /* Free remaining data in the array */ 623 /* Free remaining data in the array */
571 for (i = 0; i < conn->cc_sctp_para.pairs; i++) { 624 for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
572 fd_event_destroy( &conn->cc_sctps_data.array[i].raw_recv, free ); 625 fd_event_destroy( &conn->cc_sctps_data.array[i].raw_recv, free );
573 free(conn->cc_sctps_data.array[i].partial.buf); 626 free(conn->cc_sctps_data.array[i].partial.buf);
574 gnutls_deinit(conn->cc_sctps_data.array[i].session); 627 if (i > 0)
628 gnutls_deinit(conn->cc_sctps_data.array[i].session);
575 } 629 }
576 630
577 /* Free the array itself now */ 631 /* Free the array itself now */
578 free(conn->cc_sctps_data.array); 632 free(conn->cc_sctps_data.array);
579 conn->cc_sctps_data.array = NULL; 633 conn->cc_sctps_data.array = NULL;
"Welcome to our mercurial repository"