1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
--- a/libavformat/tls_mbedtls.c
+++ b/libavformat/tls_mbedtls.c
@@ -41,6 +41,7 @@
#include "libavutil/parseutils.h"
#include "libavutil/avstring.h"
#include "libavutil/random_seed.h"
+#include "libavutil/intreadwrite.h"
static int mbedtls_x509_fingerprint(char *cert_buf, size_t cert_sz, char **fingerprint)
{
@@ -376,6 +377,27 @@
return handle_transport_error(h, "ffurl_write", MBEDTLS_ERR_SSL_WANT_WRITE, ret);
}
+/*
+ * Some webrtc servers, such as the ones based on pion, send stun packets during the
+ * dtls handshake. openssl and gnutls filter those out internally but mbedtls passes
+ * every received udp packet to its dtls state machine, which makes the handshake fail.
+ * This is the same check as the one in whip.c, which ffmpeg n8.1 doesn't share yet.
+ */
+#define DTLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC 20
+#define DTLS_RECORD_LAYER_HEADER_LEN 13
+#define DTLS_VERSION_10 0xfeff
+#define DTLS_VERSION_12 0xfefd
+
+static int is_dtls_packet(const unsigned char *buf, int size)
+{
+ if (size > DTLS_RECORD_LAYER_HEADER_LEN) {
+ uint16_t version = AV_RB16(&buf[1]);
+ return buf[0] >= DTLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC &&
+ (version == DTLS_VERSION_10 || version == DTLS_VERSION_12);
+ }
+ return 0;
+}
+
static int mbedtls_recv(void *ctx, unsigned char *buf, size_t len)
{
TLSContext *tls_ctx = (TLSContext*) ctx;
@@ -394,6 +416,9 @@
}
av_log(tls_ctx, AV_LOG_TRACE, "Set UDP remote addr on UDP socket, now 'connected'\n");
}
+ /* Skip non-DTLS packets such as STUN to avoid failures. */
+ if (shr->is_dtls && !is_dtls_packet(buf, ret))
+ return MBEDTLS_ERR_SSL_WANT_READ;
return ret;
}
if (h->max_packet_size && len > h->max_packet_size)
|