From 2818fe8c1bbe5173cbf83ecfe7ec13585222108d Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Mon, 24 Jun 2013 20:13:42 +0000 Subject: [PATCH] patch: add alternative protocols to sdp - sdp_media_set_alt_protos() and accessor function Example usage: err = sdp_media_set_alt_protos(m->sdp, 4, "RTP/AVP", "RTP/AVPF", "RTP/SAVP", "RTP/SAVPF"); --- include/re_sdp.h | 2 ++ src/sdp/media.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++-- src/sdp/msg.c | 4 +-- src/sdp/sdp.h | 6 +++- 4 files changed, 98 insertions(+), 5 deletions(-) diff --git a/include/re_sdp.h b/include/re_sdp.h index 8340cb4..fbb5060 100644 --- a/include/re_sdp.h +++ b/include/re_sdp.h @@ -87,6 +87,7 @@ struct sdp_media; int sdp_media_add(struct sdp_media **mp, struct sdp_session *sess, const char *name, uint16_t port, const char *proto); +int sdp_media_set_alt_protos(struct sdp_media *m, unsigned protoc, ...); void sdp_media_set_encode_handler(struct sdp_media *m, sdp_media_enc_h *ench, void *arg); void sdp_media_set_fmt_ignore(struct sdp_media *m, bool fmt_ignore); @@ -101,6 +102,7 @@ void sdp_media_set_ldir(struct sdp_media *m, enum sdp_dir dir); int sdp_media_set_lattr(struct sdp_media *m, bool replace, const char *name, const char *value, ...); void sdp_media_del_lattr(struct sdp_media *m, const char *name); +const char *sdp_media_proto(const struct sdp_media *m); uint16_t sdp_media_rport(const struct sdp_media *m); const struct sa *sdp_media_raddr(const struct sdp_media *m); void sdp_media_raddr_rtcp(const struct sdp_media *m, struct sa *raddr); diff --git a/src/sdp/media.c b/src/sdp/media.c index 142d733..ba19cf7 100644 --- a/src/sdp/media.c +++ b/src/sdp/media.c @@ -18,6 +18,7 @@ static void destructor(void *arg) { struct sdp_media *m = arg; + unsigned i; list_flush(&m->lfmtl); list_flush(&m->rfmtl); @@ -31,6 +32,9 @@ static void destructor(void *arg) return; } + for (i=0; iprotov); i++) + mem_deref(m->protov[i]); + list_unlink(&m->le); mem_deref(m->name); mem_deref(m->proto); @@ -171,18 +175,57 @@ void sdp_media_rreset(struct sdp_media *m) } +/** + * Compare media line protocols + * + * @param m SDP Media line + * @param proto Transport protocol + * @param update Update media protocol if match is found in alternate set + * + * @return True if matching, False if not + */ +bool sdp_media_proto_cmp(struct sdp_media *m, const struct pl *proto, + bool update) +{ + unsigned i; + + if (!m || !proto) + return false; + + if (!pl_strcmp(proto, m->proto)) + return true; + + for (i=0; iprotov); i++) { + + if (!m->protov[i] || pl_strcmp(proto, m->protov[i])) + continue; + + if (update) { + mem_deref(m->proto); + m->proto = mem_ref(m->protov[i]); + } + + return true; + } + + return false; +} + + /** * Find an SDP Media line from name and transport protocol * * @param sess SDP Session * @param name Media name * @param proto Transport protocol + * @param update_proto Update media transport protocol * * @return Matching media line if found, NULL if not found */ struct sdp_media *sdp_media_find(const struct sdp_session *sess, const struct pl *name, - const struct pl *proto) + const struct pl *proto, + bool update_proto) { struct le *le; @@ -196,7 +239,7 @@ struct sdp_media *sdp_media_find(const struct sdp_session *sess, if (pl_strcmp(name, m->name)) continue; - if (pl_strcmp(proto, m->proto)) + if (!sdp_media_proto_cmp(m, proto, update_proto)) continue; return m; @@ -290,6 +333,44 @@ void sdp_media_align_formats(struct sdp_media *m, bool offer) } +/** + * Set alternative protocols for an SDP Media line + * + * @param m SDP Media line + * @param protoc Number of alternative protocols + * + * @return 0 if success, otherwise errorcode + */ +int sdp_media_set_alt_protos(struct sdp_media *m, unsigned protoc, ...) +{ + const char *proto; + int err = 0; + unsigned i; + va_list ap; + + if (!m) + return EINVAL; + + va_start(ap, protoc); + + for (i=0; iprotov); i++) { + + m->protov[i] = mem_deref(m->protov[i]); + + if (i >= protoc) + continue; + + proto = va_arg(ap, const char *); + if (proto) + err |= str_dup(&m->protov[i], proto); + } + + va_end(ap); + + return err; +} + + /** * Set SDP Media line encode handler * @@ -475,6 +556,12 @@ void sdp_media_del_lattr(struct sdp_media *m, const char *name) } +const char *sdp_media_proto(const struct sdp_media *m) +{ + return m ? m->proto : NULL; +} + + /** * Get the remote port number of an SDP Media line * diff --git a/src/sdp/msg.c b/src/sdp/msg.c index 0bcde9c..170ed30 100644 --- a/src/sdp/msg.c +++ b/src/sdp/msg.c @@ -181,7 +181,7 @@ static int media_decode(struct sdp_media **mp, struct sdp_session *sess, if (!offer) return EPROTO; - m = sdp_media_find(sess, &name, &proto); + m = sdp_media_find(sess, &name, &proto, true); if (!m) { err = sdp_media_radd(&m, sess, &name, &proto); if (err) @@ -196,7 +196,7 @@ static int media_decode(struct sdp_media **mp, struct sdp_session *sess, if (pl_strcmp(&name, m->name)) return offer ? ENOTSUP : EPROTO; - if (pl_strcmp(&proto, m->proto)) + if (!sdp_media_proto_cmp(m, &proto, offer)) return ENOTSUP; } diff --git a/src/sdp/sdp.h b/src/sdp/sdp.h index cd11cc5..eab7204 100644 --- a/src/sdp/sdp.h +++ b/src/sdp/sdp.h @@ -39,6 +39,7 @@ struct sdp_media { int32_t rbwv[SDP_BANDWIDTH_MAX]; char *name; char *proto; + char *protov[8]; sdp_media_enc_h *ench; void *arg; enum sdp_dir ldir; @@ -57,9 +58,12 @@ void sdp_session_rreset(struct sdp_session *sess); int sdp_media_radd(struct sdp_media **mp, struct sdp_session *sess, const struct pl *name, const struct pl *proto); void sdp_media_rreset(struct sdp_media *m); +bool sdp_media_proto_cmp(struct sdp_media *m, const struct pl *proto, + bool update); struct sdp_media *sdp_media_find(const struct sdp_session *sess, const struct pl *name, - const struct pl *proto); + const struct pl *proto, + bool update_proto); void sdp_media_align_formats(struct sdp_media *m, bool offer);