create explicit per-stream DTLS context for ICE

fixes #500

Change-Id: Iee3d9ab1c19a6992ae043896eb500b3961de3edc
changes/19/20019/1
Richard Fuchs 7 years ago
parent 4ac6473be2
commit 16024d2e7a

@ -930,9 +930,9 @@ enum call_stream_state call_stream_state_machine(struct packet_stream *ps) {
if (MEDIA_ISSET(media, DTLS)) {
mutex_lock(&ps->in_lock);
struct stream_fd *sfd = dtls_sfd(ps);
if (sfd && sfd->dtls.init && !sfd->dtls.connected) {
dtls(sfd, NULL, NULL);
struct dtls_connection *d = dtls_ptr(ps->selected_sfd);
if (d && d->init && !d->connected) {
dtls(ps->selected_sfd, NULL, NULL);
mutex_unlock(&ps->in_lock);
return CSS_DTLS;
}
@ -963,16 +963,20 @@ static int __init_stream(struct packet_stream *ps) {
}
if (MEDIA_ISSET(media, DTLS) && !PS_ISSET(ps, FALLBACK_RTCP)) {
struct stream_fd *sfd = dtls_sfd(ps);
if (sfd)
active = dtls_is_active(&sfd->dtls);
struct dtls_connection *d = dtls_ptr(ps->selected_sfd);
if (d)
active = dtls_is_active(d);
// we try to retain our role if possible, but must handle a role switch
if ((active && !MEDIA_ISSET(media, SETUP_ACTIVE))
|| (!active && !MEDIA_ISSET(media, SETUP_PASSIVE)))
active = -1;
if (active == -1)
active = (PS_ISSET(ps, FILLED) && MEDIA_ISSET(media, SETUP_ACTIVE));
dtls_connection_init(ps, active, call->dtls_cert);
dtls_connection_init(&ps->ice_dtls, ps, active, call->dtls_cert);
for (GList *l = ps->sfds.head; l; l = l->next) {
struct stream_fd *sfd = l->data;
dtls_connection_init(&sfd->dtls, ps, active, call->dtls_cert);
}
if (!PS_ISSET(ps, FINGERPRINT_VERIFIED) && media->fingerprint.hash_func
&& ps->dtls_cert)

@ -275,6 +275,7 @@ struct packet_stream {
GQueue sfds; /* LOCK: call->master_lock */
struct stream_fd * volatile selected_sfd;
struct dtls_connection ice_dtls; /* LOCK: in_lock */
struct packet_stream *rtp_sink; /* LOCK: call->master_lock */
struct packet_stream *rtcp_sink; /* LOCK: call->master_lock */
struct packet_stream *rtcp_sibling; /* LOCK: call->master_lock */

@ -35,29 +35,12 @@
#define CERT_EXPIRY_TIME (60*60*24*30) /* 30 days */
INLINE struct stream_fd *dtls_primary(struct packet_stream *ps) {
if (!ps->sfds.length)
return NULL;
return ps->sfds.head->data;
}
// determine the sfd to hold our DTLS context if we don't know the sfd.
// it's either the "selected_sfd" for regular multi-homed streams, or
// the first sfd in the list in case ICE is in use
struct stream_fd *dtls_sfd(struct packet_stream *ps) {
if (!ps)
return NULL;
if (PS_ISSET(ps, ICE))
return dtls_primary(ps);
return ps->selected_sfd;
}
// determine the DTLS context if we do have an sfd. can be sfd->dtls,
// or in case ICE is in use, the first sfd's context.
struct dtls_connection *dtls_ptr(struct stream_fd *sfd) {
if (!sfd)
return NULL;
struct packet_stream *ps = sfd->stream;
if (PS_ISSET(ps, ICE)) // ignore which sfd we were given
sfd = dtls_primary(ps);
return &ps->ice_dtls;
return &sfd->dtls;
}
@ -403,15 +386,15 @@ struct dtls_cert *dtls_cert() {
static int verify_callback(int ok, X509_STORE_CTX *store) {
SSL *ssl;
struct stream_fd *sfd;
struct dtls_connection *d;
struct packet_stream *ps;
struct call_media *media;
ssl = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx());
sfd = SSL_get_app_data(ssl);
if (sfd->dtls.ssl != ssl)
d = SSL_get_app_data(ssl);
if (d->ssl != ssl)
return 0;
ps = sfd->stream;
ps = d->ptr;
if (!ps)
return 0;
if (PS_ISSET(ps, FINGERPRINT_VERIFIED))
@ -499,15 +482,11 @@ static int try_connect(struct dtls_connection *d) {
return ret;
}
int dtls_connection_init(struct packet_stream *ps, int active, struct dtls_cert *cert) {
struct dtls_connection *d;
int dtls_connection_init(struct dtls_connection *d, struct packet_stream *ps, int active,
struct dtls_cert *cert)
{
unsigned long err;
struct stream_fd *sfd = dtls_sfd(ps);
if (!sfd)
return 0;
d = &sfd->dtls;
__DBG("dtls_connection_init(%i)", active);
if (d->init) {
@ -516,6 +495,8 @@ int dtls_connection_init(struct packet_stream *ps, int active, struct dtls_cert
dtls_connection_cleanup(d);
}
d->ptr = ps;
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
d->ssl_ctx = SSL_CTX_new(active ? DTLS_client_method() : DTLS_server_method());
#else
@ -548,7 +529,7 @@ int dtls_connection_init(struct packet_stream *ps, int active, struct dtls_cert
if (!d->r_bio || !d->w_bio)
goto error;
SSL_set_app_data(d->ssl, sfd); /* XXX obj reference here? */
SSL_set_app_data(d->ssl, d);
SSL_set_bio(d->ssl, d->r_bio, d->w_bio);
d->init = 1;
SSL_set_mode(d->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

@ -50,6 +50,7 @@ struct dtls_connection {
SSL_CTX *ssl_ctx;
SSL *ssl;
BIO *r_bio, *w_bio;
void *ptr;
int init:1,
active:1,
connected:1;
@ -65,7 +66,7 @@ int dtls_verify_cert(struct packet_stream *ps);
const struct dtls_hash_func *dtls_find_hash_func(const str *);
struct dtls_cert *dtls_cert(void);
int dtls_connection_init(struct packet_stream *, int active, struct dtls_cert *cert);
int dtls_connection_init(struct dtls_connection *, struct packet_stream *, int active, struct dtls_cert *cert);
int dtls(struct stream_fd *, const str *s, const endpoint_t *sin);
void dtls_connection_cleanup(struct dtls_connection *);
void dtls_shutdown(struct packet_stream *ps);
@ -109,7 +110,6 @@ INLINE int dtls_is_active(const struct dtls_connection *d) {
}
struct stream_fd *dtls_sfd(struct packet_stream *ps);
struct dtls_connection *dtls_ptr(struct stream_fd *sfd);

@ -45,7 +45,6 @@ static void free_stats_block(struct ssrc_stats_block *ssb) {
}
static void __free_ssrc_entry_call(void *ep) {
struct ssrc_entry_call *e = ep;
ilog(LOG_DEBUG, "__free_ssrc_entry_call");
g_queue_clear_full(&e->sender_reports, (GDestroyNotify) free_sender_report);
g_queue_clear_full(&e->rr_time_reports, (GDestroyNotify) free_rr_time);
g_queue_clear_full(&e->stats_blocks, (GDestroyNotify) free_stats_block);

Loading…
Cancel
Save