Browse Source

add support for non-standard rtcp ports

git.mgm/mediaproxy-ng/2.2
Richard Fuchs 13 years ago
parent
commit
3c10c9ac17
2 changed files with 138 additions and 67 deletions
  1. +1
    -0
      daemon/call.h
  2. +137
    -67
      daemon/sdp.c

+ 1
- 0
daemon/call.h View File

@ -62,6 +62,7 @@ struct stream_input {
struct stream stream;
enum stream_direction direction[2];
int consecutive_num;
int has_rtcp:1;
};
struct udp_fd {
int fd;


+ 137
- 67
daemon/sdp.c View File

@ -72,6 +72,7 @@ struct sdp_attribute {
enum {
ATTR_OTHER = 0,
ATTR_RTCP,
ATTR_ICE,
} attr;
union {
@ -261,6 +262,32 @@ static void parse_attribute(struct sdp_attribute *a) {
if (!str_cmp(&a->name, "rtcp"))
parse_attribute_rtcp(a);
break;
case 7:
if (!str_cmp(&a->name, "ice-pwd"))
a->attr = ATTR_ICE;
break;
case 8:
if (!str_cmp(&a->name, "ice-lite"))
a->attr = ATTR_ICE;
break;
case 9:
if (!str_cmp(&a->name, "candidate"))
a->attr = ATTR_ICE;
else if (!str_cmp(&a->name, "ice-ufrag"))
a->attr = ATTR_ICE;
break;
case 11:
if (!str_cmp(&a->name, "ice-options"))
a->attr = ATTR_ICE;
break;
case 12:
if (!str_cmp(&a->name, "ice-mismatch"))
a->attr = ATTR_ICE;
break;
case 17:
if (!str_cmp(&a->name, "remote-candidates"))
a->attr = ATTR_ICE;
break;
}
}
@ -413,13 +440,19 @@ void sdp_free(GQueue *sessions) {
}
}
static int fill_stream(struct stream_input *si, struct sdp_media *media, struct sdp_session *session, int offset) {
static int fill_stream_address(struct stream_input *si, struct sdp_media *media, struct sdp_session *session) {
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;
return 0;
}
static int fill_stream(struct stream_input *si, struct sdp_media *media, struct sdp_session *session, int offset) {
if (fill_stream_address(si, media, session))
return -1;
/* we ignore the media type */
si->stream.port = (media->port_num + (offset * 2)) & 0xffff;
@ -427,6 +460,13 @@ static int fill_stream(struct stream_input *si, struct sdp_media *media, struct
return 0;
}
static int fill_stream_rtcp(struct stream_input *si, struct sdp_media *media, struct sdp_session *session, int port) {
if (fill_stream_address(si, media, session))
return -1;
si->stream.port = port;
return 0;
}
int sdp_streams(const GQueue *sessions, GQueue *streams, GHashTable *streamhash) {
struct sdp_session *session;
struct sdp_media *media;
@ -466,10 +506,23 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, GHashTable *streamhash)
if (!si || media->port_count != 1)
continue;
str_init(&s, "rtcp");
str_init(&s, "rtcp"); /* XXX use the enum for hash instead? */
attr = g_hash_table_lookup(media->attributes.hash, &s);
if (!attr)
if (!attr || !attr->u.rtcp.port_num)
continue;
if (attr->u.rtcp.port_num == si->stream.port + 1)
continue;
si->has_rtcp = 1;
si = g_slice_alloc0(sizeof(*si));
if (fill_stream_rtcp(si, media, session, attr->u.rtcp.port_num))
goto error;
si->stream.num = ++num;
si->consecutive_num = 1;
g_hash_table_insert(streamhash, si, si);
g_queue_push_tail(streams, si);
}
}
@ -477,6 +530,8 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, GHashTable *streamhash)
error:
mylog(LOG_WARNING, "Failed to extract streams from SDP: %s", errstr);
if (si)
g_slice_free1(sizeof(*si), si);
return -1;
}
@ -608,21 +663,14 @@ warn:
return 0;
}
static int insert_ice_address(struct sdp_chopper *chop, GList *m, int off, struct sdp_ng_flags *flags, int streamoff) {
struct callstream *cs;
struct peer *peer;
struct streamrelay *sr;
static int insert_ice_address(struct sdp_chopper *chop, struct sdp_ng_flags *flags, struct streamrelay *sr) {
char buf[64];
int len;
cs = m->data;
peer = &cs->peers[off];
sr = &peer->rtps[streamoff];
if (!flags->trust_address && flags->received_from_family.len == 3 && flags->received_from_address.len)
chopper_append_str(chop, &flags->received_from_address);
else {
call_stream_address(buf, peer, SAF_ICE, &len);
call_stream_address(buf, sr->up, SAF_ICE, &len);
chopper_append_dup(chop, buf, len);
}
@ -631,7 +679,9 @@ static int insert_ice_address(struct sdp_chopper *chop, GList *m, int off, struc
return 0;
}
static int replace_network_address(struct sdp_chopper *chop, struct network_address *address, GList *m, int off, struct sdp_ng_flags *flags) {
static int replace_network_address(struct sdp_chopper *chop, struct network_address *address,
GList *m, int off, struct sdp_ng_flags *flags)
{
struct callstream *cs;
struct peer *peer;
char buf[64];
@ -670,39 +720,36 @@ void sdp_chopper_destroy(struct sdp_chopper *chop) {
g_slice_free1(sizeof(*chop), chop);
}
static int remove_ice(struct sdp_chopper *chop, struct sdp_attributes *attrs) {
struct sdp_attribute *attr;
static void random_string(char *buf, int len) {
while (len--)
*buf++ = ice_chars[random() % strlen(ice_chars)];
}
static void create_random_string(struct call *call, str *s, int len) {
char buf[30];
assert(len < sizeof(buf));
if (s->s)
return;
random_string(buf, len);
call_str_cpy_len(call, s, buf, len);
}
static int process_session_attributes(struct sdp_chopper *chop, struct sdp_attributes *attrs, struct sdp_ng_flags *flags) {
GList *l;
struct sdp_attribute *attr;
for (l = attrs->list.head; l; l = l->next) {
attr = l->data;
switch (attr->name.len) {
case 7:
if (!str_cmp(&attr->name, "ice-pwd"))
goto strip;
break;
case 8:
if (!str_cmp(&attr->name, "ice-lite"))
goto strip;
break;
case 9:
if (!str_cmp(&attr->name, "candidate"))
goto strip;
if (!str_cmp(&attr->name, "ice-ufrag"))
goto strip;
break;
case 11:
if (!str_cmp(&attr->name, "ice-options"))
goto strip;
break;
case 12:
if (!str_cmp(&attr->name, "ice-mismatch"))
goto strip;
break;
case 17:
if (!str_cmp(&attr->name, "remote-candidates"))
goto strip;
switch (attr->attr) {
case ATTR_ICE:
if (!flags->ice_remove && !flags->ice_force)
break;
goto strip;
default:
break;
}
@ -718,20 +765,37 @@ strip:
return 0;
}
static void random_string(char *buf, int len) {
while (len--)
*buf++ = ice_chars[random() % strlen(ice_chars)];
}
static int process_media_attributes(struct sdp_chopper *chop, struct sdp_attributes *attrs, struct sdp_ng_flags *flags)
{
GList *l;
struct sdp_attribute *attr;
static void create_random_string(struct call *call, str *s, int len) {
char buf[30];
for (l = attrs->list.head; l; l = l->next) {
attr = l->data;
assert(len < sizeof(buf));
if (s->s)
return;
switch (attr->attr) {
case ATTR_ICE:
if (!flags->ice_remove && !flags->ice_force)
break;
goto strip;
random_string(buf, len);
call_str_cpy_len(call, s, buf, len);
case ATTR_RTCP:
goto strip;
default:
break;
}
continue;
strip:
if (copy_up_to(chop, &attr->full_line))
return -1;
if (skip_over(chop, &attr->full_line))
return -1;
}
return 0;
}
int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
@ -742,6 +806,7 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
GList *l, *k, *m;
int off;
struct stream_input si, *sip;
struct streamrelay *rtp, *rtcp;
off = opmode;
m = call->callstreams->head;
@ -758,11 +823,8 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
goto error;
}
/* XXX convert to a "process attributes" kinda function */
if (flags->ice_remove || flags->ice_force) {
if (remove_ice(chop, &session->attributes))
goto error;
}
if (process_session_attributes(chop, &session->attributes, flags))
goto error;
if (flags->ice_force) {
create_random_string(call, &call->ice_ufrag[0], 4);
@ -775,7 +837,6 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
chopper_append_c(chop, "\r\na=ice-pwd:");
chopper_append_str(chop, &call->ice_pwd);
chopper_append_c(chop, "\r\n");
/* XXX handle RTCP attributes */
}
for (k = session->media_streams.head; k; k = k->next) {
@ -787,6 +848,7 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
sip = g_hash_table_lookup(streamhash, &si);
if (!sip)
goto error;
/* XXX use a hash instead? must link input streams to output streams */
if (!m)
m = call->callstreams->head;
while (m && ((struct callstream *) m->data)->num < sip->stream.num)
@ -794,6 +856,12 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
while (m && ((struct callstream *) m->data)->num > sip->stream.num)
m = m->prev;
/* XXX use those in function calls exclusively */
rtp = &((struct callstream *) m->data)->peers[off].rtps[0];
rtcp = &((struct callstream *) m->data)->peers[off].rtps[1];
if (sip->has_rtcp && m->next)
rtcp = &((struct callstream *) m->next->data)->peers[off].rtps[0];
if (replace_media_port(chop, media, m, off))
goto error;
@ -802,26 +870,28 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
goto error;
}
/* XXX convert to a "process attributes" kinda function */
if (flags->ice_remove || flags->ice_force) {
if (remove_ice(chop, &media->attributes))
goto error;
}
if (process_media_attributes(chop, &media->attributes, flags))
goto error;
copy_up_to_end_of(chop, &media->s);
/* XXX create exception for b=..:0 cases */
chopper_append_c(chop, "a=rtcp:");
chopper_append_printf(chop, "%hu", rtcp->fd.localport);
chopper_append_c(chop, "\r\n");
if (flags->ice_force) {
copy_up_to_end_of(chop, &media->s);
/* prio = (2^24) * 126 + (2^8) * 65535 + (256 - componentID) */
chopper_append_c(chop, "a=candidate:");
chopper_append_str(chop, &ice_foundation_str);
chopper_append_c(chop, " 1 UDP 2130706431 ");
insert_ice_address(chop, m, off, flags, 0);
insert_ice_address(chop, flags, rtp);
chopper_append_c(chop, " typ host\r\n");
chopper_append_c(chop, "a=candidate:");
chopper_append_str(chop, &ice_foundation_str);
chopper_append_c(chop, " 2 UDP 2130706430 ");
insert_ice_address(chop, m, off, flags, 1);
insert_ice_address(chop, flags, rtcp);
chopper_append_c(chop, " typ host\r\n");
/* XXX handle rtcp here too */
}
}
}


Loading…
Cancel
Save