in chime/chime-call-transport.c [463:534]
static void connect_dtls(ChimeCallAudio *audio, GSocket *s)
{
/* Not that "connected" means anything except that we think we can route to it. */
chime_debug("UDP socket connected\n");
audio->dtls_source = g_datagram_based_create_source(G_DATAGRAM_BASED(s), G_IO_IN, audio->cancel);
audio->dtls_sock = s;
g_source_set_callback(audio->dtls_source, (GSourceFunc)dtls_src_cb, audio, NULL);
g_source_attach(audio->dtls_source, NULL);
gnutls_init(&audio->dtls_sess, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
gnutls_set_default_priority(audio->dtls_sess);
gnutls_session_set_ptr(audio->dtls_sess, audio);
if (!audio->dtls_cred) {
gnutls_certificate_allocate_credentials(&audio->dtls_cred);
gnutls_certificate_set_x509_system_trust(audio->dtls_cred);
gnutls_certificate_set_x509_trust_dir(audio->dtls_cred,
CHIME_CERTS_DIR, GNUTLS_X509_FMT_PEM);
gnutls_certificate_set_verify_function(audio->dtls_cred, dtls_verify_cb);
}
gnutls_credentials_set(audio->dtls_sess, GNUTLS_CRD_CERTIFICATE, audio->dtls_cred);
if (!audio->dtls_hostname) {
gchar *hostname = g_strdup(chime_call_get_media_host(audio->call));
if (!hostname)
goto err;
char *colon = strrchr(hostname, ':');
if (!colon) {
g_free(hostname);
goto err;
}
*colon = 0;
audio->dtls_hostname = hostname;
}
/* We can't rely on the length argument to gnutls_server_name_set().
https://bugs.launchpad.net/ubuntu/+bug/1762710 */
gnutls_server_name_set(audio->dtls_sess, GNUTLS_NAME_DNS, audio->dtls_hostname, strlen(audio->dtls_hostname));
gnutls_transport_set_ptr(audio->dtls_sess, audio);
gnutls_transport_set_push_function (audio->dtls_sess,
g_tls_connection_gnutls_push_func);
gnutls_transport_set_pull_function (audio->dtls_sess,
g_tls_connection_gnutls_pull_func);
gnutls_transport_set_pull_timeout_function (audio->dtls_sess,
g_tls_connection_gnutls_pull_timeout_func);
gnutls_transport_set_vec_push_function (audio->dtls_sess,
g_tls_connection_gnutls_vec_push_func);
gnutls_dtls_set_timeouts(audio->dtls_sess, 250, 2500);
gnutls_dtls_set_mtu(audio->dtls_sess, CHIME_DTLS_MTU);
if (gnutls_handshake(audio->dtls_sess) != GNUTLS_E_AGAIN) {
chime_debug("Initial DTLS handshake failed\n");
gnutls_deinit(audio->dtls_sess);
audio->dtls_sess = NULL;
if (audio->dtls_source) {
g_source_destroy(audio->dtls_source);
audio->dtls_source = NULL;
}
goto err;
}
int timeo = gnutls_dtls_get_timeout(audio->dtls_sess);
audio->timeout_source = g_timeout_add(timeo, (GSourceFunc)dtls_timeout, audio);
return;
err:
g_clear_object(&audio->dtls_sock);
chime_call_transport_connect_ws(audio);
}