Module: sems Branch: master Commit: 10ba13bf80f5210d61feedbd8fe7fb312af92e5e URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=10ba13bf80f5210d61feedbd8fe7fb312af92e5e
Author: Stefan Sayer <[email protected]> Committer: Stefan Sayer <[email protected]> Date: Wed Nov 3 18:36:20 2010 +0100 add unknown attributes (a=) parsing both session and media level --- core/AmSdp.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- core/AmSdp.h | 21 ++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletions(-) diff --git a/core/AmSdp.cpp b/core/AmSdp.cpp index ddfd365..cbac63b 100644 --- a/core/AmSdp.cpp +++ b/core/AmSdp.cpp @@ -28,6 +28,7 @@ using std::map; #include "strings.h" #endif +static void parse_session_attr(AmSdp* sdp_msg, char* s, char** next); static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s); static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t); static void parse_sdp_media(AmSdp* sdp_msg, char* s); @@ -37,6 +38,7 @@ static void parse_sdp_origin(AmSdp* sdp_masg, char* s); inline char* get_next_line(char* s); static char* is_eql_next(char* s); static char* parse_until(char* s, char end); +static char* parse_until(char* s, char* end, char c); static bool contains(char* s, char* next_line, char c); static bool is_wsp(char s); @@ -99,6 +101,13 @@ bool SdpPayload::operator == (int r) return payload_type == r; } +string SdpAttribute::print() const { + if (value.empty()) + return "a="+attribute+CRLF; + else + return "a="+attribute+":"+value+CRLF; +} + // // class AmSdp: Methods // @@ -167,6 +176,12 @@ void AmSdp::print(string& body) const "c=IN IP4 "+conn.address+"\r\n" "t=0 0\r\n"; + // add attributes (session level) + for (std::vector<SdpAttribute>::const_iterator a_it= + attributes.begin(); a_it != attributes.end(); a_it++) { + out_buf += a_it->print(); + } + for(std::vector<SdpMedia>::const_iterator media_it = media.begin(); media_it != media.end(); media_it++) { @@ -200,6 +215,13 @@ void AmSdp::print(string& body) const if(remote_active /* dir == SdpMedia::DirActive */) out_buf += "a=direction:passive\r\n"; + + // add attributes (media level) + for (std::vector<SdpAttribute>::const_iterator a_it= + media_it->attributes.begin(); a_it != media_it->attributes.end(); a_it++) { + out_buf += a_it->print(); + } + } body = out_buf; @@ -508,7 +530,8 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s) case 'a': DBG("parse_sdp_line_ex: found attributes\n"); s = is_eql_next(s); - next = get_next_line(s); + parse_session_attr(sdp_msg, s, &next); + // next = get_next_line(s); // parse_sdp_attr(sdp_msg, s); s = next; state = SDP_DESCR; @@ -776,6 +799,40 @@ static void parse_sdp_media(AmSdp* sdp_msg, char* s) return; } +static void parse_session_attr(AmSdp* sdp_msg, char* s, char** next) { + *next = get_next_line(s); + if (*next == s) { + WARN("premature end of SDP in session attr\n"); + while (**next != '\0') (*next)++; + return; + } + char* attr_end = *next-1; + while (attr_end >= s && + ((*attr_end == 10) || (*attr_end == 13))) + attr_end--; + + if (*attr_end == ':') { + WARN("incorrect SDP: value attrib without value: '%s'\n", + string(s, attr_end-s+1).c_str()); + return; + } + + char* col = parse_until(s, attr_end, ':'); + + if (col == attr_end) { + // property attribute + sdp_msg->attributes.push_back(SdpAttribute(string(s, attr_end-s+1))); + DBG("got session attribute '%.*s\n", attr_end-s+1, s); + } else { + // value attribute + sdp_msg->attributes.push_back(SdpAttribute(string(s, col-s-1), + string(col, attr_end-col+1))); + DBG("got session attribute '%.*s:%.*s'\n", col-s-1, s, attr_end-col+1, col); + + } + +} + static void parse_sdp_attr(AmSdp* sdp_msg, char* s) { @@ -960,6 +1017,7 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s) string value(attr_line, int(next-attr_line)-1); DBG("found media attr '%s' value '%s'\n", (char*)attr.c_str(), (char*)value.c_str()); + media.attributes.push_back(SdpAttribute(attr, value)); } else { DBG("found media attr '%s', but value is not followed by cr\n", (char *)attr.c_str()); @@ -973,6 +1031,7 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s) string attr(attr_line, int(next-attr_line)-1); attr_check(attr); DBG("found media attr '%s'\n", (char*)attr.c_str()); + media.attributes.push_back(SdpAttribute(attr)); } else { DBG("found media attr line '%s', which is not followed by cr\n", attr_line); @@ -1120,6 +1179,16 @@ static char* parse_until(char* s, char end) return line; } +static char* parse_until(char* s, char* end, char c) +{ + char* line=s; + while(line<end && *line && *line != c ){ + line++; + } + if (line<end) + line++; + return line; +} static char* is_eql_next(char* s) { diff --git a/core/AmSdp.h b/core/AmSdp.h index 79967ab..7c01083 100644 --- a/core/AmSdp.h +++ b/core/AmSdp.h @@ -106,6 +106,23 @@ struct SdpPayload bool operator == (int r); }; +/** \brief a=... line in SDP */ +struct SdpAttribute +{ + string attribute; + string value; + + // property attribute + SdpAttribute(const string& attribute, + const string& value) + : attribute(attribute), value(value) { } + + // value attribute + SdpAttribute(const string& attribute) + : attribute(attribute) { } + + string print() const; +}; /** \brief m=... line in SDP */ struct SdpMedia @@ -125,6 +142,8 @@ struct SdpMedia std::vector<SdpPayload> payloads; + std::vector<SdpAttribute> attributes; // unknown attributes + SdpMedia() : conn() {} }; @@ -152,6 +171,8 @@ public: string sessionName; // s= string uri; // u= SdpConnection conn; // c= + std::vector<SdpAttribute> attributes; // unknown session level attributes + std::vector<SdpMedia> media; // m= ... [a=rtpmap:...]+ // Supported payloads _______________________________________________ Semsdev mailing list [email protected] http://lists.iptel.org/mailman/listinfo/semsdev
