Mercurial > hg > freeDiameter
comparison freeDiameter/sctps.c @ 209:b9f48f2f2a22
Some cleanups in the code
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Tue, 16 Feb 2010 15:29:55 +0900 |
parents | a68d24defda8 |
children | 5a1b93f59f8f |
comparison
equal
deleted
inserted
replaced
208:e1da03ba112f | 209:b9f48f2f2a22 |
---|---|
84 ASSERT( conn->cc_proto == IPPROTO_SCTP ); | 84 ASSERT( conn->cc_proto == IPPROTO_SCTP ); |
85 ASSERT( Target_Queue(conn) ); | 85 ASSERT( Target_Queue(conn) ); |
86 ASSERT( conn->cc_sctps_data.array ); | 86 ASSERT( conn->cc_sctps_data.array ); |
87 | 87 |
88 do { | 88 do { |
89 CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, &strid, &buf, &bufsz, &event, &conn->cc_closing), goto error ); | 89 CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, &strid, &buf, &bufsz, &event, &conn->cc_status), goto fatal ); |
90 switch (event) { | 90 switch (event) { |
91 case FDEVP_CNX_MSG_RECV: | 91 case FDEVP_CNX_MSG_RECV: |
92 /* Demux this message in the appropriate fifo, another thread will pull, gnutls process, and send in target queue */ | 92 /* Demux this message to the appropriate fifo, another thread will pull, gnutls process, and send to target queue */ |
93 if (strid < conn->cc_sctp_para.pairs) { | 93 if (strid < conn->cc_sctp_para.pairs) { |
94 CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto error ); | 94 CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto fatal ); |
95 } else { | 95 } else { |
96 TRACE_DEBUG(INFO, "Received packet (%d bytes) on out-of-range stream #%s from %s, discarded.", bufsz, strid, conn->cc_remid); | 96 TRACE_DEBUG(INFO, "Received packet (%d bytes) on out-of-range stream #%s from %s, discarded.", bufsz, strid, conn->cc_remid); |
97 free(buf); | 97 free(buf); |
98 } | 98 } |
99 break; | 99 break; |
100 | 100 |
101 case FDEVP_CNX_EP_CHANGE: | 101 case FDEVP_CNX_EP_CHANGE: |
102 /* Send this event to the target queue */ | 102 /* Send this event to the target queue */ |
103 CHECK_FCT_DO( fd_event_send( Target_Queue(conn), event, bufsz, buf), goto error ); | 103 CHECK_FCT_DO( fd_event_send( Target_Queue(conn), event, bufsz, buf), goto fatal ); |
104 break; | 104 break; |
105 | 105 |
106 case FDEVP_CNX_ERROR: | 106 case FDEVP_CNX_ERROR: |
107 fd_cnx_markerror(conn); | |
108 goto out; | |
109 | |
107 default: | 110 default: |
108 goto error; | 111 goto fatal; |
109 } | 112 } |
110 | 113 |
111 } while (conn->cc_loop); | 114 } while (conn->cc_loop); |
112 | 115 |
113 out: | 116 out: |
114 TRACE_DEBUG(FULL, "Thread terminated"); | 117 TRACE_DEBUG(FULL, "Thread terminated"); |
115 return NULL; | 118 return NULL; |
116 error: | 119 |
117 if (!conn->cc_closing) { | 120 fatal: |
118 CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */); | 121 /* An unrecoverable error occurred, stop the daemon */ |
119 } | 122 CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), ); |
120 | |
121 goto out; | 123 goto out; |
122 } | 124 } |
123 | 125 |
124 /* Decrypt the data received in this stream pair and store it in the target queue */ | 126 /* Decrypt the data received in this stream pair and store it in the target queue */ |
125 static void * decipher(void * arg) | 127 static void * decipher(void * arg) |
137 char buf[48]; | 139 char buf[48]; |
138 snprintf(buf, sizeof(buf), "Decipher (%hu@%d)", ctx->strid, cnx->cc_socket); | 140 snprintf(buf, sizeof(buf), "Decipher (%hu@%d)", ctx->strid, cnx->cc_socket); |
139 fd_log_threadname ( buf ); | 141 fd_log_threadname ( buf ); |
140 } | 142 } |
141 | 143 |
144 /* The next function loops while there is no error */ | |
142 CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */); | 145 CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */); |
143 error: | 146 error: |
144 if (!cnx->cc_closing) { | 147 fd_cnx_markerror(cnx); |
145 CHECK_FCT_DO( fd_event_send( Target_Queue(cnx), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */); | |
146 } | |
147 TRACE_DEBUG(FULL, "Thread terminated"); | 148 TRACE_DEBUG(FULL, "Thread terminated"); |
148 return NULL; | 149 return NULL; |
149 } | 150 } |
150 | 151 |
151 /*************************************************************/ | 152 /*************************************************************/ |
158 struct sctps_ctx * ctx = (struct sctps_ctx *) tr; | 159 struct sctps_ctx * ctx = (struct sctps_ctx *) tr; |
159 | 160 |
160 TRACE_ENTRY("%p %p %zd", tr, data, len); | 161 TRACE_ENTRY("%p %p %zd", tr, data, len); |
161 CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } ); | 162 CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } ); |
162 | 163 |
163 CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent->cc_socket, ctx->strid, (uint8_t *)data, len, &ctx->parent->cc_closing), /* errno is already set */ return -1 ); | 164 CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent->cc_socket, ctx->strid, (uint8_t *)data, len, &ctx->parent->cc_status), /* errno is already set */ return -1 ); |
164 | 165 |
165 return len; | 166 return len; |
166 } | 167 } |
167 | 168 |
168 /* Retrieve data received on a stream and already demultiplexed */ | 169 /* Retrieve data received on a stream and already demultiplexed */ |
173 int emptied; | 174 int emptied; |
174 | 175 |
175 TRACE_ENTRY("%p %p %zd", tr, buf, len); | 176 TRACE_ENTRY("%p %p %zd", tr, buf, len); |
176 CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; return -1; } ); | 177 CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; return -1; } ); |
177 | 178 |
178 /* If we don't have data available now, pull new message from the fifo -- this is blocking */ | 179 /* If we don't have data available now, pull new message from the fifo -- this is blocking (until the queue is destroyed) */ |
179 if (!ctx->partial.buf) { | 180 if (!ctx->partial.buf) { |
180 int ev; | 181 int ev; |
181 CHECK_FCT_DO( errno = fd_event_get(ctx->raw_recv, &ev, &ctx->partial.bufsz, (void *)&ctx->partial.buf), return -1 ); | 182 CHECK_FCT_DO( errno = fd_event_get(ctx->raw_recv, &ev, &ctx->partial.bufsz, (void *)&ctx->partial.buf), return -1 ); |
182 ASSERT( ev == FDEVP_CNX_MSG_RECV ); | 183 ASSERT( ev == FDEVP_CNX_MSG_RECV ); |
183 } | 184 } |
228 | 229 |
229 struct sr_store { | 230 struct sr_store { |
230 struct fd_list list; /* list of sr_data, ordered by key.size then key.data */ | 231 struct fd_list list; /* list of sr_data, ordered by key.size then key.data */ |
231 pthread_rwlock_t lock; | 232 pthread_rwlock_t lock; |
232 struct cnxctx *parent; | 233 struct cnxctx *parent; |
233 /* Add another list to chain in a global list to implement a garbage collector on sessions */ | 234 /* Add another list to chain in a global list to implement a garbage collector on sessions -- TODO */ |
234 }; | 235 }; |
235 | 236 |
236 /* Saved master session data for resuming sessions */ | 237 /* Saved master session data for resuming sessions */ |
237 struct sr_data { | 238 struct sr_data { |
238 struct fd_list chain; | 239 struct fd_list chain; |
333 if (match) { | 334 if (match) { |
334 sr = (struct sr_data *)li; | 335 sr = (struct sr_data *)li; |
335 | 336 |
336 /* Check the data is the same */ | 337 /* Check the data is the same */ |
337 if ((data.size != sr->data.size) || memcmp(data.data, sr->data.data, data.size)) { | 338 if ((data.size != sr->data.size) || memcmp(data.data, sr->data.data, data.size)) { |
338 TRACE_DEBUG(SR_LEVEL, "GnuTLS tried to store a session with same key and different data!"); | 339 TRACE_DEBUG(INFO, "GnuTLS tried to store a session with same key and different data!"); |
339 ret = -1; | 340 ret = -1; |
340 } else { | 341 } else { |
341 TRACE_DEBUG(SR_LEVEL, "GnuTLS tried to store a session with same key and same data, skipped."); | 342 TRACE_DEBUG(SR_LEVEL, "GnuTLS tried to store a session with same key and same data, skipped."); |
342 } | 343 } |
343 goto out; | 344 goto out; |
568 if (ret == NULL) { | 569 if (ret == NULL) { |
569 errors++; /* Handshake failed on this stream */ | 570 errors++; /* Handshake failed on this stream */ |
570 } | 571 } |
571 } | 572 } |
572 | 573 |
573 return errors ? ENOTCONN : 0; | 574 if (errors) { |
575 TRACE_DEBUG(INFO, "Handshake failed on %d/%hd stream pairs", errors, conn->cc_sctp_para.pairs); | |
576 fd_cnx_markerror(conn); | |
577 return ENOTCONN; | |
578 } | |
579 | |
580 return 0; | |
574 } | 581 } |
575 | 582 |
576 /* Receive messages from all stream pairs */ | 583 /* Receive messages from all stream pairs */ |
577 int fd_sctps_startthreads(struct cnxctx * conn) | 584 int fd_sctps_startthreads(struct cnxctx * conn) |
578 { | 585 { |
596 | 603 |
597 CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return ); | 604 CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return ); |
598 | 605 |
599 /* End all TLS sessions, in series (not as efficient as paralel, but simpler) */ | 606 /* End all TLS sessions, in series (not as efficient as paralel, but simpler) */ |
600 for (i = 1; i < conn->cc_sctp_para.pairs; i++) { | 607 for (i = 1; i < conn->cc_sctp_para.pairs; i++) { |
601 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctps_data.array[i].session, GNUTLS_SHUT_WR), /* Continue */ ); | 608 if (!conn->cc_status & CC_STATUS_ERROR) { |
609 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctps_data.array[i].session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) ); | |
610 } | |
602 } | 611 } |
603 } | 612 } |
604 | 613 |
605 /* After "bye" was sent on all streams, read from sessions until an error is received */ | 614 /* After "bye" was sent on all streams, read from sessions until an error is received */ |
606 void fd_sctps_waitthreadsterm(struct cnxctx * conn) | 615 void fd_sctps_waitthreadsterm(struct cnxctx * conn) |
626 | 635 |
627 TRACE_ENTRY("%p", conn); | 636 TRACE_ENTRY("%p", conn); |
628 CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return ); | 637 CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return ); |
629 | 638 |
630 for (i = 1; i < conn->cc_sctp_para.pairs; i++) { | 639 for (i = 1; i < conn->cc_sctp_para.pairs; i++) { |
631 gnutls_deinit(conn->cc_sctps_data.array[i].session); | 640 if (conn->cc_sctps_data.array[i].session) { |
641 gnutls_deinit(conn->cc_sctps_data.array[i].session); | |
642 conn->cc_sctps_data.array[i].session = NULL; | |
643 } | |
632 } | 644 } |
633 } | 645 } |
634 | 646 |
635 | 647 |
636 /* Stop all receiver threads */ | 648 /* Stop all receiver threads */ |
663 /* Free remaining data in the array */ | 675 /* Free remaining data in the array */ |
664 for (i = 0; i < conn->cc_sctp_para.pairs; i++) { | 676 for (i = 0; i < conn->cc_sctp_para.pairs; i++) { |
665 if (conn->cc_sctps_data.array[i].raw_recv) | 677 if (conn->cc_sctps_data.array[i].raw_recv) |
666 fd_event_destroy( &conn->cc_sctps_data.array[i].raw_recv, free ); | 678 fd_event_destroy( &conn->cc_sctps_data.array[i].raw_recv, free ); |
667 free(conn->cc_sctps_data.array[i].partial.buf); | 679 free(conn->cc_sctps_data.array[i].partial.buf); |
668 /* gnutls_session was already deinit */ | 680 if (conn->cc_sctps_data.array[i].session) { |
681 gnutls_deinit(conn->cc_sctps_data.array[i].session); | |
682 conn->cc_sctps_data.array[i].session = NULL; | |
683 } | |
669 } | 684 } |
670 | 685 |
671 /* Free the array itself now */ | 686 /* Free the array itself now */ |
672 free(conn->cc_sctps_data.array); | 687 free(conn->cc_sctps_data.array); |
673 conn->cc_sctps_data.array = NULL; | 688 conn->cc_sctps_data.array = NULL; |