2 * Copyright (c) 2014, Ericsson AB. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or other
12 * materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 #include "gstdtlsconnection.h"
34 #include "gstdtlsagent.h"
35 #include "gstdtlscertificate.h"
38 # define __AVAILABILITYMACROS__
39 # define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
42 #include <openssl/err.h>
43 #include <openssl/ssl.h>
52 GST_DEBUG_CATEGORY_STATIC (gst_dtls_connection_debug);
53 #define GST_CAT_DEFAULT gst_dtls_connection_debug
55 #define SRTP_KEY_LEN 16
56 #define SRTP_SALT_LEN 14
60 SIGNAL_ON_ENCODER_KEY,
61 SIGNAL_ON_DECODER_KEY,
62 SIGNAL_ON_PEER_CERTIFICATE,
66 static guint signals[NUM_SIGNALS];
75 static GParamSpec *properties[NUM_PROPERTIES];
77 static int connection_ex_index;
79 static void handle_timeout (gpointer data, gpointer user_data);
81 struct _GstDtlsConnectionPrivate
88 gboolean keys_exported;
94 gint bio_buffer_offset;
96 GClosure *send_closure;
98 gboolean timeout_pending;
99 GThreadPool *thread_pool;
102 G_DEFINE_TYPE_WITH_CODE (GstDtlsConnection, gst_dtls_connection, G_TYPE_OBJECT,
103 G_ADD_PRIVATE (GstDtlsConnection)
104 GST_DEBUG_CATEGORY_INIT (gst_dtls_connection_debug, "dtlsconnection", 0,
107 static void gst_dtls_connection_finalize (GObject * gobject);
108 static void gst_dtls_connection_set_property (GObject *, guint prop_id,
109 const GValue *, GParamSpec *);
111 static void log_state (GstDtlsConnection *, const gchar * str);
112 static void export_srtp_keys (GstDtlsConnection *);
113 static void openssl_poll (GstDtlsConnection *);
114 static int openssl_verify_callback (int preverify_ok,
115 X509_STORE_CTX * x509_ctx);
117 static BIO_METHOD *BIO_s_gst_dtls_connection (void);
118 static int bio_method_write (BIO *, const char *data, int size);
119 static int bio_method_read (BIO *, char *out_buffer, int size);
120 static long bio_method_ctrl (BIO *, int cmd, long arg1, void *arg2);
121 static int bio_method_new (BIO *);
122 static int bio_method_free (BIO *);
125 gst_dtls_connection_class_init (GstDtlsConnectionClass * klass)
127 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
129 gobject_class->set_property = gst_dtls_connection_set_property;
131 connection_ex_index =
132 SSL_get_ex_new_index (0, (gpointer) "gstdtlsagent connection index", NULL,
135 signals[SIGNAL_ON_DECODER_KEY] =
136 g_signal_new ("on-decoder-key", G_TYPE_FROM_CLASS (klass),
137 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
138 g_cclosure_marshal_generic, G_TYPE_NONE, 3,
139 G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT);
141 signals[SIGNAL_ON_ENCODER_KEY] =
142 g_signal_new ("on-encoder-key", G_TYPE_FROM_CLASS (klass),
143 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
144 g_cclosure_marshal_generic, G_TYPE_NONE, 3,
145 G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT);
147 signals[SIGNAL_ON_PEER_CERTIFICATE] =
148 g_signal_new ("on-peer-certificate", G_TYPE_FROM_CLASS (klass),
149 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
150 g_cclosure_marshal_generic, G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
152 properties[PROP_AGENT] =
153 g_param_spec_object ("agent",
155 "Agent to use in creation of the connection",
157 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
159 g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
161 _gst_dtls_init_openssl ();
163 gobject_class->finalize = gst_dtls_connection_finalize;
167 gst_dtls_connection_init (GstDtlsConnection * self)
169 GstDtlsConnectionPrivate *priv;
171 self->priv = priv = gst_dtls_connection_get_instance_private (self);
176 priv->send_closure = NULL;
178 priv->is_client = FALSE;
179 priv->is_alive = TRUE;
180 priv->keys_exported = FALSE;
182 priv->bio_buffer = NULL;
183 priv->bio_buffer_len = 0;
184 priv->bio_buffer_offset = 0;
186 g_mutex_init (&priv->mutex);
187 g_cond_init (&priv->condition);
189 /* Thread pool for handling timeouts, we only need one thread for that
190 * really and share threads with all other thread pools around there as
191 * this is not going to happen very often */
192 priv->thread_pool = g_thread_pool_new (handle_timeout, self, 1, FALSE, NULL);
193 g_assert (priv->thread_pool);
194 priv->timeout_pending = FALSE;
198 gst_dtls_connection_finalize (GObject * gobject)
200 GstDtlsConnection *self = GST_DTLS_CONNECTION (gobject);
201 GstDtlsConnectionPrivate *priv = self->priv;
203 g_thread_pool_free (priv->thread_pool, TRUE, TRUE);
204 priv->thread_pool = NULL;
206 SSL_free (priv->ssl);
209 if (priv->send_closure) {
210 g_closure_unref (priv->send_closure);
211 priv->send_closure = NULL;
214 g_mutex_clear (&priv->mutex);
215 g_cond_clear (&priv->condition);
217 GST_DEBUG_OBJECT (self, "finalized");
219 G_OBJECT_CLASS (gst_dtls_connection_parent_class)->finalize (gobject);
222 #if OPENSSL_VERSION_NUMBER < 0x10100001L
224 BIO_set_data (BIO * bio, void *ptr)
230 BIO_get_data (BIO * bio)
236 BIO_set_shutdown (BIO * bio, int shutdown)
238 bio->shutdown = shutdown;
242 BIO_set_init (BIO * bio, int init)
248 X509_STORE_CTX_get0_cert (X509_STORE_CTX * ctx)
255 gst_dtls_connection_set_property (GObject * object, guint prop_id,
256 const GValue * value, GParamSpec * pspec)
258 GstDtlsConnection *self = GST_DTLS_CONNECTION (object);
260 GstDtlsConnectionPrivate *priv = self->priv;
261 SSL_CTX *ssl_context;
265 g_return_if_fail (!priv->ssl);
266 agent = GST_DTLS_AGENT (g_value_get_object (value));
267 g_return_if_fail (GST_IS_DTLS_AGENT (agent));
269 ssl_context = _gst_dtls_agent_peek_context (agent);
271 priv->ssl = SSL_new (ssl_context);
272 g_return_if_fail (priv->ssl);
274 priv->bio = BIO_new (BIO_s_gst_dtls_connection ());
275 g_return_if_fail (priv->bio);
277 BIO_set_data (priv->bio, self);
278 SSL_set_bio (priv->ssl, priv->bio, priv->bio);
280 SSL_set_verify (priv->ssl,
281 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
282 openssl_verify_callback);
283 SSL_set_ex_data (priv->ssl, connection_ex_index, self);
285 log_state (self, "connection created");
288 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
293 gst_dtls_connection_start (GstDtlsConnection * self, gboolean is_client)
295 GstDtlsConnectionPrivate *priv;
299 g_return_if_fail (priv->send_closure);
300 g_return_if_fail (priv->ssl);
301 g_return_if_fail (priv->bio);
303 GST_TRACE_OBJECT (self, "locking @ start");
304 g_mutex_lock (&priv->mutex);
305 GST_TRACE_OBJECT (self, "locked @ start");
307 priv->is_alive = TRUE;
308 priv->bio_buffer = NULL;
309 priv->bio_buffer_len = 0;
310 priv->bio_buffer_offset = 0;
311 priv->keys_exported = FALSE;
313 priv->is_client = is_client;
314 if (priv->is_client) {
315 SSL_set_connect_state (priv->ssl);
317 SSL_set_accept_state (priv->ssl);
319 log_state (self, "initial state set");
323 log_state (self, "first poll done");
325 GST_TRACE_OBJECT (self, "unlocking @ start");
326 g_mutex_unlock (&priv->mutex);
330 handle_timeout (gpointer data, gpointer user_data)
332 GstDtlsConnection *self = user_data;
333 GstDtlsConnectionPrivate *priv;
338 g_mutex_lock (&priv->mutex);
339 priv->timeout_pending = FALSE;
340 if (priv->is_alive) {
341 ret = DTLSv1_handle_timeout (priv->ssl);
343 GST_DEBUG_OBJECT (self, "handle timeout returned %d, is_alive: %d", ret,
347 GST_WARNING_OBJECT (self, "handling timeout failed");
348 } else if (ret > 0) {
349 log_state (self, "handling timeout before poll");
351 log_state (self, "handling timeout after poll");
354 g_mutex_unlock (&priv->mutex);
358 schedule_timeout_handling (GstClock * clock, GstClockTime time, GstClockID id,
361 GstDtlsConnection *self = user_data;
363 g_mutex_lock (&self->priv->mutex);
364 if (self->priv->is_alive && !self->priv->timeout_pending) {
365 self->priv->timeout_pending = TRUE;
367 GST_TRACE_OBJECT (self, "Schedule timeout now");
368 g_thread_pool_push (self->priv->thread_pool, GINT_TO_POINTER (0xc0ffee),
371 g_mutex_unlock (&self->priv->mutex);
377 gst_dtls_connection_check_timeout_locked (GstDtlsConnection * self)
379 GstDtlsConnectionPrivate *priv;
380 struct timeval timeout;
381 gint64 end_time, wait_time;
383 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
387 if (DTLSv1_get_timeout (priv->ssl, &timeout)) {
388 wait_time = timeout.tv_sec * G_USEC_PER_SEC + timeout.tv_usec;
390 GST_DEBUG_OBJECT (self, "waiting for %" G_GINT64_FORMAT " usec", wait_time);
392 GstClock *system_clock = gst_system_clock_obtain ();
394 #ifndef G_DISABLE_ASSERT
395 GstClockReturn clock_return;
398 end_time = gst_clock_get_time (system_clock) + wait_time * GST_USECOND;
400 clock_id = gst_clock_new_single_shot_id (system_clock, end_time);
401 #ifndef G_DISABLE_ASSERT
406 gst_clock_id_wait_async (clock_id, schedule_timeout_handling,
407 g_object_ref (self), (GDestroyNotify) g_object_unref);
408 g_assert (clock_return == GST_CLOCK_OK);
409 gst_clock_id_unref (clock_id);
410 gst_object_unref (system_clock);
412 if (self->priv->is_alive && !self->priv->timeout_pending) {
413 self->priv->timeout_pending = TRUE;
414 GST_TRACE_OBJECT (self, "Schedule timeout now");
416 g_thread_pool_push (self->priv->thread_pool, GINT_TO_POINTER (0xc0ffee),
421 GST_DEBUG_OBJECT (self, "no timeout set");
426 gst_dtls_connection_check_timeout (GstDtlsConnection * self)
428 GstDtlsConnectionPrivate *priv;
430 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
434 GST_TRACE_OBJECT (self, "locking @ start_timeout");
435 g_mutex_lock (&priv->mutex);
436 GST_TRACE_OBJECT (self, "locked @ start_timeout");
437 gst_dtls_connection_check_timeout_locked (self);
438 g_mutex_unlock (&priv->mutex);
439 GST_TRACE_OBJECT (self, "unlocking @ start_timeout");
443 gst_dtls_connection_stop (GstDtlsConnection * self)
445 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
446 g_return_if_fail (self->priv->ssl);
447 g_return_if_fail (self->priv->bio);
449 GST_DEBUG_OBJECT (self, "stopping connection");
451 GST_TRACE_OBJECT (self, "locking @ stop");
452 g_mutex_lock (&self->priv->mutex);
453 GST_TRACE_OBJECT (self, "locked @ stop");
455 self->priv->is_alive = FALSE;
456 GST_TRACE_OBJECT (self, "signaling @ stop");
457 g_cond_signal (&self->priv->condition);
458 GST_TRACE_OBJECT (self, "signaled @ stop");
460 GST_TRACE_OBJECT (self, "unlocking @ stop");
461 g_mutex_unlock (&self->priv->mutex);
463 GST_DEBUG_OBJECT (self, "stopped connection");
467 gst_dtls_connection_close (GstDtlsConnection * self)
469 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
470 g_return_if_fail (self->priv->ssl);
471 g_return_if_fail (self->priv->bio);
473 GST_DEBUG_OBJECT (self, "closing connection");
475 GST_TRACE_OBJECT (self, "locking @ close");
476 g_mutex_lock (&self->priv->mutex);
477 GST_TRACE_OBJECT (self, "locked @ close");
479 if (self->priv->is_alive) {
480 self->priv->is_alive = FALSE;
481 g_cond_signal (&self->priv->condition);
484 GST_TRACE_OBJECT (self, "unlocking @ close");
485 g_mutex_unlock (&self->priv->mutex);
487 GST_DEBUG_OBJECT (self, "closed connection");
491 gst_dtls_connection_set_send_callback (GstDtlsConnection * self,
494 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
496 GST_TRACE_OBJECT (self, "locking @ set_send_callback");
497 g_mutex_lock (&self->priv->mutex);
498 GST_TRACE_OBJECT (self, "locked @ set_send_callback");
500 if (self->priv->send_closure) {
501 g_closure_unref (self->priv->send_closure);
502 self->priv->send_closure = NULL;
504 self->priv->send_closure = closure;
506 if (closure && G_CLOSURE_NEEDS_MARSHAL (closure)) {
507 g_closure_set_marshal (closure, g_cclosure_marshal_generic);
510 GST_TRACE_OBJECT (self, "unlocking @ set_send_callback");
511 g_mutex_unlock (&self->priv->mutex);
515 gst_dtls_connection_process (GstDtlsConnection * self, gpointer data, gint len)
517 GstDtlsConnectionPrivate *priv;
520 g_return_val_if_fail (GST_IS_DTLS_CONNECTION (self), 0);
521 g_return_val_if_fail (self->priv->ssl, 0);
522 g_return_val_if_fail (self->priv->bio, 0);
526 GST_TRACE_OBJECT (self, "locking @ process");
527 g_mutex_lock (&priv->mutex);
528 GST_TRACE_OBJECT (self, "locked @ process");
530 g_warn_if_fail (!priv->bio_buffer);
532 priv->bio_buffer = data;
533 priv->bio_buffer_len = len;
534 priv->bio_buffer_offset = 0;
536 log_state (self, "process start");
538 if (SSL_want_write (priv->ssl)) {
540 log_state (self, "process want write, after poll");
543 result = SSL_read (priv->ssl, data, len);
545 log_state (self, "process after read");
549 log_state (self, "process after poll");
551 GST_DEBUG_OBJECT (self, "read result: %d", result);
553 GST_TRACE_OBJECT (self, "unlocking @ process");
554 g_mutex_unlock (&priv->mutex);
560 gst_dtls_connection_send (GstDtlsConnection * self, gpointer data, gint len)
564 g_return_val_if_fail (GST_IS_DTLS_CONNECTION (self), 0);
566 g_return_val_if_fail (self->priv->ssl, 0);
567 g_return_val_if_fail (self->priv->bio, 0);
569 GST_TRACE_OBJECT (self, "locking @ send");
570 g_mutex_lock (&self->priv->mutex);
571 GST_TRACE_OBJECT (self, "locked @ send");
573 if (SSL_is_init_finished (self->priv->ssl)) {
574 ret = SSL_write (self->priv->ssl, data, len);
575 GST_DEBUG_OBJECT (self, "data sent: input was %d B, output is %d B", len,
578 GST_WARNING_OBJECT (self,
579 "tried to send data before handshake was complete");
583 GST_TRACE_OBJECT (self, "unlocking @ send");
584 g_mutex_unlock (&self->priv->mutex);
600 log_state (GstDtlsConnection * self, const gchar * str)
602 GstDtlsConnectionPrivate *priv = self->priv;
605 states |= (! !SSL_is_init_finished (priv->ssl) << 0);
606 states |= (! !SSL_in_init (priv->ssl) << 4);
607 states |= (! !SSL_in_before (priv->ssl) << 8);
608 states |= (! !SSL_in_connect_init (priv->ssl) << 12);
609 states |= (! !SSL_in_accept_init (priv->ssl) << 16);
610 states |= (! !SSL_want_write (priv->ssl) << 20);
611 states |= (! !SSL_want_read (priv->ssl) << 24);
613 #if OPENSSL_VERSION_NUMBER < 0x10100001L
614 GST_LOG_OBJECT (self, "%s: role=%s buf=(%d,%p:%d/%d) %x|%x %s",
616 priv->is_client ? "client" : "server",
617 pqueue_size (priv->ssl->d1->sent_messages),
619 priv->bio_buffer_offset,
620 priv->bio_buffer_len,
621 states, SSL_get_state (priv->ssl), SSL_state_string_long (priv->ssl));
623 GST_LOG_OBJECT (self, "%s: role=%s buf=(%p:%d/%d) %x|%x %s",
625 priv->is_client ? "client" : "server",
627 priv->bio_buffer_offset,
628 priv->bio_buffer_len,
629 states, SSL_get_state (priv->ssl), SSL_state_string_long (priv->ssl));
634 export_srtp_keys (GstDtlsConnection * self)
638 guint8 v[SRTP_KEY_LEN];
643 guint8 v[SRTP_SALT_LEN];
658 } client_key, server_key;
660 SRTP_PROTECTION_PROFILE *profile;
661 GstDtlsSrtpCipher cipher;
662 GstDtlsSrtpAuth auth;
665 static gchar export_string[] = "EXTRACTOR-dtls_srtp";
667 success = SSL_export_keying_material (self->priv->ssl,
668 (gpointer) & exported_keys, 60, export_string, strlen (export_string),
672 GST_WARNING_OBJECT (self, "failed to export srtp keys");
676 profile = SSL_get_selected_srtp_profile (self->priv->ssl);
678 GST_INFO_OBJECT (self, "keys received, profile is %s", profile->name);
680 switch (profile->id) {
681 case SRTP_AES128_CM_SHA1_80:
682 cipher = GST_DTLS_SRTP_CIPHER_AES_128_ICM;
683 auth = GST_DTLS_SRTP_AUTH_HMAC_SHA1_80;
685 case SRTP_AES128_CM_SHA1_32:
686 cipher = GST_DTLS_SRTP_CIPHER_AES_128_ICM;
687 auth = GST_DTLS_SRTP_AUTH_HMAC_SHA1_32;
690 GST_WARNING_OBJECT (self, "invalid crypto suite set by handshake");
694 client_key.key = exported_keys.client_key;
695 server_key.key = exported_keys.server_key;
696 client_key.salt = exported_keys.client_salt;
697 server_key.salt = exported_keys.server_salt;
699 if (self->priv->is_client) {
700 g_signal_emit (self, signals[SIGNAL_ON_ENCODER_KEY], 0, &client_key, cipher,
702 g_signal_emit (self, signals[SIGNAL_ON_DECODER_KEY], 0, &server_key,
705 g_signal_emit (self, signals[SIGNAL_ON_ENCODER_KEY], 0, &server_key,
707 g_signal_emit (self, signals[SIGNAL_ON_DECODER_KEY], 0, &client_key, cipher,
712 self->priv->keys_exported = TRUE;
716 ssl_warn_cb (const char *str, size_t len, void *u)
718 GstDtlsConnection *self = u;
719 GST_WARNING_OBJECT (self, "ssl error: %s", str);
724 ssl_err_cb (const char *str, size_t len, void *u)
726 GstDtlsConnection *self = u;
727 GST_ERROR_OBJECT (self, "ssl error: %s", str);
732 openssl_poll (GstDtlsConnection * self)
737 log_state (self, "poll: before handshake");
740 ret = SSL_do_handshake (self->priv->ssl);
742 log_state (self, "poll: after handshake");
746 if (!self->priv->keys_exported) {
747 GST_INFO_OBJECT (self,
748 "handshake just completed successfully, exporting keys");
749 export_srtp_keys (self);
751 GST_INFO_OBJECT (self, "handshake is completed");
755 GST_DEBUG_OBJECT (self, "do_handshake encountered EOF");
758 GST_DEBUG_OBJECT (self, "do_handshake encountered BIO error");
761 GST_DEBUG_OBJECT (self, "do_handshake returned %d", ret);
764 error = SSL_get_error (self->priv->ssl, ret);
768 GST_WARNING_OBJECT (self, "no error, handshake should be done");
771 GST_ERROR_OBJECT (self, "SSL error");
772 ERR_print_errors_cb (ssl_err_cb, self);
774 case SSL_ERROR_WANT_READ:
775 GST_LOG_OBJECT (self, "SSL wants read");
777 case SSL_ERROR_WANT_WRITE:
778 GST_LOG_OBJECT (self, "SSL wants write");
780 case SSL_ERROR_SYSCALL:{
781 gchar message[1024] = "<unknown>";
784 syserror = WSAGetLastError ();
785 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, syserror, 0, message,
786 sizeof message, NULL);
789 strerror_r (syserror, message, sizeof message);
791 GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT,
792 syserror != 0 ? GST_LEVEL_WARNING : GST_LEVEL_LOG,
793 self, "SSL syscall error: errno %d: %s", syserror, message);
797 GST_WARNING_OBJECT (self, "Unknown SSL error: %d, ret: %d", error, ret);
800 ERR_print_errors_cb (ssl_warn_cb, self);
804 openssl_verify_callback (int preverify_ok, X509_STORE_CTX * x509_ctx)
806 GstDtlsConnection *self;
810 gboolean accepted = FALSE;
813 X509_STORE_CTX_get_ex_data (x509_ctx,
814 SSL_get_ex_data_X509_STORE_CTX_idx ());
815 self = SSL_get_ex_data (ssl, connection_ex_index);
816 g_return_val_if_fail (GST_IS_DTLS_CONNECTION (self), FALSE);
818 pem = _gst_dtls_x509_to_pem (X509_STORE_CTX_get0_cert (x509_ctx));
821 GST_WARNING_OBJECT (self,
822 "failed to convert received certificate to pem format");
824 bio = BIO_new (BIO_s_mem ());
830 X509_NAME_print_ex (bio,
831 X509_get_subject_name (X509_STORE_CTX_get0_cert (x509_ctx)), 1,
833 BIO_read (bio, buffer, len);
835 GST_DEBUG_OBJECT (self, "Peer certificate received:\n%s", buffer);
838 GST_DEBUG_OBJECT (self, "failed to create certificate print membio");
841 g_signal_emit (self, signals[SIGNAL_ON_PEER_CERTIFICATE], 0, pem,
850 ######## #### #######
856 ######## #### #######
859 #if OPENSSL_VERSION_NUMBER < 0x10100001L
860 static BIO_METHOD custom_bio_methods = {
874 BIO_s_gst_dtls_connection (void)
876 return &custom_bio_methods;
879 static BIO_METHOD *custom_bio_methods;
882 BIO_s_gst_dtls_connection (void)
884 if (custom_bio_methods != NULL)
885 return custom_bio_methods;
887 custom_bio_methods = BIO_meth_new (BIO_TYPE_BIO, "stream");
888 if (custom_bio_methods == NULL
889 || !BIO_meth_set_write (custom_bio_methods, bio_method_write)
890 || !BIO_meth_set_read (custom_bio_methods, bio_method_read)
891 || !BIO_meth_set_ctrl (custom_bio_methods, bio_method_ctrl)
892 || !BIO_meth_set_create (custom_bio_methods, bio_method_new)
893 || !BIO_meth_set_destroy (custom_bio_methods, bio_method_free)) {
894 BIO_meth_free (custom_bio_methods);
898 return custom_bio_methods;
903 bio_method_write (BIO * bio, const char *data, int size)
905 GstDtlsConnection *self = GST_DTLS_CONNECTION (BIO_get_data (bio));
907 GST_LOG_OBJECT (self, "BIO: writing %d", size);
909 if (self->priv->send_closure) {
910 GValue values[3] = { G_VALUE_INIT };
912 g_value_init (&values[0], GST_TYPE_DTLS_CONNECTION);
913 g_value_set_object (&values[0], self);
915 g_value_init (&values[1], G_TYPE_POINTER);
916 g_value_set_pointer (&values[1], (gpointer) data);
918 g_value_init (&values[2], G_TYPE_INT);
919 g_value_set_int (&values[2], size);
921 g_closure_invoke (self->priv->send_closure, NULL, 3, values, NULL);
923 g_value_unset (&values[0]);
930 bio_method_read (BIO * bio, char *out_buffer, int size)
932 GstDtlsConnection *self = GST_DTLS_CONNECTION (BIO_get_data (bio));
933 GstDtlsConnectionPrivate *priv = self->priv;
937 internal_size = priv->bio_buffer_len - priv->bio_buffer_offset;
939 if (!priv->bio_buffer) {
940 GST_LOG_OBJECT (self, "BIO: EOF");
944 if (!out_buffer || size <= 0) {
945 GST_WARNING_OBJECT (self, "BIO: read got invalid arguments");
947 BIO_set_retry_read (bio);
949 return internal_size;
952 if (size > internal_size) {
953 copy_size = internal_size;
958 GST_DEBUG_OBJECT (self,
959 "reading %d/%d bytes %d at offset %d, output buff size is %d", copy_size,
960 priv->bio_buffer_len, internal_size, priv->bio_buffer_offset, size);
962 memcpy (out_buffer, (guint8 *) priv->bio_buffer + priv->bio_buffer_offset,
964 priv->bio_buffer_offset += copy_size;
966 if (priv->bio_buffer_len == priv->bio_buffer_offset) {
967 priv->bio_buffer = NULL;
974 bio_method_ctrl (BIO * bio, int cmd, long arg1, void *arg2)
976 GstDtlsConnection *self = GST_DTLS_CONNECTION (BIO_get_data (bio));
977 GstDtlsConnectionPrivate *priv = self->priv;
980 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
981 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
982 GST_LOG_OBJECT (self, "BIO: Timeout set");
983 gst_dtls_connection_check_timeout_locked (self);
986 priv->bio_buffer = NULL;
987 priv->bio_buffer_len = 0;
988 priv->bio_buffer_offset = 0;
989 GST_LOG_OBJECT (self, "BIO: EOF reset");
992 gint eof = !(priv->bio_buffer_len - priv->bio_buffer_offset);
993 GST_LOG_OBJECT (self, "BIO: EOF query returned %d", eof);
996 case BIO_CTRL_WPENDING:
997 GST_LOG_OBJECT (self, "BIO: pending write");
999 case BIO_CTRL_PENDING:{
1000 gint pending = priv->bio_buffer_len - priv->bio_buffer_offset;
1001 GST_LOG_OBJECT (self, "BIO: %d bytes pending", pending);
1004 case BIO_CTRL_FLUSH:
1005 GST_LOG_OBJECT (self, "BIO: flushing");
1007 case BIO_CTRL_DGRAM_QUERY_MTU:
1008 GST_DEBUG_OBJECT (self, "BIO: MTU query, returning 0...");
1010 case BIO_CTRL_DGRAM_MTU_EXCEEDED:
1011 GST_WARNING_OBJECT (self, "BIO: MTU exceeded");
1014 GST_LOG_OBJECT (self, "BIO: unhandled ctrl, %d", cmd);
1020 bio_method_new (BIO * bio)
1022 GST_LOG_OBJECT (NULL, "BIO: new");
1024 BIO_set_shutdown (bio, 0);
1025 BIO_set_init (bio, 1);
1031 bio_method_free (BIO * bio)
1034 GST_LOG_OBJECT (NULL, "BIO free called with null bio");
1038 GST_LOG_OBJECT (GST_DTLS_CONNECTION (BIO_get_data (bio)), "BIO free");