comparison libfdcore/sctp3436.c @ 1344:a5c072798f1a

Increase two buffer sizes to avoid truncation. Remove trailing whitespace while here.
author Thomas Klausner <tk@giga.or.at>
date Fri, 12 Apr 2019 13:15:04 +0200
parents 6a1042d8075b
children 3cbe458fbfa9
comparison
equal deleted inserted replaced
1343:0c25bfa3660e 1344:a5c072798f1a
48 - we have several fifo queues (1 per stream pairs). 48 - we have several fifo queues (1 per stream pairs).
49 GnuTLS is configured to use custom push / pull functions: 49 GnuTLS is configured to use custom push / pull functions:
50 - the pull function retrieves the data from the fifo queue corresponding to a stream #. 50 - the pull function retrieves the data from the fifo queue corresponding to a stream #.
51 - the push function sends the data on a certain stream. 51 - the push function sends the data on a certain stream.
52 We also have a demux thread that reads the socket and store received data in the appropriate fifo 52 We also have a demux thread that reads the socket and store received data in the appropriate fifo
53 53
54 We have one gnutls_session per stream pair, and as many threads that read the gnutls records and save incoming data to the target queue. 54 We have one gnutls_session per stream pair, and as many threads that read the gnutls records and save incoming data to the target queue.
55 55
56 This complexity is required because we cannot read a socket for a given stream only; we can only get the next message and find its stream. 56 This complexity is required because we cannot read a socket for a given stream only; we can only get the next message and find its stream.
57 */ 57 */
58 58
59 /* Note that this mechanism is replaced by DTLS in RFC6733 */ 59 /* Note that this mechanism is replaced by DTLS in RFC6733 */
60 60
68 struct cnxctx * conn = arg; 68 struct cnxctx * conn = arg;
69 uint8_t * buf; 69 uint8_t * buf;
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 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out); 75 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
76 76
77 /* Set the thread name */ 77 /* Set the thread name */
78 { 78 {
79 char buf[48]; 79 char buf[100];
80 snprintf(buf, sizeof(buf), "Demuxer (%d:%s)", conn->cc_socket, conn->cc_remid); 80 snprintf(buf, sizeof(buf), "Demuxer (%d:%s)", conn->cc_socket, conn->cc_remid);
81 fd_log_threadname ( buf ); 81 fd_log_threadname ( buf );
82 } 82 }
83 83
84 ASSERT( conn->cc_proto == IPPROTO_SCTP ); 84 ASSERT( conn->cc_proto == IPPROTO_SCTP );
85 ASSERT( fd_cnx_target_queue(conn) ); 85 ASSERT( fd_cnx_target_queue(conn) );
86 ASSERT( conn->cc_sctp3436_data.array ); 86 ASSERT( conn->cc_sctp3436_data.array );
87 87
88 do { 88 do {
89 CHECK_FCT_DO( fd_sctp_recvmeta(conn, &strid, &buf, &bufsz, &event), goto fatal ); 89 CHECK_FCT_DO( fd_sctp_recvmeta(conn, &strid, &buf, &bufsz, &event), goto fatal );
90 switch (event) { 90 switch (event) {
91 case FDEVP_CNX_MSG_RECV: 91 case FDEVP_CNX_MSG_RECV:
92 /* Demux this message to the appropriate fifo, another thread will pull, gnutls process, and send to target queue */ 92 /* Demux this message to the appropriate fifo, another thread will pull, gnutls process, and send to target queue */
95 } else { 95 } else {
96 TRACE_DEBUG(INFO, "Received packet (%zd bytes) on out-of-range stream #%d from %s, discarded.", bufsz, strid, conn->cc_remid); 96 TRACE_DEBUG(INFO, "Received packet (%zd bytes) on out-of-range stream #%d 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( fd_cnx_target_queue(conn), event, bufsz, buf), goto fatal ); 103 CHECK_FCT_DO( fd_event_send( fd_cnx_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 goto out; 107 goto out;
108 108
109 case FDEVP_CNX_SHUTDOWN: 109 case FDEVP_CNX_SHUTDOWN:
110 /* Just ignore the notification for now, we will get another error later anyway */ 110 /* Just ignore the notification for now, we will get another error later anyway */
111 continue; 111 continue;
112 112
113 default: 113 default:
114 goto fatal; 114 goto fatal;
115 } 115 }
116 116
117 } while (conn->cc_loop); 117 } while (conn->cc_loop);
118 118
119 out: 119 out:
120 /* Signal termination of the connection to all decipher threads */ 120 /* Signal termination of the connection to all decipher threads */
121 for (strid = 0; strid < conn->cc_sctp_para.pairs; strid++) { 121 for (strid = 0; strid < conn->cc_sctp_para.pairs; strid++) {
122 if (conn->cc_sctp3436_data.array[strid].raw_recv) { 122 if (conn->cc_sctp3436_data.array[strid].raw_recv) {
123 CHECK_FCT_DO(fd_event_send(conn->cc_sctp3436_data.array[strid].raw_recv, FDEVP_CNX_ERROR, 0, NULL), goto fatal ); 123 CHECK_FCT_DO(fd_event_send(conn->cc_sctp3436_data.array[strid].raw_recv, FDEVP_CNX_ERROR, 0, NULL), goto fatal );
124 } 124 }
125 } 125 }
126 fd_cnx_markerror(conn); 126 fd_cnx_markerror(conn);
127 TRACE_DEBUG(FULL, "Thread terminated"); 127 TRACE_DEBUG(FULL, "Thread terminated");
128 return NULL; 128 return NULL;
129 129
130 fatal: 130 fatal:
131 /* An unrecoverable error occurred, stop the daemon */ 131 /* An unrecoverable error occurred, stop the daemon */
132 CHECK_FCT_DO(fd_core_shutdown(), ); 132 CHECK_FCT_DO(fd_core_shutdown(), );
133 goto out; 133 goto out;
134 } 134 }
136 /* Decrypt the data received in this stream pair and store it in the target queue */ 136 /* Decrypt the data received in this stream pair and store it in the target queue */
137 static void * decipher(void * arg) 137 static void * decipher(void * arg)
138 { 138 {
139 struct sctp3436_ctx * ctx = arg; 139 struct sctp3436_ctx * ctx = arg;
140 struct cnxctx *cnx; 140 struct cnxctx *cnx;
141 141
142 TRACE_ENTRY("%p", arg); 142 TRACE_ENTRY("%p", arg);
143 CHECK_PARAMS_DO(ctx && ctx->raw_recv && ctx->parent, goto error); 143 CHECK_PARAMS_DO(ctx && ctx->raw_recv && ctx->parent, goto error);
144 cnx = ctx->parent; 144 cnx = ctx->parent;
145 ASSERT( fd_cnx_target_queue(cnx) ); 145 ASSERT( fd_cnx_target_queue(cnx) );
146 146
147 /* Set the thread name */ 147 /* Set the thread name */
148 { 148 {
149 char buf[48]; 149 char buf[100];
150 snprintf(buf, sizeof(buf), "Decipher (%hu@%d:%s)", ctx->strid, cnx->cc_socket, cnx->cc_remid); 150 snprintf(buf, sizeof(buf), "Decipher (%hu@%d:%s)", ctx->strid, cnx->cc_socket, cnx->cc_remid);
151 fd_log_threadname ( buf ); 151 fd_log_threadname ( buf );
152 } 152 }
153 153
154 /* The next function loops while there is no error */ 154 /* The next function loops while there is no error */
155 CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */); 155 CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */);
156 error: 156 error:
157 fd_cnx_markerror(cnx); 157 fd_cnx_markerror(cnx);
158 TRACE_DEBUG(FULL, "Thread terminated"); 158 TRACE_DEBUG(FULL, "Thread terminated");
159 return NULL; 159 return NULL;
160 } 160 }
161 161
162 /*************************************************************/ 162 /*************************************************************/
163 /* push / pull */ 163 /* push / pull */
168 static int sctp3436_pull_timeout(gnutls_transport_ptr_t tr, unsigned int ms) 168 static int sctp3436_pull_timeout(gnutls_transport_ptr_t tr, unsigned int ms)
169 { 169 {
170 struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr; 170 struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
171 struct timespec tsstore, *ts = NULL; 171 struct timespec tsstore, *ts = NULL;
172 int ret; 172 int ret;
173 173
174 TRACE_ENTRY("%p %d", tr, ms); 174 TRACE_ENTRY("%p %d", tr, ms);
175 175
176 if (ctx->partial.buf) 176 if (ctx->partial.buf)
177 return 1; /* data is already available for pull */ 177 return 1; /* data is already available for pull */
178 178
179 if (ms) { 179 if (ms) {
180 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &tsstore), return -1 ); 180 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &tsstore), return -1 );
181 tsstore.tv_nsec += (long)ms * 1000000; 181 tsstore.tv_nsec += (long)ms * 1000000;
182 tsstore.tv_sec += tsstore.tv_nsec / 1000000000L; 182 tsstore.tv_sec += tsstore.tv_nsec / 1000000000L;
183 tsstore.tv_nsec %= 1000000000L; 183 tsstore.tv_nsec %= 1000000000L;
184 ts = &tsstore; 184 ts = &tsstore;
185 } 185 }
186 186
187 ret = fd_fifo_select ( ctx->raw_recv, ts ); 187 ret = fd_fifo_select ( ctx->raw_recv, ts );
188 if (ret < 0) { 188 if (ret < 0) {
189 errno = -ret; 189 errno = -ret;
190 ret = -1; 190 ret = -1;
191 } 191 }
192 192
193 return ret; 193 return ret;
194 } 194 }
195 #endif /* GNUTLS_VERSION_300 */ 195 #endif /* GNUTLS_VERSION_300 */
196 196
197 /* Send data over the connection, called by gnutls */ 197 /* Send data over the connection, called by gnutls */
198 #ifndef GNUTLS_VERSION_212 198 #ifndef GNUTLS_VERSION_212
199 static ssize_t sctp3436_push(gnutls_transport_ptr_t tr, const void * data, size_t len) 199 static ssize_t sctp3436_push(gnutls_transport_ptr_t tr, const void * data, size_t len)
200 { 200 {
201 struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr; 201 struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
202 struct iovec iov; 202 struct iovec iov;
203 203
204 TRACE_ENTRY("%p %p %zd", tr, data, len); 204 TRACE_ENTRY("%p %p %zd", tr, data, len);
205 CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } ); 205 CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } );
206 206
207 iov.iov_base = (void *)data; 207 iov.iov_base = (void *)data;
208 iov.iov_len = len; 208 iov.iov_len = len;
209 209
210 return fd_sctp_sendstrv(ctx->parent, ctx->strid, &iov, 1); 210 return fd_sctp_sendstrv(ctx->parent, ctx->strid, &iov, 1);
211 } 211 }
212 #else /* GNUTLS_VERSION_212 */ 212 #else /* GNUTLS_VERSION_212 */
213 static ssize_t sctp3436_pushv(gnutls_transport_ptr_t tr, const giovec_t * iov, int iovcnt) 213 static ssize_t sctp3436_pushv(gnutls_transport_ptr_t tr, const giovec_t * iov, int iovcnt)
214 { 214 {
215 struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr; 215 struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
216 216
217 TRACE_ENTRY("%p %p %d", tr, iov, iovcnt); 217 TRACE_ENTRY("%p %p %d", tr, iov, iovcnt);
218 CHECK_PARAMS_DO( tr && iov, { errno = EINVAL; return -1; } ); 218 CHECK_PARAMS_DO( tr && iov, { errno = EINVAL; return -1; } );
219 219
220 return fd_sctp_sendstrv(ctx->parent, ctx->strid, (const struct iovec *)iov, iovcnt); 220 return fd_sctp_sendstrv(ctx->parent, ctx->strid, (const struct iovec *)iov, iovcnt);
221 } 221 }
222 #endif /* GNUTLS_VERSION_212 */ 222 #endif /* GNUTLS_VERSION_212 */
223 223
224 /* Retrieve data received on a stream and already demultiplexed */ 224 /* Retrieve data received on a stream and already demultiplexed */
225 static ssize_t sctp3436_pull(gnutls_transport_ptr_t tr, void * buf, size_t len) 225 static ssize_t sctp3436_pull(gnutls_transport_ptr_t tr, void * buf, size_t len)
226 { 226 {
227 struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr; 227 struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
228 size_t pulled = 0; 228 size_t pulled = 0;
229 int emptied; 229 int emptied;
230 230
231 TRACE_ENTRY("%p %p %zd", tr, buf, len); 231 TRACE_ENTRY("%p %p %zd", tr, buf, len);
232 CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; goto error; } ); 232 CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; goto error; } );
233 233
234 /* If we don't have data available now, pull new message from the fifo -- this is blocking (until the queue is destroyed) */ 234 /* If we don't have data available now, pull new message from the fifo -- this is blocking (until the queue is destroyed) */
235 if (!ctx->partial.buf) { 235 if (!ctx->partial.buf) {
236 int ev; 236 int ev;
237 CHECK_FCT_DO( errno = fd_event_get(ctx->raw_recv, &ev, &ctx->partial.bufsz, (void *)&ctx->partial.buf), goto error ); 237 CHECK_FCT_DO( errno = fd_event_get(ctx->raw_recv, &ev, &ctx->partial.bufsz, (void *)&ctx->partial.buf), goto error );
238 if (ev == FDEVP_CNX_ERROR) { 238 if (ev == FDEVP_CNX_ERROR) {
239 /* Documentations says to return 0 on connection closed, but it does hang within gnutls_handshake */ 239 /* Documentations says to return 0 on connection closed, but it does hang within gnutls_handshake */
240 return -1; 240 return -1;
241 } 241 }
242 } 242 }
243 243
244 pulled = ctx->partial.bufsz - ctx->partial.offset; 244 pulled = ctx->partial.bufsz - ctx->partial.offset;
245 if (pulled <= len) { 245 if (pulled <= len) {
246 emptied = 1; 246 emptied = 1;
247 } else { 247 } else {
248 /* limit to the capacity of destination buffer */ 248 /* limit to the capacity of destination buffer */
261 ctx->partial.offset += pulled; 261 ctx->partial.offset += pulled;
262 } 262 }
263 263
264 /* We are done */ 264 /* We are done */
265 return pulled; 265 return pulled;
266 266
267 error: 267 error:
268 gnutls_transport_set_errno (ctx->session, errno); 268 gnutls_transport_set_errno (ctx->session, errno);
269 return -1; 269 return -1;
270 } 270 }
271 271
275 #endif /* !GNUTLS_VERSION_300 */ 275 #endif /* !GNUTLS_VERSION_300 */
276 static void set_sess_transport(gnutls_session_t session, struct sctp3436_ctx *ctx) 276 static void set_sess_transport(gnutls_session_t session, struct sctp3436_ctx *ctx)
277 { 277 {
278 /* Set the transport pointer passed to push & pull callbacks */ 278 /* Set the transport pointer passed to push & pull callbacks */
279 GNUTLS_TRACE( gnutls_transport_set_ptr( session, (gnutls_transport_ptr_t) ctx ) ); 279 GNUTLS_TRACE( gnutls_transport_set_ptr( session, (gnutls_transport_ptr_t) ctx ) );
280 280
281 /* Reset the low water value, since we don't use sockets */ 281 /* Reset the low water value, since we don't use sockets */
282 #ifndef GNUTLS_VERSION_300 282 #ifndef GNUTLS_VERSION_300
283 /* starting version 2.12, this call is not needed */ 283 /* starting version 2.12, this call is not needed */
284 GNUTLS_TRACE( gnutls_transport_set_lowat( session, 0 ) ); 284 GNUTLS_TRACE( gnutls_transport_set_lowat( session, 0 ) );
285 #else /* GNUTLS_VERSION_300 */ 285 #else /* GNUTLS_VERSION_300 */
286 /* but in 3.0 we have to provide the pull_timeout callback */ 286 /* but in 3.0 we have to provide the pull_timeout callback */
287 GNUTLS_TRACE( gnutls_transport_set_pull_timeout_function( session, sctp3436_pull_timeout ) ); 287 GNUTLS_TRACE( gnutls_transport_set_pull_timeout_function( session, sctp3436_pull_timeout ) );
288 #endif /* GNUTLS_VERSION_300 */ 288 #endif /* GNUTLS_VERSION_300 */
289 289
290 /* Set the push and pull callbacks */ 290 /* Set the push and pull callbacks */
291 GNUTLS_TRACE( gnutls_transport_set_pull_function(session, sctp3436_pull) ); 291 GNUTLS_TRACE( gnutls_transport_set_pull_function(session, sctp3436_pull) );
292 #ifndef GNUTLS_VERSION_212 292 #ifndef GNUTLS_VERSION_212
293 GNUTLS_TRACE( gnutls_transport_set_push_function(session, sctp3436_push) ); 293 GNUTLS_TRACE( gnutls_transport_set_push_function(session, sctp3436_push) );
294 #else /* GNUTLS_VERSION_212 */ 294 #else /* GNUTLS_VERSION_212 */
322 /* Initialize the store area for a connection */ 322 /* Initialize the store area for a connection */
323 static int store_init(struct cnxctx * conn) 323 static int store_init(struct cnxctx * conn)
324 { 324 {
325 TRACE_ENTRY("%p", conn); 325 TRACE_ENTRY("%p", conn);
326 CHECK_PARAMS( conn && !conn->cc_sctp3436_data.sess_store ); 326 CHECK_PARAMS( conn && !conn->cc_sctp3436_data.sess_store );
327 327
328 CHECK_MALLOC( conn->cc_sctp3436_data.sess_store = malloc(sizeof(struct sr_store)) ); 328 CHECK_MALLOC( conn->cc_sctp3436_data.sess_store = malloc(sizeof(struct sr_store)) );
329 memset(conn->cc_sctp3436_data.sess_store, 0, sizeof(struct sr_store)); 329 memset(conn->cc_sctp3436_data.sess_store, 0, sizeof(struct sr_store));
330 330
331 fd_list_init(&conn->cc_sctp3436_data.sess_store->list, NULL); 331 fd_list_init(&conn->cc_sctp3436_data.sess_store->list, NULL);
332 CHECK_POSIX( pthread_rwlock_init(&conn->cc_sctp3436_data.sess_store->lock, NULL) ); 332 CHECK_POSIX( pthread_rwlock_init(&conn->cc_sctp3436_data.sess_store->lock, NULL) );
333 conn->cc_sctp3436_data.sess_store->parent = conn; 333 conn->cc_sctp3436_data.sess_store->parent = conn;
334 334
335 return 0; 335 return 0;
336 } 336 }
337 337
338 /* Destroy the store area for a connection, and all its content */ 338 /* Destroy the store area for a connection, and all its content */
339 static void store_destroy(struct cnxctx * conn) 339 static void store_destroy(struct cnxctx * conn)
340 { 340 {
341 /* Del all list entries */ 341 /* Del all list entries */
342 TRACE_ENTRY("%p", conn); 342 TRACE_ENTRY("%p", conn);
343 CHECK_PARAMS_DO( conn, return ); 343 CHECK_PARAMS_DO( conn, return );
344 344
345 if (!conn->cc_sctp3436_data.sess_store) 345 if (!conn->cc_sctp3436_data.sess_store)
346 return; 346 return;
347 347
348 CHECK_POSIX_DO( pthread_rwlock_destroy(&conn->cc_sctp3436_data.sess_store->lock), /* continue */ ); 348 CHECK_POSIX_DO( pthread_rwlock_destroy(&conn->cc_sctp3436_data.sess_store->lock), /* continue */ );
349 349
350 while (!FD_IS_LIST_EMPTY(&conn->cc_sctp3436_data.sess_store->list)) { 350 while (!FD_IS_LIST_EMPTY(&conn->cc_sctp3436_data.sess_store->list)) {
351 struct sr_data * sr = (struct sr_data *) conn->cc_sctp3436_data.sess_store->list.next; 351 struct sr_data * sr = (struct sr_data *) conn->cc_sctp3436_data.sess_store->list.next;
352 fd_list_unlink( &sr->chain ); 352 fd_list_unlink( &sr->chain );
353 free(sr->key.data); 353 free(sr->key.data);
354 free(sr->data.data); 354 free(sr->data.data);
355 free(sr); 355 free(sr);
356 } 356 }
357 357
358 free(conn->cc_sctp3436_data.sess_store); 358 free(conn->cc_sctp3436_data.sess_store);
359 conn->cc_sctp3436_data.sess_store = NULL; 359 conn->cc_sctp3436_data.sess_store = NULL;
360 return; 360 return;
361 } 361 }
362 362
363 /* Search the position (or next if not found) of a key in a store */ 363 /* Search the position (or next if not found) of a key in a store */
364 static struct fd_list * find_or_next(struct sr_store * sto, gnutls_datum_t key, int * match) 364 static struct fd_list * find_or_next(struct sr_store * sto, gnutls_datum_t key, int * match)
365 { 365 {
366 struct fd_list * ret; 366 struct fd_list * ret;
367 *match = 0; 367 *match = 0;
368 368
369 for (ret = sto->list.next; ret != &sto->list; ret = ret->next) { 369 for (ret = sto->list.next; ret != &sto->list; ret = ret->next) {
370 int cmp = 0; 370 int cmp = 0;
371 struct sr_data * sr = (struct sr_data *)ret; 371 struct sr_data * sr = (struct sr_data *)ret;
372 372
373 cmp = fd_os_cmp(key.data, key.size, sr->key.data, sr->key.size); 373 cmp = fd_os_cmp(key.data, key.size, sr->key.data, sr->key.size);
374 if (cmp > 0) 374 if (cmp > 0)
375 continue; 375 continue;
376 376
377 if (cmp == 0) 377 if (cmp == 0)
378 *match = 1; 378 *match = 1;
379 379
380 break; 380 break;
381 } 381 }
382 382
383 return ret; 383 return ret;
384 } 384 }
385 385
386 /* Callbacks for the TLS server side of the connection, called during gnutls_handshake */ 386 /* Callbacks for the TLS server side of the connection, called during gnutls_handshake */
387 static int sr_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data) 387 static int sr_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data)
389 struct sr_store * sto = (struct sr_store *)dbf; 389 struct sr_store * sto = (struct sr_store *)dbf;
390 struct fd_list * li; 390 struct fd_list * li;
391 struct sr_data * sr; 391 struct sr_data * sr;
392 int match = 0; 392 int match = 0;
393 int ret = 0; 393 int ret = 0;
394 394
395 TRACE_DEBUG( GNUTLS_DBG_LEVEL, "GNUTLS Callback: %s", __PRETTY_FUNCTION__ ); 395 TRACE_DEBUG( GNUTLS_DBG_LEVEL, "GNUTLS Callback: %s", __PRETTY_FUNCTION__ );
396 CHECK_PARAMS_DO( sto && key.data && data.data, return -1 ); 396 CHECK_PARAMS_DO( sto && key.data && data.data, return -1 );
397 397
398 CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 ); 398 CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 );
399 TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Session store [key ", key.data, key.size, "]"); 399 TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Session store [key ", key.data, key.size, "]");
400 400
401 li = find_or_next(sto, key, &match); 401 li = find_or_next(sto, key, &match);
402 if (match) { 402 if (match) {
403 sr = (struct sr_data *)li; 403 sr = (struct sr_data *)li;
404 404
405 /* Check the data is the same */ 405 /* Check the data is the same */
406 if ((data.size != sr->data.size) || memcmp(data.data, sr->data.data, data.size)) { 406 if ((data.size != sr->data.size) || memcmp(data.data, sr->data.data, data.size)) {
407 TRACE_DEBUG(INFO, "GnuTLS tried to store a session with same key and different data!"); 407 TRACE_DEBUG(INFO, "GnuTLS tried to store a session with same key and different data!");
408 TRACE_BUFFER(FD_LOG_DEBUG, INFO, "Session store [key ", key.data, key.size, "]"); 408 TRACE_BUFFER(FD_LOG_DEBUG, INFO, "Session store [key ", key.data, key.size, "]");
409 TRACE_BUFFER(FD_LOG_DEBUG, INFO, " -- old data [", sr->data.data, sr->data.size, "]"); 409 TRACE_BUFFER(FD_LOG_DEBUG, INFO, " -- old data [", sr->data.data, sr->data.size, "]");
410 TRACE_BUFFER(FD_LOG_DEBUG, INFO, " -- new data [", data.data, data.size, "]"); 410 TRACE_BUFFER(FD_LOG_DEBUG, INFO, " -- new data [", data.data, data.size, "]");
411 411
412 ret = -1; 412 ret = -1;
413 } else { 413 } else {
414 TRACE_DEBUG(GNUTLS_DBG_LEVEL, "GnuTLS tried to store a session with same key and same data, skipped."); 414 TRACE_DEBUG(GNUTLS_DBG_LEVEL, "GnuTLS tried to store a session with same key and same data, skipped.");
415 } 415 }
416 goto out; 416 goto out;
417 } 417 }
418 418
419 /* Create a new entry */ 419 /* Create a new entry */
420 CHECK_MALLOC_DO( sr = malloc(sizeof(struct sr_data)), { ret = -1; goto out; } ); 420 CHECK_MALLOC_DO( sr = malloc(sizeof(struct sr_data)), { ret = -1; goto out; } );
421 memset(sr, 0, sizeof(struct sr_data)); 421 memset(sr, 0, sizeof(struct sr_data));
422 422
423 fd_list_init(&sr->chain, sr); 423 fd_list_init(&sr->chain, sr);
427 memcpy(sr->key.data, key.data, key.size); 427 memcpy(sr->key.data, key.data, key.size);
428 428
429 CHECK_MALLOC_DO( sr->data.data = malloc(data.size), { ret = -1; goto out; } ); 429 CHECK_MALLOC_DO( sr->data.data = malloc(data.size), { ret = -1; goto out; } );
430 sr->data.size = data.size; 430 sr->data.size = data.size;
431 memcpy(sr->data.data, data.data, data.size); 431 memcpy(sr->data.data, data.data, data.size);
432 432
433 /* Save this new entry in the list, we are done */ 433 /* Save this new entry in the list, we are done */
434 fd_list_insert_before(li, &sr->chain); 434 fd_list_insert_before(li, &sr->chain);
435 435
436 out: 436 out:
437 CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return -1 ); 437 CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return -1 );
438 return ret; 438 return ret;
439 } 439 }
440 440
441 static int sr_remove (void *dbf, gnutls_datum_t key) 441 static int sr_remove (void *dbf, gnutls_datum_t key)
443 struct sr_store * sto = (struct sr_store *)dbf; 443 struct sr_store * sto = (struct sr_store *)dbf;
444 struct fd_list * li; 444 struct fd_list * li;
445 struct sr_data * sr; 445 struct sr_data * sr;
446 int match = 0; 446 int match = 0;
447 int ret = 0; 447 int ret = 0;
448 448
449 TRACE_DEBUG( GNUTLS_DBG_LEVEL, "GNUTLS Callback: %s", __PRETTY_FUNCTION__ ); 449 TRACE_DEBUG( GNUTLS_DBG_LEVEL, "GNUTLS Callback: %s", __PRETTY_FUNCTION__ );
450 CHECK_PARAMS_DO( sto && key.data, return -1 ); 450 CHECK_PARAMS_DO( sto && key.data, return -1 );
451 451
452 CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 ); 452 CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 );
453 TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Session delete [key ", key.data, key.size, "]"); 453 TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Session delete [key ", key.data, key.size, "]");
454 454
455 li = find_or_next(sto, key, &match); 455 li = find_or_next(sto, key, &match);
456 if (match) { 456 if (match) {
457 sr = (struct sr_data *)li; 457 sr = (struct sr_data *)li;
458 458
459 /* Destroy this data */ 459 /* Destroy this data */
460 fd_list_unlink(li); 460 fd_list_unlink(li);
461 free(sr->key.data); 461 free(sr->key.data);
462 free(sr->data.data); 462 free(sr->data.data);
463 free(sr); 463 free(sr);
464 } else { 464 } else {
465 /* It was not found */ 465 /* It was not found */
466 ret = -1; 466 ret = -1;
467 } 467 }
468 468
469 CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return -1 ); 469 CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return -1 );
470 return ret; 470 return ret;
471 } 471 }
472 472
473 static gnutls_datum_t sr_fetch (void *dbf, gnutls_datum_t key) 473 static gnutls_datum_t sr_fetch (void *dbf, gnutls_datum_t key)
482 TRACE_DEBUG( GNUTLS_DBG_LEVEL, "GNUTLS Callback: %s", __PRETTY_FUNCTION__ ); 482 TRACE_DEBUG( GNUTLS_DBG_LEVEL, "GNUTLS Callback: %s", __PRETTY_FUNCTION__ );
483 CHECK_PARAMS_DO( sto && key.data, return error ); 483 CHECK_PARAMS_DO( sto && key.data, return error );
484 484
485 CHECK_POSIX_DO( pthread_rwlock_rdlock(&sto->lock), return error ); 485 CHECK_POSIX_DO( pthread_rwlock_rdlock(&sto->lock), return error );
486 TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Session fetch [key ", key.data, key.size, "]"); 486 TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Session fetch [key ", key.data, key.size, "]");
487 487
488 li = find_or_next(sto, key, &match); 488 li = find_or_next(sto, key, &match);
489 if (match) { 489 if (match) {
490 sr = (struct sr_data *)li; 490 sr = (struct sr_data *)li;
491 GNUTLS_TRACE( CHECK_MALLOC_DO(res.data = gnutls_malloc(sr->data.size), goto out ) ); 491 GNUTLS_TRACE( CHECK_MALLOC_DO(res.data = gnutls_malloc(sr->data.size), goto out ) );
492 res.size = sr->data.size; 492 res.size = sr->data.size;
493 memcpy(res.data, sr->data.data, res.size); 493 memcpy(res.data, sr->data.data, res.size);
494 } 494 }
495 out: 495 out:
496 TRACE_DEBUG(GNUTLS_DBG_LEVEL, "Fetched (%p, %d) from store %p", res.data, res.size, sto); 496 TRACE_DEBUG(GNUTLS_DBG_LEVEL, "Fetched (%p, %d) from store %p", res.data, res.size, sto);
497 CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return error); 497 CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return error);
498 return res; 498 return res;
499 } 499 }
500 500
501 /* Set the session pointer in a session object */ 501 /* Set the session pointer in a session object */
502 static void set_resume_callbacks(gnutls_session_t session, struct cnxctx * conn) 502 static void set_resume_callbacks(gnutls_session_t session, struct cnxctx * conn)
503 { 503 {
504 TRACE_ENTRY("%p", conn); 504 TRACE_ENTRY("%p", conn);
505 505
506 GNUTLS_TRACE( gnutls_db_set_retrieve_function(session, sr_fetch)); 506 GNUTLS_TRACE( gnutls_db_set_retrieve_function(session, sr_fetch));
507 GNUTLS_TRACE( gnutls_db_set_remove_function (session, sr_remove)); 507 GNUTLS_TRACE( gnutls_db_set_remove_function (session, sr_remove));
508 GNUTLS_TRACE( gnutls_db_set_store_function (session, sr_store)); 508 GNUTLS_TRACE( gnutls_db_set_store_function (session, sr_store));
509 GNUTLS_TRACE( gnutls_db_set_ptr (session, conn->cc_sctp3436_data.sess_store)); 509 GNUTLS_TRACE( gnutls_db_set_ptr (session, conn->cc_sctp3436_data.sess_store));
510 510
511 return; 511 return;
512 } 512 }
513 513
514 /* The handshake is made in parallel in several threads to speed up */ 514 /* The handshake is made in parallel in several threads to speed up */
515 static void * handshake_resume_th(void * arg) 515 static void * handshake_resume_th(void * arg)
516 { 516 {
517 struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) arg; 517 struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) arg;
518 int resumed; 518 int resumed;
519 519
520 TRACE_ENTRY("%p", arg); 520 TRACE_ENTRY("%p", arg);
521 521
522 /* Set the thread name */ 522 /* Set the thread name */
523 { 523 {
524 char buf[48]; 524 char buf[48];
525 snprintf(buf, sizeof(buf), "Handshake resume (%hu@%d)", ctx->strid, ctx->parent->cc_socket); 525 snprintf(buf, sizeof(buf), "Handshake resume (%hu@%d)", ctx->strid, ctx->parent->cc_socket);
526 fd_log_threadname ( buf ); 526 fd_log_threadname ( buf );
527 } 527 }
528 528
529 TRACE_DEBUG(FULL, "Starting TLS resumed handshake on stream %hu", ctx->strid); 529 TRACE_DEBUG(FULL, "Starting TLS resumed handshake on stream %hu", ctx->strid);
530 530
531 CHECK_GNUTLS_DO( gnutls_handshake( ctx->session ), return NULL); 531 CHECK_GNUTLS_DO( gnutls_handshake( ctx->session ), return NULL);
532 532
533 GNUTLS_TRACE( resumed = gnutls_session_is_resumed(ctx->session) ); 533 GNUTLS_TRACE( resumed = gnutls_session_is_resumed(ctx->session) );
534 #ifndef GNUTLS_VERSION_300 534 #ifndef GNUTLS_VERSION_300
535 if (!resumed) { 535 if (!resumed) {
536 /* Check the credentials here also */ 536 /* Check the credentials here also */
537 CHECK_FCT_DO( fd_tls_verify_credentials(ctx->session, ctx->parent, 0), return NULL ); 537 CHECK_FCT_DO( fd_tls_verify_credentials(ctx->session, ctx->parent, 0), return NULL );
542 fd_log_debug("Session was resumed successfully on stream %hu (conn: '%s')", ctx->strid, fd_cnx_getid(ctx->parent)); 542 fd_log_debug("Session was resumed successfully on stream %hu (conn: '%s')", ctx->strid, fd_cnx_getid(ctx->parent));
543 } else { 543 } else {
544 fd_log_debug("Session was NOT resumed on stream %hu (full handshake) (conn: '%s')", ctx->strid, fd_cnx_getid(ctx->parent)); 544 fd_log_debug("Session was NOT resumed on stream %hu (full handshake) (conn: '%s')", ctx->strid, fd_cnx_getid(ctx->parent));
545 } 545 }
546 } 546 }
547 547
548 /* Finished, OK */ 548 /* Finished, OK */
549 return arg; 549 return arg;
550 } 550 }
551 551
552 552
556 556
557 /* Initialize the wrapper for the connection */ 557 /* Initialize the wrapper for the connection */
558 int fd_sctp3436_init(struct cnxctx * conn) 558 int fd_sctp3436_init(struct cnxctx * conn)
559 { 559 {
560 uint16_t i; 560 uint16_t i;
561 561
562 TRACE_ENTRY("%p", conn); 562 TRACE_ENTRY("%p", conn);
563 CHECK_PARAMS( conn && (conn->cc_sctp_para.pairs > 1) && (!conn->cc_sctp3436_data.array) ); 563 CHECK_PARAMS( conn && (conn->cc_sctp_para.pairs > 1) && (!conn->cc_sctp3436_data.array) );
564 564
565 /* First, alloc the array and initialize the non-TLS data */ 565 /* First, alloc the array and initialize the non-TLS data */
566 CHECK_MALLOC( conn->cc_sctp3436_data.array = calloc(conn->cc_sctp_para.pairs, sizeof(struct sctp3436_ctx)) ); 566 CHECK_MALLOC( conn->cc_sctp3436_data.array = calloc(conn->cc_sctp_para.pairs, sizeof(struct sctp3436_ctx)) );
567 for (i = 0; i < conn->cc_sctp_para.pairs; i++) { 567 for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
568 conn->cc_sctp3436_data.array[i].parent = conn; 568 conn->cc_sctp3436_data.array[i].parent = conn;
569 conn->cc_sctp3436_data.array[i].strid = i; 569 conn->cc_sctp3436_data.array[i].strid = i;
570 CHECK_FCT( fd_fifo_new(&conn->cc_sctp3436_data.array[i].raw_recv, 10) ); 570 CHECK_FCT( fd_fifo_new(&conn->cc_sctp3436_data.array[i].raw_recv, 10) );
571 } 571 }
572 572
573 /* Set push/pull functions in the master session, using fifo in array[0] */ 573 /* Set push/pull functions in the master session, using fifo in array[0] */
574 set_sess_transport(conn->cc_tls_para.session, &conn->cc_sctp3436_data.array[0]); 574 set_sess_transport(conn->cc_tls_para.session, &conn->cc_sctp3436_data.array[0]);
575 575
576 /* For server side, we also initialize the resuming capabilities */ 576 /* For server side, we also initialize the resuming capabilities */
577 if (conn->cc_tls_para.mode == GNUTLS_SERVER) { 577 if (conn->cc_tls_para.mode == GNUTLS_SERVER) {
578 578
579 /* Prepare the store for sessions data */ 579 /* Prepare the store for sessions data */
580 CHECK_FCT( store_init(conn) ); 580 CHECK_FCT( store_init(conn) );
581 581
582 /* Set the callbacks for resuming in the master session */ 582 /* Set the callbacks for resuming in the master session */
583 set_resume_callbacks(conn->cc_tls_para.session, conn); 583 set_resume_callbacks(conn->cc_tls_para.session, conn);
584 } 584 }
585 585
586 /* Start the demux thread */ 586 /* Start the demux thread */
587 CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, demuxer, conn ) ); 587 CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, demuxer, conn ) );
588 588
589 return 0; 589 return 0;
590 } 590 }
591 591
592 /* Handshake other streams, after full handshake on the master session */ 592 /* Handshake other streams, after full handshake on the master session */
593 int fd_sctp3436_handshake_others(struct cnxctx * conn, char * priority, void * alt_creds) 593 int fd_sctp3436_handshake_others(struct cnxctx * conn, char * priority, void * alt_creds)
594 { 594 {
595 uint16_t i; 595 uint16_t i;
596 int errors = 0; 596 int errors = 0;
597 gnutls_datum_t master_data; 597 gnutls_datum_t master_data;
598 598
599 TRACE_ENTRY("%p %p", conn, priority); 599 TRACE_ENTRY("%p %p", conn, priority);
600 CHECK_PARAMS( conn && (conn->cc_sctp_para.pairs > 1) && conn->cc_sctp3436_data.array ); 600 CHECK_PARAMS( conn && (conn->cc_sctp_para.pairs > 1) && conn->cc_sctp3436_data.array );
601 601
602 /* Server side: we set all the parameters, the resume callback will take care of resuming the session */ 602 /* Server side: we set all the parameters, the resume callback will take care of resuming the session */
603 /* Client side: we duplicate the parameters of the master session, then set the transport pointer */ 603 /* Client side: we duplicate the parameters of the master session, then set the transport pointer */
604 604
605 /* For client side, retrieve the master session parameters */ 605 /* For client side, retrieve the master session parameters */
606 if (conn->cc_tls_para.mode == GNUTLS_CLIENT) { 606 if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
607 CHECK_GNUTLS_DO( gnutls_session_get_data2(conn->cc_tls_para.session, &master_data), return ENOMEM ); 607 CHECK_GNUTLS_DO( gnutls_session_get_data2(conn->cc_tls_para.session, &master_data), return ENOMEM );
608 /* For debug: */ 608 /* For debug: */
609 if (TRACE_BOOL(GNUTLS_DBG_LEVEL)) { 609 if (TRACE_BOOL(GNUTLS_DBG_LEVEL)) {
611 size_t ids = sizeof(id); 611 size_t ids = sizeof(id);
612 CHECK_GNUTLS_DO( gnutls_session_get_id(conn->cc_tls_para.session, id, &ids), /* continue */ ); 612 CHECK_GNUTLS_DO( gnutls_session_get_id(conn->cc_tls_para.session, id, &ids), /* continue */ );
613 TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Master session id: [", id, ids, "]"); 613 TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Master session id: [", id, ids, "]");
614 } 614 }
615 } 615 }
616 616
617 /* Initialize the session objects and start the handshake in a separate thread */ 617 /* Initialize the session objects and start the handshake in a separate thread */
618 for (i = 1; i < conn->cc_sctp_para.pairs; i++) { 618 for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
619 /* Set credentials and priority */ 619 /* Set credentials and priority */
620 CHECK_FCT( fd_tls_prepare(&conn->cc_sctp3436_data.array[i].session, conn->cc_tls_para.mode, 0, priority, alt_creds) ); 620 CHECK_FCT( fd_tls_prepare(&conn->cc_sctp3436_data.array[i].session, conn->cc_tls_para.mode, 0, priority, alt_creds) );
621 621
622 /* additional initialization for gnutls 3.x */ 622 /* additional initialization for gnutls 3.x */
623 #ifdef GNUTLS_VERSION_300 623 #ifdef GNUTLS_VERSION_300
624 /* the verify function has already been set in the global initialization in config.c */ 624 /* the verify function has already been set in the global initialization in config.c */
625 625
626 /* fd_tls_verify_credentials_2 uses the connection */ 626 /* fd_tls_verify_credentials_2 uses the connection */
641 if (conn->cc_tls_para.mode == GNUTLS_CLIENT) { 641 if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
642 CHECK_GNUTLS_DO( gnutls_session_set_data(conn->cc_sctp3436_data.array[i].session, master_data.data, master_data.size), return ENOMEM ); 642 CHECK_GNUTLS_DO( gnutls_session_set_data(conn->cc_sctp3436_data.array[i].session, master_data.data, master_data.size), return ENOMEM );
643 } else { 643 } else {
644 set_resume_callbacks(conn->cc_sctp3436_data.array[i].session, conn); 644 set_resume_callbacks(conn->cc_sctp3436_data.array[i].session, conn);
645 } 645 }
646 646
647 /* Set transport parameters */ 647 /* Set transport parameters */
648 set_sess_transport(conn->cc_sctp3436_data.array[i].session, &conn->cc_sctp3436_data.array[i]); 648 set_sess_transport(conn->cc_sctp3436_data.array[i].session, &conn->cc_sctp3436_data.array[i]);
649 649
650 /* Start the handshake thread */ 650 /* Start the handshake thread */
651 CHECK_POSIX( pthread_create( &conn->cc_sctp3436_data.array[i].thr, NULL, handshake_resume_th, &conn->cc_sctp3436_data.array[i] ) ); 651 CHECK_POSIX( pthread_create( &conn->cc_sctp3436_data.array[i].thr, NULL, handshake_resume_th, &conn->cc_sctp3436_data.array[i] ) );
652 } 652 }
653 653
654 /* We can now release the memory of master session data if any */ 654 /* We can now release the memory of master session data if any */
655 if (conn->cc_tls_para.mode == GNUTLS_CLIENT) { 655 if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
656 GNUTLS_TRACE( gnutls_free(master_data.data) ); 656 GNUTLS_TRACE( gnutls_free(master_data.data) );
657 } 657 }
658 658
659 /* Now wait for all handshakes to finish */ 659 /* Now wait for all handshakes to finish */
660 for (i = 1; i < conn->cc_sctp_para.pairs; i++) { 660 for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
661 void * ret; 661 void * ret;
662 CHECK_POSIX( pthread_join(conn->cc_sctp3436_data.array[i].thr, &ret) ); 662 CHECK_POSIX( pthread_join(conn->cc_sctp3436_data.array[i].thr, &ret) );
663 conn->cc_sctp3436_data.array[i].thr = (pthread_t) NULL; 663 conn->cc_sctp3436_data.array[i].thr = (pthread_t) NULL;
664 if (ret == NULL) { 664 if (ret == NULL) {
665 errors++; /* Handshake failed on this stream */ 665 errors++; /* Handshake failed on this stream */
666 } 666 }
667 } 667 }
668 668
669 if (errors) { 669 if (errors) {
670 TRACE_DEBUG(INFO, "Handshake failed on %d/%hd stream pairs", errors, conn->cc_sctp_para.pairs); 670 TRACE_DEBUG(INFO, "Handshake failed on %d/%hd stream pairs", errors, conn->cc_sctp_para.pairs);
671 fd_cnx_markerror(conn); 671 fd_cnx_markerror(conn);
672 return ENOTCONN; 672 return ENOTCONN;
673 } 673 }
674 674
675 return 0; 675 return 0;
676 } 676 }
677 677
678 /* Receive messages from others ? all other stream pairs : the master pair */ 678 /* Receive messages from others ? all other stream pairs : the master pair */
679 int fd_sctp3436_startthreads(struct cnxctx * conn, int others) 679 int fd_sctp3436_startthreads(struct cnxctx * conn, int others)
680 { 680 {
681 uint16_t i; 681 uint16_t i;
682 682
683 TRACE_ENTRY("%p", conn); 683 TRACE_ENTRY("%p", conn);
684 CHECK_PARAMS( conn && conn->cc_sctp3436_data.array ); 684 CHECK_PARAMS( conn && conn->cc_sctp3436_data.array );
685 685
686 if (others) { 686 if (others) {
687 for (i = 1; i < conn->cc_sctp_para.pairs; i++) { 687 for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
688 688
689 /* Start the decipher thread */ 689 /* Start the decipher thread */
690 CHECK_POSIX( pthread_create( &conn->cc_sctp3436_data.array[i].thr, NULL, decipher, &conn->cc_sctp3436_data.array[i] ) ); 690 CHECK_POSIX( pthread_create( &conn->cc_sctp3436_data.array[i].thr, NULL, decipher, &conn->cc_sctp3436_data.array[i] ) );
697 697
698 /* Initiate a "bye" on all stream pairs */ 698 /* Initiate a "bye" on all stream pairs */
699 void fd_sctp3436_bye(struct cnxctx * conn) 699 void fd_sctp3436_bye(struct cnxctx * conn)
700 { 700 {
701 uint16_t i; 701 uint16_t i;
702 702
703 CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return ); 703 CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return );
704 704
705 /* End all TLS sessions, in series (not as efficient as paralel, but simpler) */ 705 /* End all TLS sessions, in series (not as efficient as paralel, but simpler) */
706 for (i = 1; i < conn->cc_sctp_para.pairs; i++) { 706 for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
707 if ( ! fd_cnx_teststate(conn, CC_STATUS_ERROR)) { 707 if ( ! fd_cnx_teststate(conn, CC_STATUS_ERROR)) {
708 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctp3436_data.array[i].session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) ); 708 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctp3436_data.array[i].session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) );
709 } 709 }
712 712
713 /* After "bye" was sent on all streams, read from sessions until an error is received */ 713 /* After "bye" was sent on all streams, read from sessions until an error is received */
714 void fd_sctp3436_waitthreadsterm(struct cnxctx * conn) 714 void fd_sctp3436_waitthreadsterm(struct cnxctx * conn)
715 { 715 {
716 uint16_t i; 716 uint16_t i;
717 717
718 TRACE_ENTRY("%p", conn); 718 TRACE_ENTRY("%p", conn);
719 CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return ); 719 CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return );
720 720
721 for (i = 0; i < conn->cc_sctp_para.pairs; i++) { 721 for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
722 if (conn->cc_sctp3436_data.array[i].thr != (pthread_t)NULL) { 722 if (conn->cc_sctp3436_data.array[i].thr != (pthread_t)NULL) {
723 CHECK_POSIX_DO( pthread_join(conn->cc_sctp3436_data.array[i].thr, NULL), /* continue */ ); 723 CHECK_POSIX_DO( pthread_join(conn->cc_sctp3436_data.array[i].thr, NULL), /* continue */ );
724 conn->cc_sctp3436_data.array[i].thr = (pthread_t)NULL; 724 conn->cc_sctp3436_data.array[i].thr = (pthread_t)NULL;
725 } 725 }
729 729
730 /* Free gnutls resources of all sessions */ 730 /* Free gnutls resources of all sessions */
731 void fd_sctp3436_gnutls_deinit_others(struct cnxctx * conn) 731 void fd_sctp3436_gnutls_deinit_others(struct cnxctx * conn)
732 { 732 {
733 uint16_t i; 733 uint16_t i;
734 734
735 TRACE_ENTRY("%p", conn); 735 TRACE_ENTRY("%p", conn);
736 CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return ); 736 CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return );
737 737
738 for (i = 1; i < conn->cc_sctp_para.pairs; i++) { 738 for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
739 if (conn->cc_sctp3436_data.array[i].session) { 739 if (conn->cc_sctp3436_data.array[i].session) {
740 GNUTLS_TRACE( gnutls_deinit(conn->cc_sctp3436_data.array[i].session) ); 740 GNUTLS_TRACE( gnutls_deinit(conn->cc_sctp3436_data.array[i].session) );
741 conn->cc_sctp3436_data.array[i].session = NULL; 741 conn->cc_sctp3436_data.array[i].session = NULL;
742 } 742 }
746 746
747 /* Stop all receiver threads */ 747 /* Stop all receiver threads */
748 void fd_sctp3436_stopthreads(struct cnxctx * conn) 748 void fd_sctp3436_stopthreads(struct cnxctx * conn)
749 { 749 {
750 uint16_t i; 750 uint16_t i;
751 751
752 TRACE_ENTRY("%p", conn); 752 TRACE_ENTRY("%p", conn);
753 CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return ); 753 CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return );
754 754
755 for (i = 0; i < conn->cc_sctp_para.pairs; i++) { 755 for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
756 CHECK_FCT_DO( fd_thr_term(&conn->cc_sctp3436_data.array[i].thr), /* continue */ ); 756 CHECK_FCT_DO( fd_thr_term(&conn->cc_sctp3436_data.array[i].thr), /* continue */ );
757 } 757 }
758 return; 758 return;
759 } 759 }
760 760
761 /* Destroy a wrapper context */ 761 /* Destroy a wrapper context */
762 void fd_sctp3436_destroy(struct cnxctx * conn) 762 void fd_sctp3436_destroy(struct cnxctx * conn)
763 { 763 {
764 uint16_t i; 764 uint16_t i;
765 765
766 CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return ); 766 CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return );
767 767
768 /* Terminate all receiving threads in case we did not do it yet */ 768 /* Terminate all receiving threads in case we did not do it yet */
769 fd_sctp3436_stopthreads(conn); 769 fd_sctp3436_stopthreads(conn);
770 770
771 /* Now, stop the demux thread */ 771 /* Now, stop the demux thread */
772 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ ); 772 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
773 773
774 /* Free remaining data in the array */ 774 /* Free remaining data in the array */
775 for (i = 0; i < conn->cc_sctp_para.pairs; i++) { 775 for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
776 if (conn->cc_sctp3436_data.array[i].raw_recv) 776 if (conn->cc_sctp3436_data.array[i].raw_recv)
777 fd_event_destroy( &conn->cc_sctp3436_data.array[i].raw_recv, free ); 777 fd_event_destroy( &conn->cc_sctp3436_data.array[i].raw_recv, free );
778 free(conn->cc_sctp3436_data.array[i].partial.buf); 778 free(conn->cc_sctp3436_data.array[i].partial.buf);
779 if (conn->cc_sctp3436_data.array[i].session) { 779 if (conn->cc_sctp3436_data.array[i].session) {
780 GNUTLS_TRACE( gnutls_deinit(conn->cc_sctp3436_data.array[i].session) ); 780 GNUTLS_TRACE( gnutls_deinit(conn->cc_sctp3436_data.array[i].session) );
781 conn->cc_sctp3436_data.array[i].session = NULL; 781 conn->cc_sctp3436_data.array[i].session = NULL;
782 } 782 }
783 } 783 }
784 784
785 /* Free the array itself now */ 785 /* Free the array itself now */
786 free(conn->cc_sctp3436_data.array); 786 free(conn->cc_sctp3436_data.array);
787 conn->cc_sctp3436_data.array = NULL; 787 conn->cc_sctp3436_data.array = NULL;
788 788
789 /* Delete the store of sessions */ 789 /* Delete the store of sessions */
790 store_destroy(conn); 790 store_destroy(conn);
791 791
792 return ; 792 return ;
793 } 793 }
"Welcome to our mercurial repository"