gint gst_dtls_connection_send (GstDtlsConnection * self, gpointer data, gint len) { int ret = 0; g_return_val_if_fail (GST_IS_DTLS_CONNECTION (self), 0); g_return_val_if_fail (self->priv->ssl, 0); g_return_val_if_fail (self->priv->bio, 0); GST_TRACE_OBJECT (self, "locking @ send"); g_mutex_lock (&self->priv->mutex); GST_TRACE_OBJECT (self, "locked @ send"); if (SSL_is_init_finished (self->priv->ssl)) { ret = SSL_write (self->priv->ssl, data, len); GST_DEBUG_OBJECT (self, "data sent: input was %d B, output is %d B", len, ret); } else { GST_WARNING_OBJECT (self, "tried to send data before handshake was complete"); ret = 0; } GST_TRACE_OBJECT (self, "unlocking @ send"); g_mutex_unlock (&self->priv->mutex); return ret; }
static void on_key_received (GstDtlsConnection * connection, gpointer key, guint cipher, guint auth, GstDtlsEnc * self) { gpointer key_dup; gchar *key_str; g_return_if_fail (GST_IS_DTLS_ENC (self)); g_return_if_fail (GST_IS_DTLS_CONNECTION (connection)); self->srtp_cipher = cipher; self->srtp_auth = auth; key_dup = g_memdup (key, GST_DTLS_SRTP_MASTER_KEY_LENGTH); if (self->encoder_key) { gst_buffer_unref (self->encoder_key); self->encoder_key = NULL; } self->encoder_key = gst_buffer_new_wrapped (key_dup, GST_DTLS_SRTP_MASTER_KEY_LENGTH); key_str = g_base64_encode (key, GST_DTLS_SRTP_MASTER_KEY_LENGTH); GST_INFO_OBJECT (self, "received key: %s", key_str); g_free (key_str); g_signal_emit (self, signals[SIGNAL_ON_KEY_RECEIVED], 0); }
static void gst_dtls_connection_check_timeout_locked (GstDtlsConnection * self) { GstDtlsConnectionPrivate *priv; struct timeval timeout; gint64 end_time, wait_time; g_return_if_fail (GST_IS_DTLS_CONNECTION (self)); priv = self->priv; if (DTLSv1_get_timeout (priv->ssl, &timeout)) { wait_time = timeout.tv_sec * G_USEC_PER_SEC + timeout.tv_usec; GST_DEBUG_OBJECT (self, "waiting for %" G_GINT64_FORMAT " usec", wait_time); if (wait_time) { GstClock *system_clock = gst_system_clock_obtain (); GstClockID clock_id; #ifndef G_DISABLE_ASSERT GstClockReturn clock_return; #endif end_time = gst_clock_get_time (system_clock) + wait_time * GST_USECOND; clock_id = gst_clock_new_single_shot_id (system_clock, end_time); #ifndef G_DISABLE_ASSERT clock_return = #else (void) #endif gst_clock_id_wait_async (clock_id, schedule_timeout_handling, g_object_ref (self), (GDestroyNotify) g_object_unref); g_assert (clock_return == GST_CLOCK_OK); gst_clock_id_unref (clock_id); gst_object_unref (system_clock); } else { if (self->priv->is_alive && !self->priv->timeout_pending) { self->priv->timeout_pending = TRUE; GST_TRACE_OBJECT (self, "Schedule timeout now"); g_thread_pool_push (self->priv->thread_pool, GINT_TO_POINTER (0xc0ffee), NULL); } } } else { GST_DEBUG_OBJECT (self, "no timeout set"); } }
void gst_dtls_connection_check_timeout (GstDtlsConnection * self) { GstDtlsConnectionPrivate *priv; g_return_if_fail (GST_IS_DTLS_CONNECTION (self)); priv = self->priv; GST_TRACE_OBJECT (self, "locking @ start_timeout"); g_mutex_lock (&priv->mutex); GST_TRACE_OBJECT (self, "locked @ start_timeout"); gst_dtls_connection_check_timeout_locked (self); g_mutex_unlock (&priv->mutex); GST_TRACE_OBJECT (self, "unlocking @ start_timeout"); }
static int openssl_verify_callback (int preverify_ok, X509_STORE_CTX * x509_ctx) { GstDtlsConnection *self; SSL *ssl; BIO *bio; gchar *pem = NULL; gboolean accepted = FALSE; ssl = X509_STORE_CTX_get_ex_data (x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx ()); self = SSL_get_ex_data (ssl, connection_ex_index); g_return_val_if_fail (GST_IS_DTLS_CONNECTION (self), FALSE); pem = _gst_dtls_x509_to_pem (X509_STORE_CTX_get0_cert (x509_ctx)); if (!pem) { GST_WARNING_OBJECT (self, "failed to convert received certificate to pem format"); } else { bio = BIO_new (BIO_s_mem ()); if (bio) { gchar buffer[2048]; gint len; len = X509_NAME_print_ex (bio, X509_get_subject_name (X509_STORE_CTX_get0_cert (x509_ctx)), 1, XN_FLAG_MULTILINE); BIO_read (bio, buffer, len); buffer[len] = '\0'; GST_DEBUG_OBJECT (self, "Peer certificate received:\n%s", buffer); BIO_free (bio); } else { GST_DEBUG_OBJECT (self, "failed to create certificate print membio"); } g_signal_emit (self, signals[SIGNAL_ON_PEER_CERTIFICATE], 0, pem, &accepted); g_free (pem); } return accepted; }
gint gst_dtls_connection_process (GstDtlsConnection * self, gpointer data, gint len) { GstDtlsConnectionPrivate *priv; gint result; g_return_val_if_fail (GST_IS_DTLS_CONNECTION (self), 0); g_return_val_if_fail (self->priv->ssl, 0); g_return_val_if_fail (self->priv->bio, 0); priv = self->priv; GST_TRACE_OBJECT (self, "locking @ process"); g_mutex_lock (&priv->mutex); GST_TRACE_OBJECT (self, "locked @ process"); g_warn_if_fail (!priv->bio_buffer); priv->bio_buffer = data; priv->bio_buffer_len = len; priv->bio_buffer_offset = 0; log_state (self, "process start"); if (SSL_want_write (priv->ssl)) { openssl_poll (self); log_state (self, "process want write, after poll"); } result = SSL_read (priv->ssl, data, len); log_state (self, "process after read"); openssl_poll (self); log_state (self, "process after poll"); GST_DEBUG_OBJECT (self, "read result: %d", result); GST_TRACE_OBJECT (self, "unlocking @ process"); g_mutex_unlock (&priv->mutex); return result; }
void gst_dtls_connection_set_send_callback (GstDtlsConnection * self, GClosure * closure) { g_return_if_fail (GST_IS_DTLS_CONNECTION (self)); GST_TRACE_OBJECT (self, "locking @ set_send_callback"); g_mutex_lock (&self->priv->mutex); GST_TRACE_OBJECT (self, "locked @ set_send_callback"); if (self->priv->send_closure) { g_closure_unref (self->priv->send_closure); self->priv->send_closure = NULL; } self->priv->send_closure = closure; if (closure && G_CLOSURE_NEEDS_MARSHAL (closure)) { g_closure_set_marshal (closure, g_cclosure_marshal_generic); } GST_TRACE_OBJECT (self, "unlocking @ set_send_callback"); g_mutex_unlock (&self->priv->mutex); }
void gst_dtls_connection_close (GstDtlsConnection * self) { g_return_if_fail (GST_IS_DTLS_CONNECTION (self)); g_return_if_fail (self->priv->ssl); g_return_if_fail (self->priv->bio); GST_DEBUG_OBJECT (self, "closing connection"); GST_TRACE_OBJECT (self, "locking @ close"); g_mutex_lock (&self->priv->mutex); GST_TRACE_OBJECT (self, "locked @ close"); if (self->priv->is_alive) { self->priv->is_alive = FALSE; g_cond_signal (&self->priv->condition); } GST_TRACE_OBJECT (self, "unlocking @ close"); g_mutex_unlock (&self->priv->mutex); GST_DEBUG_OBJECT (self, "closed connection"); }
void gst_dtls_connection_stop (GstDtlsConnection * self) { g_return_if_fail (GST_IS_DTLS_CONNECTION (self)); g_return_if_fail (self->priv->ssl); g_return_if_fail (self->priv->bio); GST_DEBUG_OBJECT (self, "stopping connection"); GST_TRACE_OBJECT (self, "locking @ stop"); g_mutex_lock (&self->priv->mutex); GST_TRACE_OBJECT (self, "locked @ stop"); self->priv->is_alive = FALSE; GST_TRACE_OBJECT (self, "signaling @ stop"); g_cond_signal (&self->priv->condition); GST_TRACE_OBJECT (self, "signaled @ stop"); GST_TRACE_OBJECT (self, "unlocking @ stop"); g_mutex_unlock (&self->priv->mutex); GST_DEBUG_OBJECT (self, "stopped connection"); }