diff --git a/daemon/dtls.c b/daemon/dtls.c index 04669a29f..c231487c3 100644 --- a/daemon/dtls.c +++ b/daemon/dtls.c @@ -604,6 +604,51 @@ static int try_connect(struct dtls_connection *d) { return ret; } +static long dtls_bio_callback(BIO *bio, int oper, const char *argp, size_t len, int argi, long argl, + int ret, size_t *proc) +{ + if (oper == (BIO_CB_CTRL | BIO_CB_RETURN)) { + if (argi == BIO_CTRL_DGRAM_QUERY_MTU) + return rtpe_config.dtls_mtu; // this is with overhead already subtracted + if (argi == BIO_CTRL_DGRAM_GET_MTU_OVERHEAD) + return DTLS_MTU_OVERHEAD; + return ret; + } + + if (oper != BIO_CB_WRITE) + return ret; + if (!argp || len <= 0) + return ret; + + struct packet_stream *ps = (struct packet_stream *) BIO_get_callback_arg(bio); + if (!ps) + return ret; + struct stream_fd *sfd = ps->selected_sfd; + if (!sfd) + return ret; + struct dtls_connection *d = dtls_ptr(sfd); + if (!d) + return ret; + + __DBG("dtls packet output: len %zu %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + len, + argp[0], argp[1], argp[2], argp[3], + argp[4], argp[5], argp[6], argp[7], + argp[8], argp[9], argp[10], argp[11], + argp[12], argp[13], argp[14], argp[15]); + + const endpoint_t *fsin = &ps->endpoint; + if (fsin->port == 9 || fsin->address.family == NULL) + return ret; + + ilogs(srtp, LOG_DEBUG, "Sending DTLS packet"); + socket_sendto(&sfd->socket, argp, len, fsin); + atomic64_inc_na(&ps->stats_out->packets); + atomic64_add_na(&ps->stats_out->bytes, len); + + return ret; +} + int dtls_connection_init(struct dtls_connection *d, struct packet_stream *ps, int active, struct dtls_cert *cert) { @@ -656,6 +701,14 @@ int dtls_connection_init(struct dtls_connection *d, struct packet_stream *ps, in if (!d->r_bio || !d->w_bio) goto error; + BIO_set_callback_ex(d->w_bio, dtls_bio_callback); + BIO_set_callback_arg(d->w_bio, (char *) ps); + +#if defined(BIO_CTRL_DGRAM_SET_MTU) + BIO_ctrl(d->w_bio, BIO_CTRL_DGRAM_SET_MTU, rtpe_config.dtls_mtu, NULL); + BIO_ctrl(d->r_bio, BIO_CTRL_DGRAM_SET_MTU, rtpe_config.dtls_mtu, NULL); +#endif + SSL_set_app_data(d->ssl, d); SSL_set_bio(d->ssl, d->r_bio, d->w_bio); d->init = 1; @@ -792,7 +845,6 @@ static int dtls_setup_crypto(struct packet_stream *ps, struct dtls_connection *d int dtls(stream_fd *sfd, const str *s, const endpoint_t *fsin) { struct packet_stream *ps = sfd->stream; int ret; - unsigned char buf[0x10000]; if (!ps) return 0; @@ -856,42 +908,6 @@ int dtls(stream_fd *sfd, const str *s, const endpoint_t *fsin) { } } - while (1) { - ret = BIO_ctrl_pending(d->w_bio); - if (ret <= 0) - break; - - if (ret > sizeof(buf)) { - ilogs(srtp, LOG_ERROR, "BIO buffer overflow"); - (void) BIO_reset(d->w_bio); - break; - } - - ret = BIO_read(d->w_bio, buf, ret); - if (ret <= 0) - break; - - __DBG("dtls packet output: len %u %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - ret, - buf[0], buf[1], buf[2], buf[3], - buf[4], buf[5], buf[6], buf[7], - buf[8], buf[9], buf[10], buf[11], - buf[12], buf[13], buf[14], buf[15]); - - if (!fsin) { - fsin = &ps->endpoint; - if (fsin->port == 9 || fsin->address.family == NULL) - fsin = NULL; - } - - if (fsin) { - ilogs(srtp, LOG_DEBUG, "Sending DTLS packet"); - socket_sendto(&sfd->socket, buf, ret, fsin); - atomic64_inc_na(&ps->stats_out->packets); - atomic64_add_na(&ps->stats_out->bytes, ret); - } - } - return dret; } diff --git a/daemon/main.c b/daemon/main.c index 55f1ec24a..d034f1102 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -955,6 +955,8 @@ static void options(int *argc, char ***argv) { However, this does not preclude link layers with an MTU smaller than this minimum MTU from conveying IP data. Internet IPv4 path MTU is 68 bytes.*/ die("Invalid --dtls-mtu (%i)", rtpe_config.dtls_mtu); + rtpe_config.dtls_mtu -= DTLS_MTU_OVERHEAD; + if (rtpe_config.jb_length < 0) die("Invalid negative jitter buffer size"); diff --git a/include/dtls.h b/include/dtls.h index b9b836b48..80238658e 100644 --- a/include/dtls.h +++ b/include/dtls.h @@ -13,6 +13,7 @@ #include "types.h" #define DTLS_MAX_DIGEST_LEN 64 +#define DTLS_MTU_OVERHEAD 48 // 40 bytes IPv6 + 8 bytes UDP struct packet_stream; struct sockaddr_in6;