|
|
|
@ -121,7 +121,7 @@ struct sdp_media { |
|
|
|
int port_count; |
|
|
|
|
|
|
|
struct sdp_connection connection; |
|
|
|
const char *c_line_pos; |
|
|
|
const char *c_line_pos; // XXX to be obsoleted |
|
|
|
struct session_bandwidth bandwidth; |
|
|
|
struct sdp_attributes attributes; |
|
|
|
str_slice_q format_list; /* list of slice-alloc'd str objects */ |
|
|
|
@ -266,7 +266,7 @@ enum attribute_other { |
|
|
|
|
|
|
|
struct sdp_attribute { |
|
|
|
/* example: a=rtpmap:8 PCMA/8000 */ |
|
|
|
str full_line; /* including a= and \r\n */ |
|
|
|
str full_line; /* including a= and \r\n */ // XXX to be obsoleted |
|
|
|
str param; /* "PCMA/8000" */ |
|
|
|
|
|
|
|
struct sdp_attribute_strs strs; |
|
|
|
@ -1213,59 +1213,59 @@ static int parse_attribute(struct sdp_attribute *a) { |
|
|
|
} |
|
|
|
|
|
|
|
int sdp_parse(str *body, sdp_sessions_q *sessions, const sdp_ng_flags *flags) { |
|
|
|
char *b, *end, *value, *line_end, *next_line; |
|
|
|
str b; |
|
|
|
struct sdp_session *session = NULL; |
|
|
|
struct sdp_media *media = NULL; |
|
|
|
const char *errstr; |
|
|
|
struct sdp_attributes *attrs; |
|
|
|
struct sdp_attribute *attr; |
|
|
|
str *adj_s; |
|
|
|
int media_sdp_id = 0; |
|
|
|
|
|
|
|
b = body->s; |
|
|
|
end = str_end(body); |
|
|
|
b = *body; |
|
|
|
|
|
|
|
while (b && b < end - 1) { |
|
|
|
while (b.len >= 2) { |
|
|
|
if (!rtpe_config.reject_invalid_sdp) { |
|
|
|
if (b[0] == '\n' || b[0] == '\r') { |
|
|
|
body->len = b - body->s; |
|
|
|
if (b.s[0] == '\n' || b.s[0] == '\r') { |
|
|
|
body->len = b.s - body->s; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
char line_code = b.s[0]; |
|
|
|
|
|
|
|
errstr = "Missing '=' sign"; |
|
|
|
if (b[1] != '=') |
|
|
|
if (b.s[1] != '=') |
|
|
|
goto error; |
|
|
|
|
|
|
|
value = &b[2]; |
|
|
|
line_end = memchr(value, '\n', end - value); |
|
|
|
if (!line_end) { |
|
|
|
/* assume missing LF at end of body */ |
|
|
|
line_end = end; |
|
|
|
next_line = NULL; |
|
|
|
} |
|
|
|
else { |
|
|
|
next_line = line_end + 1; |
|
|
|
if (line_end[-1] == '\r') |
|
|
|
line_end--; |
|
|
|
} |
|
|
|
str full_line; |
|
|
|
str_token(&full_line, &b, '\n'); |
|
|
|
if (full_line.s[full_line.len - 1] == '\r') |
|
|
|
full_line.len--; |
|
|
|
|
|
|
|
errstr = "SDP doesn't start with a session definition"; |
|
|
|
if (!session && b[0] != 'v') { |
|
|
|
if (!session && line_code != 'v') { |
|
|
|
if (!flags->fragment) |
|
|
|
goto error; |
|
|
|
else |
|
|
|
goto new_session; // allowed for trickle ICE SDP fragments |
|
|
|
} |
|
|
|
|
|
|
|
str value_str = STR_LEN(value, line_end - value); |
|
|
|
str value = full_line; |
|
|
|
str_shift(&value, 2); // removes `v=` etc |
|
|
|
|
|
|
|
full_line.len = b.s - full_line.s; // include \r\n |
|
|
|
|
|
|
|
switch (b[0]) { |
|
|
|
switch (line_code) { |
|
|
|
case 'v': |
|
|
|
errstr = "Error in v= line"; |
|
|
|
if (line_end != value + 1) |
|
|
|
if (value.len != 1) { |
|
|
|
abort(); |
|
|
|
goto error; |
|
|
|
if (value[0] != '0') |
|
|
|
} |
|
|
|
if (value.s[0] != '0') { |
|
|
|
abort(); |
|
|
|
goto error; |
|
|
|
} |
|
|
|
|
|
|
|
new_session: |
|
|
|
session = g_slice_alloc0(sizeof(*session)); |
|
|
|
@ -1273,7 +1273,7 @@ new_session: |
|
|
|
attrs_init(&session->attributes); |
|
|
|
t_queue_push_tail(sessions, session); |
|
|
|
media = NULL; |
|
|
|
session->s.s = b; |
|
|
|
session->s = full_line; |
|
|
|
RESET_BANDWIDTH(session->bandwidth, -1); |
|
|
|
|
|
|
|
break; |
|
|
|
@ -1283,30 +1283,31 @@ new_session: |
|
|
|
if (media) |
|
|
|
goto error; |
|
|
|
errstr = "Error parsing o= line"; |
|
|
|
if (parse_origin(&value_str, &session->origin)) |
|
|
|
if (parse_origin(&value, &session->origin)) |
|
|
|
goto error; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 'm': |
|
|
|
if (media && !media->c_line_pos) |
|
|
|
media->c_line_pos = b; |
|
|
|
media->c_line_pos = full_line.s; |
|
|
|
|
|
|
|
|
|
|
|
media = g_slice_alloc0(sizeof(*media)); |
|
|
|
media->session = session; |
|
|
|
attrs_init(&media->attributes); |
|
|
|
errstr = "Error parsing m= line"; |
|
|
|
if (parse_media(&value_str, media)) |
|
|
|
if (parse_media(&value, media)) |
|
|
|
goto error; |
|
|
|
t_queue_push_tail(&session->media_streams, media); |
|
|
|
media->s.s = b; |
|
|
|
media->s = full_line; |
|
|
|
RESET_BANDWIDTH(media->bandwidth, -1); |
|
|
|
media->media_sdp_id = media_sdp_id++; |
|
|
|
break; |
|
|
|
|
|
|
|
case 'c': |
|
|
|
errstr = "Error parsing c= line"; |
|
|
|
if (parse_connection(&value_str, |
|
|
|
if (parse_connection(&value, |
|
|
|
media ? &media->connection : &session->connection)) |
|
|
|
goto error; |
|
|
|
|
|
|
|
@ -1314,15 +1315,12 @@ new_session: |
|
|
|
|
|
|
|
case 'a': |
|
|
|
if (media && !media->c_line_pos) |
|
|
|
media->c_line_pos = b; |
|
|
|
media->c_line_pos = full_line.s; |
|
|
|
|
|
|
|
attr = g_slice_alloc0(sizeof(*attr)); |
|
|
|
|
|
|
|
attr->full_line.s = b; |
|
|
|
attr->full_line.len = next_line ? (next_line - b) : (line_end - b); |
|
|
|
|
|
|
|
attr->strs.line_value.s = value; |
|
|
|
attr->strs.line_value.len = line_end - value; |
|
|
|
attr->full_line = full_line; |
|
|
|
attr->strs.line_value = value; |
|
|
|
|
|
|
|
if (parse_attribute(attr)) { |
|
|
|
attr_free(attr); |
|
|
|
@ -1336,48 +1334,48 @@ new_session: |
|
|
|
|
|
|
|
case 'b': |
|
|
|
if (media && !media->c_line_pos) |
|
|
|
media->c_line_pos = b; |
|
|
|
media->c_line_pos = full_line.s; |
|
|
|
|
|
|
|
/* RR:0 */ |
|
|
|
if (line_end - value < 4) |
|
|
|
if (value.len < 4) |
|
|
|
break; |
|
|
|
|
|
|
|
/* AS, RR, RS */ |
|
|
|
if (!memcmp(value, "AS:", 3)) { |
|
|
|
*(media ? &media->bandwidth.as : &session->bandwidth.as) = strtol((value + 3), NULL, 10); |
|
|
|
if (!memcmp(value.s, "AS:", 3)) { |
|
|
|
*(media ? &media->bandwidth.as : &session->bandwidth.as) = strtol((value.s + 3), NULL, 10); |
|
|
|
} |
|
|
|
else if (!memcmp(value, "RR:", 3)) { |
|
|
|
*(media ? &media->bandwidth.rr : &session->bandwidth.rr) = strtol((value + 3), NULL, 10); |
|
|
|
else if (!memcmp(value.s, "RR:", 3)) { |
|
|
|
*(media ? &media->bandwidth.rr : &session->bandwidth.rr) = strtol((value.s + 3), NULL, 10); |
|
|
|
} |
|
|
|
else if (!memcmp(value, "RS:", 3)) { |
|
|
|
*(media ? &media->bandwidth.rs : &session->bandwidth.rs) = strtol((value + 3), NULL, 10); |
|
|
|
else if (!memcmp(value.s, "RS:", 3)) { |
|
|
|
*(media ? &media->bandwidth.rs : &session->bandwidth.rs) = strtol((value.s + 3), NULL, 10); |
|
|
|
} |
|
|
|
else if (!memcmp(value, "TIAS:", 5)) { |
|
|
|
*(media ? &media->bandwidth.tias : &session->bandwidth.tias) = strtol((value + 5), NULL, 10); |
|
|
|
else if (!memcmp(value.s, "TIAS:", 5)) { |
|
|
|
*(media ? &media->bandwidth.tias : &session->bandwidth.tias) = strtol((value.s + 5), NULL, 10); |
|
|
|
} |
|
|
|
/* CT has only session level */ |
|
|
|
else if (!memcmp(value, "CT:", 3)) { |
|
|
|
session->bandwidth.ct = strtol((value + 3), NULL, 10); |
|
|
|
else if (!memcmp(value.s, "CT:", 3)) { |
|
|
|
session->bandwidth.ct = strtol((value.s + 3), NULL, 10); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case 'k': |
|
|
|
if (media && !media->c_line_pos) |
|
|
|
media->c_line_pos = b; |
|
|
|
media->c_line_pos = full_line.s; |
|
|
|
break; |
|
|
|
|
|
|
|
case 's': |
|
|
|
errstr = "s= line found within media section"; |
|
|
|
if (media) |
|
|
|
goto error; |
|
|
|
session->session_name = value_str; |
|
|
|
session->session_name = value; |
|
|
|
break; |
|
|
|
|
|
|
|
case 't': |
|
|
|
errstr = "t= line found within media section"; |
|
|
|
if (media) |
|
|
|
goto error; |
|
|
|
session->session_timing = value_str; |
|
|
|
session->session_timing = value; |
|
|
|
break; |
|
|
|
|
|
|
|
case 'i': |
|
|
|
@ -1397,16 +1395,15 @@ new_session: |
|
|
|
if (!session) |
|
|
|
goto error; |
|
|
|
|
|
|
|
adj_s = media ? &media->s : &session->s; |
|
|
|
adj_s->len = (next_line ? : end) - adj_s->s; |
|
|
|
|
|
|
|
b = next_line; |
|
|
|
// XXX to be obsoleted |
|
|
|
str *adj_s = media ? &media->s : &session->s; |
|
|
|
adj_s->len = b.s - adj_s->s; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
error: |
|
|
|
ilog(LOG_WARNING, "Error parsing SDP at offset %li: %s", (long) (b - body->s), errstr); |
|
|
|
ilog(LOG_WARNING, "Error parsing SDP at offset %zu: %s", (size_t) (b.s - body->s), errstr); |
|
|
|
sdp_sessions_clear(sessions); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|