keep track of sdp stream endpoints and use them as index when rewriting

git.mgm/mediaproxy-ng/2.2
Richard Fuchs 13 years ago
parent 7651df841a
commit 6adda7c301

@ -2187,6 +2187,26 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, GQueue *streams, ben
}
}
static unsigned int stream_hash(struct stream_input *s) {
unsigned int ret, *p;
ret = s->stream.port;
p = (void *) &s->stream.ip46;
while (((void *) p) < (((void *) &s->stream.ip46) + sizeof(s->stream.ip46))) {
ret ^= *p;
p++;
}
return ret;
}
static int stream_equal(struct stream_input *a, struct stream_input *b) {
if (a->stream.port != b->stream.port)
return 0;
if (memcmp(&a->stream.ip46, &b->stream.ip46, sizeof(a->stream.ip46)))
return 0;
return 1;
}
static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output, enum call_opmode opmode, const char *tagname) {
str sdp, fromtag, viabranch, callid;
char *errstr;
@ -2196,6 +2216,7 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster
int ret, num;
struct sdp_ng_flags flags;
struct sdp_chopper *chopper;
GHashTable *streamhash;
if (!bencode_dictionary_get_str(input, "sdp", &sdp))
return "No SDP body in message";
@ -2209,8 +2230,9 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster
if (sdp_parse(&sdp, &parsed))
return "Failed to parse SDP";
streamhash = g_hash_table_new((GHashFunc) stream_hash, (GEqualFunc) stream_equal);
errstr = "Incomplete SDP specification";
if (sdp_streams(&parsed, &streams))
if (sdp_streams(&parsed, &streams, streamhash))
goto out;
call_ng_process_flags(&flags, &streams, input);
@ -2224,7 +2246,7 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster
chopper = sdp_chopper_new(&sdp);
bencode_buffer_destroy_add(output->buffer, (free_func_t) sdp_chopper_destroy, chopper);
num = call_streams(call, &streams, &fromtag, opmode);
ret = sdp_replace(chopper, &parsed, call, (num >= 0) ? opmode : (opmode ^ 1), &flags);
ret = sdp_replace(chopper, &parsed, call, (num >= 0) ? opmode : (opmode ^ 1), &flags, streamhash);
mutex_unlock(&call->lock);
obj_put(call);
@ -2241,6 +2263,7 @@ static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster
out:
sdp_free(&parsed);
streams_free(&streams);
g_hash_table_destroy(streamhash);
log_info = NULL;
return errstr;

@ -296,13 +296,27 @@ void sdp_free(GQueue *sessions) {
}
}
int sdp_streams(const GQueue *sessions, GQueue *streams) {
static int fill_stream(struct stream_input *si, struct sdp_media *media, struct sdp_session *session, int offset) {
if (media->connection.parsed)
si->stream.ip46 = media->connection.address.parsed;
else if (session->connection.parsed)
si->stream.ip46 = session->connection.address.parsed;
else
return -1;
/* we ignore the media type */
si->stream.port = (media->port_num + (offset * 2)) & 0xffff;
return 0;
}
int sdp_streams(const GQueue *sessions, GQueue *streams, GHashTable *streamhash) {
struct sdp_session *session;
struct sdp_media *media;
struct stream_input *si;
GList *l, *k;
const char *errstr;
int i, num, cons_num;
int i, num;
num = 0;
for (l = sessions->head; l; l = l->next) {
@ -311,24 +325,22 @@ int sdp_streams(const GQueue *sessions, GQueue *streams) {
for (k = session->media_streams.head; k; k = k->next) {
media = k->data;
cons_num = media->port_count;
for (i = 0; i < media->port_count; i++) {
si = g_slice_alloc0(sizeof(*si));
errstr = "No address info found for stream";
if (media->connection.parsed)
si->stream.ip46 = media->connection.address.parsed;
else if (session->connection.parsed)
si->stream.ip46 = session->connection.address.parsed;
else
if (fill_stream(si, media, session, i))
goto error;
/* we ignore the media type */
si->stream.port = (media->port_num + (i * 2)) & 0xffff;
if (i == 0 && g_hash_table_contains(streamhash, si)) {
g_slice_free1(sizeof(*si), si);
continue;
}
si->stream.num = ++num;
si->consecutive_num = cons_num;
cons_num = 1;
si->consecutive_num = (i == 0) ? media->port_count : 1;
g_hash_table_insert(streamhash, si, si);
g_queue_push_tail(streams, si);
}
}
@ -499,14 +511,14 @@ void sdp_chopper_destroy(struct sdp_chopper *chop) {
}
/* XXX use stream numbers as index */
/* XXX use port numbers as index */
int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
enum call_opmode opmode, struct sdp_ng_flags *flags)
enum call_opmode opmode, struct sdp_ng_flags *flags, GHashTable *streamhash)
{
struct sdp_session *session;
struct sdp_media *media;
GList *l, *k, *m;
int off, skip;
struct stream_input si, *sip;
off = opmode;
m = call->callstreams->head;
@ -526,6 +538,19 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
for (k = session->media_streams.head; k; k = k->next) {
media = k->data;
if (fill_stream(&si, media, session, 0))
goto error;
sip = g_hash_table_lookup(streamhash, &si);
if (!sip)
goto error;
if (!m)
m = call->callstreams->head;
while (m && ((struct callstream *) m->data)->num < sip->stream.num)
m = m->next;
while (m && ((struct callstream *) m->data)->num > sip->stream.num)
m = m->prev;
skip = replace_media_port(chop, media, m, off);
if (skip < 0)
goto error;

@ -27,9 +27,9 @@ struct sdp_chopper {
};
int sdp_parse(str *body, GQueue *sessions);
int sdp_streams(const GQueue *sessions, GQueue *streams);
int sdp_streams(const GQueue *sessions, GQueue *streams, GHashTable *);
void sdp_free(GQueue *sessions);
int sdp_replace(struct sdp_chopper *, GQueue *, struct call *, enum call_opmode, struct sdp_ng_flags *);
int sdp_replace(struct sdp_chopper *, GQueue *, struct call *, enum call_opmode, struct sdp_ng_flags *, GHashTable *);
struct sdp_chopper *sdp_chopper_new(str *input);
void sdp_chopper_destroy(struct sdp_chopper *chop);

Loading…
Cancel
Save