diff --git a/daemon/sdp.c b/daemon/sdp.c index da71859d4..059102555 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -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; }