Mercurial > hg > freeDiameter
diff libfdcore/sctp3436.c @ 1186:56c36d1007b4
Further preparation of the DTLS integration. Some cleanups in the GNUTLS handling.
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Fri, 07 Jun 2013 18:48:34 +0800 |
parents | 22de21feec64 |
children | 6a1042d8075b |
line wrap: on
line diff
--- a/libfdcore/sctp3436.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/sctp3436.c Fri Jun 07 18:48:34 2013 +0800 @@ -51,12 +51,12 @@ - the push function sends the data on a certain stream. We also have a demux thread that reads the socket and store received data in the appropriate fifo - We have one gnutls_session per stream pair, and as many streams that read the gnutls records and save incoming data to the target queue. + 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. 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. */ -/* TODO: change this whole wrapper to DTLS which should not require many different threads */ +/* Note that this mechanism is replaced by DTLS in RFC6733 */ /*************************************************************/ /* threads */ @@ -163,18 +163,63 @@ /* push / pull */ /*************************************************************/ +#ifdef GNUTLS_VERSION_300 +/* Check if data is available for gnutls on a given context */ +static int sctp3436_pull_timeout(gnutls_transport_ptr_t tr, unsigned int ms) +{ + struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr; + struct timespec tsstore, *ts = NULL; + int ret; + + TRACE_ENTRY("%p %d", tr, ms); + + if (ctx->partial.buf) + return 1; /* data is already available for pull */ + + if (ms) { + CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &tsstore), return -1 ); + tsstore.tv_nsec += (long)ms * 1000000; + tsstore.tv_sec += tsstore.tv_nsec / 1000000000L; + tsstore.tv_nsec %= 1000000000L; + ts = &tsstore; + } + + ret = fd_fifo_select ( ctx->raw_recv, ts ); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} +#endif /* GNUTLS_VERSION_300 */ + /* Send data over the connection, called by gnutls */ +#ifndef GNUTLS_VERSION_212 static ssize_t sctp3436_push(gnutls_transport_ptr_t tr, const void * data, size_t len) { struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr; + struct iovec iov; TRACE_ENTRY("%p %p %zd", tr, data, len); CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } ); - CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent, ctx->strid, (uint8_t *)data, len), return -1 ); + iov.iov_base = (void *)data; + iov.iov_len = len; - return len; + return fd_sctp_sendstrv(ctx->parent, ctx->strid, &iov, 1); } +#else /* GNUTLS_VERSION_212 */ +static ssize_t sctp3436_pushv(gnutls_transport_ptr_t tr, const giovec_t * iov, int iovcnt) +{ + struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr; + + TRACE_ENTRY("%p %p %d", tr, iov, iovcnt); + CHECK_PARAMS_DO( tr && iov, { errno = EINVAL; return -1; } ); + + return fd_sctp_sendstrv(ctx->parent, ctx->strid, (const struct iovec *)iov, iovcnt); +} +#endif /* GNUTLS_VERSION_212 */ /* Retrieve data received on a stream and already demultiplexed */ static ssize_t sctp3436_pull(gnutls_transport_ptr_t tr, void * buf, size_t len) @@ -237,11 +282,18 @@ #ifndef GNUTLS_VERSION_300 /* starting version 2.12, this call is not needed */ GNUTLS_TRACE( gnutls_transport_set_lowat( session, 0 ) ); +#else /* GNUTLS_VERSION_300 */ + /* but in 3.0 we have to provide the pull_timeout callback */ + GNUTLS_TRACE( gnutls_transport_set_pull_timeout_function( session, sctp3436_pull_timeout ) ); #endif /* GNUTLS_VERSION_300 */ /* Set the push and pull callbacks */ GNUTLS_TRACE( gnutls_transport_set_pull_function(session, sctp3436_pull) ); +#ifndef GNUTLS_VERSION_212 GNUTLS_TRACE( gnutls_transport_set_push_function(session, sctp3436_push) ); +#else /* GNUTLS_VERSION_212 */ + GNUTLS_TRACE( gnutls_transport_set_vec_push_function(session, sctp3436_pushv) ); +#endif /* GNUTLS_VERSION_212 */ return; }