static void connect_dtls()

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);
}