janus_dtls_srtp *janus_dtls_srtp_create(void *ice_component, janus_dtls_role role) { janus_ice_component *component = (janus_ice_component *)ice_component; if(component == NULL) { JANUS_LOG(LOG_ERR, "No component, no DTLS...\n"); return NULL; } janus_ice_stream *stream = component->stream; if(!stream) { JANUS_LOG(LOG_ERR, "No stream, no DTLS...\n"); return NULL; } janus_ice_handle *handle = stream->handle; if(!handle || !handle->agent) { JANUS_LOG(LOG_ERR, "No handle/agent, no DTLS...\n"); return NULL; } janus_dtls_srtp *dtls = calloc(1, sizeof(janus_dtls_srtp)); if(dtls == NULL) { JANUS_LOG(LOG_FATAL, "Memory error!\n"); return NULL; } /* Create SSL context, at last */ dtls->srtp_valid = 0; dtls->dtls_last_msg = NULL; dtls->dtls_last_len = 0; dtls->ssl = SSL_new(janus_dtls_get_ssl_ctx()); if(!dtls->ssl) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] No component DTLS SSL session??\n", handle->handle_id); janus_dtls_srtp_destroy(dtls); return NULL; } SSL_set_ex_data(dtls->ssl, 0, dtls); SSL_set_info_callback(dtls->ssl, janus_dtls_callback); dtls->read_bio = BIO_new(BIO_s_mem()); if(!dtls->read_bio) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error creating read BIO!\n", handle->handle_id); janus_dtls_srtp_destroy(dtls); return NULL; } BIO_set_mem_eof_return(dtls->read_bio, -1); dtls->write_bio = BIO_new(BIO_s_mem()); if(!dtls->write_bio) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error creating write BIO!\n", handle->handle_id); janus_dtls_srtp_destroy(dtls); return NULL; } BIO_set_mem_eof_return(dtls->write_bio, -1); SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->write_bio); dtls->dtls_role = role; if(dtls->dtls_role == JANUS_DTLS_ROLE_CLIENT) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Setting connect state (DTLS client)\n", handle->handle_id); SSL_set_connect_state(dtls->ssl); } else { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Setting accept state (DTLS server)\n", handle->handle_id); SSL_set_accept_state(dtls->ssl); } /* Done */ dtls->component = component; return dtls; }
janus_dtls_srtp *janus_dtls_srtp_create(void *ice_component, janus_dtls_role role) { janus_ice_component *component = (janus_ice_component *)ice_component; if(component == NULL) { JANUS_LOG(LOG_ERR, "No component, no DTLS...\n"); return NULL; } janus_ice_stream *stream = component->stream; if(!stream) { JANUS_LOG(LOG_ERR, "No stream, no DTLS...\n"); return NULL; } janus_ice_handle *handle = stream->handle; if(!handle || !handle->agent) { JANUS_LOG(LOG_ERR, "No handle/agent, no DTLS...\n"); return NULL; } janus_dtls_srtp *dtls = g_malloc0(sizeof(janus_dtls_srtp)); if(dtls == NULL) { JANUS_LOG(LOG_FATAL, "Memory error!\n"); return NULL; } /* Create SSL context, at last */ dtls->srtp_valid = 0; dtls->ssl = SSL_new(janus_dtls_get_ssl_ctx()); if(!dtls->ssl) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] No component DTLS SSL session??\n", handle->handle_id); janus_dtls_srtp_destroy(dtls); return NULL; } SSL_set_ex_data(dtls->ssl, 0, dtls); SSL_set_info_callback(dtls->ssl, janus_dtls_callback); dtls->read_bio = BIO_new(BIO_s_mem()); if(!dtls->read_bio) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error creating read BIO!\n", handle->handle_id); janus_dtls_srtp_destroy(dtls); return NULL; } BIO_set_mem_eof_return(dtls->read_bio, -1); dtls->write_bio = BIO_new(BIO_s_mem()); if(!dtls->write_bio) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error creating write BIO!\n", handle->handle_id); janus_dtls_srtp_destroy(dtls); return NULL; } BIO_set_mem_eof_return(dtls->write_bio, -1); /* The write BIO needs our custom filter, or fragmentation won't work */ dtls->filter_bio = BIO_new(BIO_janus_dtls_filter()); if(!dtls->filter_bio) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error creating filter BIO!\n", handle->handle_id); janus_dtls_srtp_destroy(dtls); return NULL; } /* Chain filter and write BIOs */ BIO_push(dtls->filter_bio, dtls->write_bio); /* Set the filter as the BIO to use for outgoing data */ SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->filter_bio); dtls->dtls_role = role; if(dtls->dtls_role == JANUS_DTLS_ROLE_CLIENT) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Setting connect state (DTLS client)\n", handle->handle_id); SSL_set_connect_state(dtls->ssl); } else { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Setting accept state (DTLS server)\n", handle->handle_id); SSL_set_accept_state(dtls->ssl); } /* https://code.google.com/p/chromium/issues/detail?id=406458 * Specify an ECDH group for ECDHE ciphers, otherwise they cannot be * negotiated when acting as the server. Use NIST's P-256 which is * commonly supported. */ EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if(ecdh == NULL) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error creating ECDH group!\n", handle->handle_id); janus_dtls_srtp_destroy(dtls); return NULL; } SSL_set_options(dtls->ssl, SSL_OP_SINGLE_ECDH_USE); SSL_set_tmp_ecdh(dtls->ssl, ecdh); EC_KEY_free(ecdh); dtls->ready = 0; #ifdef HAVE_SCTP dtls->sctp = NULL; #endif janus_mutex_init(&dtls->srtp_mutex); /* Done */ dtls->dtls_connected = 0; dtls->component = component; return dtls; }