Browse Source

TT#12800 canonicalize ssrc handling

Change-Id: I481dd4062f044f9f7add65b4b82d276629f47ce8
changes/69/12269/15
Richard Fuchs 9 years ago
parent
commit
b3583633e3
9 changed files with 148 additions and 65 deletions
  1. +1
    -1
      daemon/Makefile
  2. +3
    -0
      daemon/call.c
  3. +2
    -0
      daemon/call.h
  4. +0
    -38
      daemon/crypto.h
  5. +3
    -2
      daemon/media_socket.c
  6. +14
    -22
      daemon/rtp.c
  7. +4
    -2
      daemon/rtp.h
  8. +74
    -0
      daemon/ssrc.c
  9. +47
    -0
      daemon/ssrc.h

+ 1
- 1
daemon/Makefile View File

@ -38,7 +38,7 @@ include ../lib/lib.Makefile
SRCS= main.c kernel.c poller.c aux.c control_tcp.c streambuf.c call.c control_udp.c redis.c \
bencode.c cookie_cache.c udp_listener.c control_ng.c sdp.c str.c stun.c rtcp.c \
crypto.c rtp.c call_interfaces.c dtls.c log.c cli.c graphite.c ice.c socket.c \
media_socket.c rtcp_xr.c homer.c recording.c statistics.c cdr.c
media_socket.c rtcp_xr.c homer.c recording.c statistics.c cdr.c ssrc.c
LIBSRCS= loglib.c auxlib.c rtplib.c
OBJS= $(SRCS:.c=.o) $(LIBSRCS:.c=.o)


+ 3
- 0
daemon/call.c View File

@ -40,6 +40,7 @@
#include "rtplib.h"
#include "cdr.h"
#include "statistics.h"
#include "ssrc.h"
/* also serves as array index for callstream->peers[] */
@ -2004,6 +2005,7 @@ static void __call_free(void *p) {
g_hash_table_destroy(c->tags);
g_hash_table_destroy(c->viabranches);
free_ssrc_hash(&c->ssrc_hash);
while (c->streams.head) {
ps = g_queue_pop_head(&c->streams);
@ -2031,6 +2033,7 @@ static struct call *call_create(const str *callid, struct callmaster *m) {
c->created = poller_now;
c->dtls_cert = dtls_cert();
c->tos = m->conf.default_tos;
c->ssrc_hash = create_ssrc_hash();
return c;
}


+ 2
- 0
daemon/call.h View File

@ -204,6 +204,7 @@ struct local_interface;
struct call_monologue;
struct ice_agent;
struct homer_sender;
struct ssrc_hash;
typedef bencode_buffer_t call_buffer_t;
@ -367,6 +368,7 @@ struct call {
GQueue stream_fds;
GQueue endpoint_maps;
struct dtls_cert *dtls_cert; /* for outgoing */
struct ssrc_hash *ssrc_hash;
str callid;
time_t created;


+ 0
- 38
daemon/crypto.h View File

@ -88,15 +88,10 @@ struct crypto_context {
/* <from, to>? */
void *session_key_ctx[2];
GHashTable *ssrc_hash;
int have_session_key:1;
};
struct rtp_ssrc_entry {
u_int32_t ssrc;
u_int64_t index;
};
extern const struct crypto_suite *crypto_suites;
extern const int num_crypto_suites;
@ -109,11 +104,6 @@ const struct crypto_suite *crypto_find_suite(const str *);
int crypto_gen_session_key(struct crypto_context *, str *, unsigned char, int);
void crypto_dump_keys(struct crypto_context *in, struct crypto_context *out);
INLINE struct rtp_ssrc_entry *find_ssrc(u_int32_t, GHashTable *);
INLINE void add_ssrc_entry(struct rtp_ssrc_entry *, GHashTable *);
INLINE struct rtp_ssrc_entry *create_ssrc_entry(u_int32_t, u_int64_t);
INLINE void free_ssrc_table(GHashTable **);
INLINE GHashTable *create_ssrc_table(void);
INLINE int crypto_encrypt_rtp(struct crypto_context *c, struct rtp_header *rtp,
@ -147,7 +137,6 @@ INLINE void crypto_params_cleanup(struct crypto_params *p) {
}
INLINE void crypto_cleanup(struct crypto_context *c) {
crypto_params_cleanup(&c->params);
free_ssrc_table(&c->ssrc_hash);
if (!c->params.crypto_suite)
return;
if (c->params.crypto_suite->session_key_cleanup)
@ -202,31 +191,4 @@ INLINE int crypto_params_cmp(const struct crypto_params *a, const struct crypto_
INLINE struct rtp_ssrc_entry *find_ssrc(u_int32_t ssrc, GHashTable *ht) {
return g_hash_table_lookup(ht, &ssrc);
}
INLINE void add_ssrc_entry(struct rtp_ssrc_entry *ent, GHashTable *ht) {
g_hash_table_insert(ht, &ent->ssrc, ent);
}
INLINE struct rtp_ssrc_entry *create_ssrc_entry(u_int32_t ssrc, u_int64_t index) {
struct rtp_ssrc_entry *ent;
ent = g_slice_alloc(sizeof(struct rtp_ssrc_entry));
ent->ssrc = ssrc;
ent->index = index;
return ent;
}
INLINE void free_ssrc_table(GHashTable **ht) {
if (!*ht)
return;
g_hash_table_destroy(*ht);
*ht = NULL;
}
INLINE void free_ssrc_entry(void *p) {
g_slice_free1(sizeof(struct rtp_ssrc_entry), p);
}
INLINE GHashTable *create_ssrc_table(void) {
return g_hash_table_new_full(uint32_hash, uint32_eq, free_ssrc_entry, NULL);
}
#endif

+ 3
- 2
daemon/media_socket.c View File

@ -21,6 +21,7 @@
#include "recording.h"
#include "rtplib.h"
#include "rtcplib.h"
#include "ssrc.h"
#ifndef PORT_RANDOM_MIN
@ -790,13 +791,13 @@ static int call_avpf2avp_rtcp(str *s, struct packet_stream *stream) {
return rtcp_avpf2avp(s);
}
static int call_avp2savp_rtp(str *s, struct packet_stream *stream) {
return rtp_avp2savp(s, &stream->crypto);
return rtp_avp2savp(s, &stream->crypto, stream->call->ssrc_hash, SSRC_DIR_OUTPUT);
}
static int call_avp2savp_rtcp(str *s, struct packet_stream *stream) {
return rtcp_avp2savp(s, &stream->crypto);
}
static int call_savp2avp_rtp(str *s, struct packet_stream *stream) {
return rtp_savp2avp(s, &stream->selected_sfd->crypto);
return rtp_savp2avp(s, &stream->selected_sfd->crypto, stream->call->ssrc_hash, SSRC_DIR_INPUT);
}
static int call_savp2avp_rtcp(str *s, struct packet_stream *stream) {
return rtcp_savp2avp(s, &stream->selected_sfd->crypto);


+ 14
- 22
daemon/rtp.c View File

@ -9,6 +9,7 @@
#include "crypto.h"
#include "log.h"
#include "rtplib.h"
#include "ssrc.h"
@ -85,11 +86,13 @@ void rtp_append_mki(str *s, struct crypto_context *c) {
s->len += c->params.mki_len;
}
static int rtp_ssrc_check(const struct rtp_header *rtp, struct crypto_context *c) {
struct rtp_ssrc_entry *cur_ssrc;
static int rtp_ssrc_check(const struct rtp_header *rtp, struct crypto_context *c, struct ssrc_hash *ht,
enum ssrc_dir dir)
{
struct ssrc_ctx *ssrc_ctx;
/* check last known SSRC */
if (G_LIKELY(rtp->ssrc == c->ssrc))
if (G_LIKELY(rtp->ssrc == c->ssrc)) // XXX replace by pointer
return 0;
if (!c->ssrc) {
c->ssrc = rtp->ssrc;
@ -98,32 +101,21 @@ static int rtp_ssrc_check(const struct rtp_header *rtp, struct crypto_context *c
/* SSRC mismatch. stash away last know info */
ilog(LOG_DEBUG, "SSRC changed, updating SRTP crypto contexts");
if (G_UNLIKELY(!c->ssrc_hash))
c->ssrc_hash = create_ssrc_table();
// Find the entry for the last SSRC.
cur_ssrc = find_ssrc(c->ssrc, c->ssrc_hash);
// If it doesn't exist, create a new entry.
if (G_UNLIKELY(!cur_ssrc)) {
cur_ssrc = create_ssrc_entry(c->ssrc, c->last_index);
add_ssrc_entry(cur_ssrc, c->ssrc_hash);
}
else
cur_ssrc->index = c->last_index;
ssrc_ctx = get_ssrc_ctx(c->ssrc, ht, dir);
ssrc_ctx->srtp_index = c->last_index;
// New SSRC, set the crypto context.
c->ssrc = rtp->ssrc;
cur_ssrc = find_ssrc(rtp->ssrc, c->ssrc_hash);
if (G_UNLIKELY(!cur_ssrc))
c->last_index = 0;
else
c->last_index = cur_ssrc->index;
ssrc_ctx = get_ssrc_ctx(rtp->ssrc, ht, dir);
c->last_index = ssrc_ctx->srtp_index; // defaults to 0
return 1;
}
/* rfc 3711, section 3.3 */
int rtp_avp2savp(str *s, struct crypto_context *c) {
int rtp_avp2savp(str *s, struct crypto_context *c, struct ssrc_hash *ht, enum ssrc_dir dir) {
struct rtp_header *rtp;
str payload, to_auth;
u_int64_t index;
@ -134,7 +126,7 @@ int rtp_avp2savp(str *s, struct crypto_context *c) {
if (check_session_keys(c))
return -1;
ret = rtp_ssrc_check(rtp, c);
ret = rtp_ssrc_check(rtp, c, ht, dir);
index = packet_index(c, rtp);
/* rfc 3711 section 3.1 */
@ -154,7 +146,7 @@ int rtp_avp2savp(str *s, struct crypto_context *c) {
}
/* rfc 3711, section 3.3 */
int rtp_savp2avp(str *s, struct crypto_context *c) {
int rtp_savp2avp(str *s, struct crypto_context *c, struct ssrc_hash *ht, enum ssrc_dir dir) {
struct rtp_header *rtp;
u_int64_t index;
str payload, to_auth, to_decrypt, auth_tag;
@ -166,7 +158,7 @@ int rtp_savp2avp(str *s, struct crypto_context *c) {
if (check_session_keys(c))
return -1;
ret = rtp_ssrc_check(rtp, c);
ret = rtp_ssrc_check(rtp, c, ht, dir);
index = packet_index(c, rtp);
if (srtp_payloads(&to_auth, &to_decrypt, &auth_tag, NULL,
c->params.session_params.unauthenticated_srtp ? 0 : c->params.crypto_suite->srtp_auth_tag,


+ 4
- 2
daemon/rtp.h View File

@ -10,6 +10,8 @@
struct crypto_context;
struct rtp_header;
struct ssrc_hash;
enum ssrc_dir;
@ -17,8 +19,8 @@ struct rtp_header;
const struct rtp_payload_type *rtp_payload_type(unsigned int, GHashTable *);
int rtp_avp2savp(str *, struct crypto_context *);
int rtp_savp2avp(str *, struct crypto_context *);
int rtp_avp2savp(str *, struct crypto_context *, struct ssrc_hash *, enum ssrc_dir);
int rtp_savp2avp(str *, struct crypto_context *, struct ssrc_hash *, enum ssrc_dir);
void rtp_append_mki(str *s, struct crypto_context *c);
int srtp_payloads(str *to_auth, str *to_decrypt, str *auth_tag, str *mki,


+ 74
- 0
daemon/ssrc.c View File

@ -0,0 +1,74 @@
#include "ssrc.h"
#include <glib.h>
#include "aux.h"
static struct ssrc_entry *create_ssrc_entry(u_int32_t ssrc) {
struct ssrc_entry *ent;
ent = g_slice_alloc0(sizeof(struct ssrc_entry));
ent->ssrc = ssrc;
return ent;
}
static void add_ssrc_entry(struct ssrc_entry *ent, struct ssrc_hash *ht) {
g_hash_table_replace(ht->ht, &ent->ssrc, ent);
}
static void free_ssrc_entry(void *p) {
g_slice_free1(sizeof(struct ssrc_entry), p);
}
struct ssrc_entry *find_ssrc(u_int32_t ssrc, struct ssrc_hash *ht) {
rwlock_lock_r(&ht->lock);
struct ssrc_entry *ret = g_hash_table_lookup(ht->ht, &ssrc);
rwlock_unlock_r(&ht->lock);
return ret;
}
struct ssrc_entry *get_ssrc(u_int32_t ssrc, struct ssrc_hash *ht /* , int *created */) {
struct ssrc_entry *ent;
restart:
ent = find_ssrc(ssrc, ht);
if (G_LIKELY(ent)) {
// if (created)
// *created = 0;
return ent;
}
ent = create_ssrc_entry(ssrc);
rwlock_lock_w(&ht->lock);
if (g_hash_table_lookup(ht->ht, &ssrc)) {
// preempted
rwlock_unlock_w(&ht->lock);
free_ssrc_entry(ent);
goto restart;
}
add_ssrc_entry(ent, ht);
rwlock_unlock_w(&ht->lock);
// if (created)
// *created = 1;
return ent;
}
void free_ssrc_hash(struct ssrc_hash **ht) {
if (!*ht)
return;
g_hash_table_destroy((*ht)->ht);
g_slice_free1(sizeof(**ht), *ht);
*ht = NULL;
}
struct ssrc_hash *create_ssrc_hash(void) {
struct ssrc_hash *ret;
ret = g_slice_alloc0(sizeof(*ret));
ret->ht = g_hash_table_new_full(uint32_hash, uint32_eq, NULL, free_ssrc_entry);
rwlock_init(&ret->lock);
return ret;
}
struct ssrc_ctx *get_ssrc_ctx(u_int32_t ssrc, struct ssrc_hash *ht, enum ssrc_dir dir) {
struct ssrc_entry *s = get_ssrc(ssrc, ht /* , NULL */);
return ((void *) s) + dir;
}

+ 47
- 0
daemon/ssrc.h View File

@ -0,0 +1,47 @@
#ifndef _SSRC_H_
#define _SSRC_H_
#include <sys/types.h>
#include <glib.h>
#include "compat.h"
#include "aux.h"
struct ssrc_hash {
GHashTable *ht;
rwlock_t lock;
};
struct ssrc_ctx {
// XXX lock this?
u_int64_t srtp_index;
// XXX move entire crypto context in here?
};
struct ssrc_entry {
// XXX lock this?
u_int32_t ssrc;
struct ssrc_ctx input_ctx,
output_ctx;
};
enum ssrc_dir {
SSRC_DIR_INPUT = G_STRUCT_OFFSET(struct ssrc_entry, input_ctx),
SSRC_DIR_OUTPUT = G_STRUCT_OFFSET(struct ssrc_entry, output_ctx),
};
void free_ssrc_hash(struct ssrc_hash **);
struct ssrc_hash *create_ssrc_hash(void);
struct ssrc_entry *find_ssrc(u_int32_t, struct ssrc_hash *); // returns NULL if not found
struct ssrc_entry *get_ssrc(u_int32_t, struct ssrc_hash * /* , int *created */); // creates new entry if not found
//void add_ssrc_entry(struct ssrc_entry *, struct ssrc_hash *); // XXX static
//struct ssrc_entry *create_ssrc_entry(u_int32_t);
struct ssrc_ctx *get_ssrc_ctx(u_int32_t, struct ssrc_hash *, enum ssrc_dir); // creates new entry if not found
#endif

Loading…
Cancel
Save