Hello Neels Hofmeyr, Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/4006

to look at the new patch set (#16).

sdp: refactoring sdp parser/generator

move SDP generator function write_response_sdp() from mgcp_protocol.c
to mgcp_sdp.c and use msgb_printf() instead of snprintf()

move prototypes for mgcp_parse_sdp_data() and mgcp_set_audio_info()
to mgcp_sdp.h

change parameter list of mgcp_parse_sdp_data() so that it takes the
rtp conn directly, rather than struct mgcp_rtp_end.

add doxygen comments to all public functions

Change-Id: I9f88c93872ff913bc211f560b26901267f577324
---
M include/osmocom/mgcp/Makefile.am
M include/osmocom/mgcp/mgcp_internal.h
A include/osmocom/mgcp/mgcp_sdp.h
M src/libosmo-mgcp/mgcp_protocol.c
M src/libosmo-mgcp/mgcp_sdp.c
5 files changed, 158 insertions(+), 100 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-mgw refs/changes/06/4006/16

diff --git a/include/osmocom/mgcp/Makefile.am b/include/osmocom/mgcp/Makefile.am
index 646b887..cd8f599 100644
--- a/include/osmocom/mgcp/Makefile.am
+++ b/include/osmocom/mgcp/Makefile.am
@@ -4,4 +4,5 @@
        mgcp_conn.h \
        mgcp_stat.h \
        mgcp_ep.h \
+       mgcp_sdp.h \
        $(NULL)
diff --git a/include/osmocom/mgcp/mgcp_internal.h 
b/include/osmocom/mgcp/mgcp_internal.h
index 751aba5..d4c8dc9 100644
--- a/include/osmocom/mgcp/mgcp_internal.h
+++ b/include/osmocom/mgcp/mgcp_internal.h
@@ -317,9 +317,6 @@
 #define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
 
 #define PTYPE_UNDEFINED (-1)
-int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, 
struct mgcp_parse_data *p);
-int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
-                       int payload_type, const char *audio_name);
 
 /*! get the ip-address where the mgw application is bound on.
  *  \param[in] endp mgcp endpoint, that holds a copy of the VTY parameters
diff --git a/include/osmocom/mgcp/mgcp_sdp.h b/include/osmocom/mgcp/mgcp_sdp.h
new file mode 100644
index 0000000..da23cba
--- /dev/null
+++ b/include/osmocom/mgcp/mgcp_sdp.h
@@ -0,0 +1,35 @@
+/*
+ * SDP generation and parsing
+ *
+ * (C) 2009-2015 by Holger Hans Peter Freyther <ze...@selfish.org>
+ * (C) 2009-2014 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+#include <osmocom/mgcp/mgcp_sdp.h>
+
+int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
+                       struct mgcp_conn_rtp *conn,
+                       struct mgcp_parse_data *p);
+
+int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
+                       int payload_type, const char *audio_name);
+
+int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
+                           const struct mgcp_conn_rtp *conn, struct msgb *sdp,
+                           const char *addr);
diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c
index c00cdc6..6c611f7 100644
--- a/src/libosmo-mgcp/mgcp_protocol.c
+++ b/src/libosmo-mgcp/mgcp_protocol.c
@@ -39,6 +39,7 @@
 #include <osmocom/mgcp/mgcp_stat.h>
 #include <osmocom/mgcp/mgcp_msg.h>
 #include <osmocom/mgcp/mgcp_ep.h>
+#include <osmocom/mgcp/mgcp_sdp.h>
 
 struct mgcp_request {
        char *name;
@@ -191,80 +192,6 @@
        return create_resp(endp, code, " FAIL", msg, trans, NULL, NULL);
 }
 
-static int write_response_sdp(struct mgcp_endpoint *endp,
-                             struct mgcp_conn_rtp *conn,
-                             char *sdp_record, size_t size, const char *addr)
-{
-       const char *fmtp_extra;
-       const char *audio_name;
-       int payload_type;
-       int len;
-       int nchars;
-
-       if (!conn)
-               return -1;
-
-       endp->cfg->get_net_downlink_format_cb(endp, &payload_type,
-                                             &audio_name, &fmtp_extra, conn);
-
-       len = snprintf(sdp_record, size,
-                      "v=0\r\n"
-                      "o=- %u 23 IN IP4 %s\r\n"
-                      "s=-\r\n"
-                      "c=IN IP4 %s\r\n"
-                      "t=0 0\r\n", conn->conn->id, addr, addr);
-
-       if (len < 0 || len >= size)
-               goto buffer_too_small;
-
-       if (payload_type >= 0) {
-               nchars = snprintf(sdp_record + len, size - len,
-                                 "m=audio %d RTP/AVP %d\r\n",
-                                 conn->end.local_port, payload_type);
-               if (nchars < 0 || nchars >= size - len)
-                       goto buffer_too_small;
-
-               len += nchars;
-
-               if (audio_name && endp->tcfg->audio_send_name) {
-                       nchars = snprintf(sdp_record + len, size - len,
-                                         "a=rtpmap:%d %s\r\n",
-                                         payload_type, audio_name);
-
-                       if (nchars < 0 || nchars >= size - len)
-                               goto buffer_too_small;
-
-                       len += nchars;
-               }
-
-               if (fmtp_extra) {
-                       nchars = snprintf(sdp_record + len, size - len,
-                                         "%s\r\n", fmtp_extra);
-
-                       if (nchars < 0 || nchars >= size - len)
-                               goto buffer_too_small;
-
-                       len += nchars;
-               }
-       }
-       if (conn->end.packet_duration_ms > 0 && endp->tcfg->audio_send_ptime) {
-               nchars = snprintf(sdp_record + len, size - len,
-                                 "a=ptime:%u\r\n",
-                                 conn->end.packet_duration_ms);
-               if (nchars < 0 || nchars >= size - len)
-                       goto buffer_too_small;
-
-               len += nchars;
-       }
-
-       return len;
-
-buffer_too_small:
-       LOGP(DLMGCP, LOGL_ERROR, "SDP buffer too small: %zu (needed %d)\n",
-            size, len);
-       return -1;
-}
-
 /* Format MGCP response string (with SDP attached) */
 static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
                                             struct mgcp_conn_rtp *conn,
@@ -272,10 +199,14 @@
                                             const char *trans_id)
 {
        const char *addr = endp->cfg->local_ip;
-       char sdp_record[4096];
-       int len;
-       int nchars;
+       struct msgb *sdp;
+       int rc;
+       struct msgb *result;
        char osmux_extension[strlen("\nX-Osmux: 255") + 1];
+
+       sdp = msgb_alloc_headroom(4096, 128, "sdp record");
+       if (!sdp)
+               return NULL;
 
        if (!addr)
                addr = mgcp_net_src_addr(endp);
@@ -287,21 +218,19 @@
                osmux_extension[0] = '\0';
        }
 
-       len = snprintf(sdp_record, sizeof(sdp_record),
-                      "I: %u%s\n\n", conn->conn->id, osmux_extension);
-       if (len < 0)
-               return NULL;
+       rc = msgb_printf(sdp, "I: %u%s\n\n", conn->conn->id, osmux_extension);
+       if (rc < 0)
+               goto error;
 
-       nchars = write_response_sdp(endp, conn, sdp_record + len,
-                                   sizeof(sdp_record) - len - 1, addr);
-       if (nchars < 0)
-               return NULL;
-
-       len += nchars;
-
-       sdp_record[sizeof(sdp_record) - 1] = '\0';
-
-       return create_resp(endp, 200, " OK", msg, trans_id, NULL, sdp_record);
+       rc = mgcp_write_response_sdp(endp, conn, sdp, addr);
+       if (rc < 0)
+               goto error;
+       result = create_resp(endp, 200, " OK", msg, trans_id, NULL, (char*) 
sdp->data);
+       msgb_free(sdp);
+       return result;
+error:
+       msgb_free(sdp);
+       return NULL;
 }
 
 /* Send out dummy packet to keep the connection open, if the connection is an
@@ -689,7 +618,7 @@
 
        /* set up RTP media parameters */
        if (have_sdp)
-               mgcp_parse_sdp_data(endp, &conn->end, p);
+               mgcp_parse_sdp_data(endp, conn, p);
        else if (endp->local_options.codec)
                mgcp_set_audio_info(p->cfg, &conn->end.codec,
                                    PTYPE_UNDEFINED, endp->local_options.codec);
@@ -836,7 +765,7 @@
                        conn->conn->mode = conn->conn->mode_orig;
 
        if (have_sdp)
-               mgcp_parse_sdp_data(endp, &conn->end, p);
+               mgcp_parse_sdp_data(endp, conn, p);
 
        set_local_cx_options(endp->tcfg->endpoints, &endp->local_options,
                             local_options);
diff --git a/src/libosmo-mgcp/mgcp_sdp.c b/src/libosmo-mgcp/mgcp_sdp.c
index 7568351..e6bf9c2 100644
--- a/src/libosmo-mgcp/mgcp_sdp.c
+++ b/src/libosmo-mgcp/mgcp_sdp.c
@@ -20,6 +20,7 @@
  *
  */
 
+#include <osmocom/core/msgb.h>
 #include <osmocom/mgcp/mgcp.h>
 #include <osmocom/mgcp/mgcp_internal.h>
 #include <osmocom/mgcp/mgcp_msg.h>
@@ -38,6 +39,12 @@
        int channels;
 };
 
+/*! Set codec configuration depending on payload type and codec name.
+ *  \param[in] ctx talloc context.
+ *  \param[out] codec configuration (caller provided memory).
+ *  \param[in] payload_type codec type id (e.g. 3 for GSM, -1 when undefined).
+ *  \param[in] audio_name audio codec name (e.g. "GSM/8000/1").
+ *  \returns 0 on success, -1 on failure. */
 int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
                        int payload_type, const char *audio_name)
 {
@@ -107,7 +114,7 @@
        return 0;
 }
 
-void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
+static void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
 {
        int i;
 
@@ -137,7 +144,8 @@
        }
 }
 
-void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used, int 
payload, char *audio_name)
+static void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used,
+                         int payload, const char *audio_name)
 {
        int i;
 
@@ -163,7 +171,9 @@
        LOGP(DLMGCP, LOGL_ERROR, "Unconfigured PT(%d) with %s\n", payload, 
audio_name);
 }
 
-int is_codec_compatible(struct mgcp_endpoint *endp, struct sdp_rtp_map *codec)
+/* Check if the codec matches what is set up in the trunk config */
+static int is_codec_compatible(const struct mgcp_endpoint *endp,
+                              const struct sdp_rtp_map *codec)
 {
        char *bts_codec;
        char audio_codec[64];
@@ -182,7 +192,17 @@
        return strcasecmp(audio_codec, codec->codec_name) == 0;
 }
 
-int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, 
struct mgcp_parse_data *p)
+/*! Analyze SDP input string.
+ *  \param[in] endp trunk endpoint.
+ *  \param[out] conn associated rtp connection.
+ *  \param[out] caller provided memory to store the parsing results.
+ *  \returns 0 on success, -1 on failure.
+ *
+ *  Note: In conn (conn->end) the function returns the packet duration,
+ *  the rtp port and the rtcp port */
+int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
+                       struct mgcp_conn_rtp *conn,
+                       struct mgcp_parse_data *p)
 {
        struct sdp_rtp_map codecs[10];
        int codecs_used = 0;
@@ -191,7 +211,13 @@
        int i;
        int codecs_assigned = 0;
        void *tmp_ctx = talloc_new(NULL);
+       struct mgcp_rtp_end *rtp;
 
+       OSMO_ASSERT(endp);
+       OSMO_ASSERT(conn);
+       OSMO_ASSERT(p);
+
+       rtp = &conn->end;
        memset(&codecs, 0, sizeof(codecs));
 
        for_each_line(line, p->save) {
@@ -304,3 +330,73 @@
        return codecs_assigned > 0;
 }
 
+/*! Generate SDP response string.
+ *  \param[in] endp trunk endpoint.
+ *  \param[in] conn associated rtp connection.
+ *  \param[out] sdp msg buffer to append resulting SDP string data.
+ *  \param[in] addr IPV4 address string (e.g. 192.168.100.1).
+ *  \returns 0 on success, -1 on failure. */
+int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
+                           const struct mgcp_conn_rtp *conn, struct msgb *sdp,
+                           const char *addr)
+{
+       const char *fmtp_extra;
+       const char *audio_name;
+       int payload_type;
+       int rc;
+
+       OSMO_ASSERT(endp);
+       OSMO_ASSERT(conn);
+       OSMO_ASSERT(sdp);
+       OSMO_ASSERT(addr);
+
+       /* FIXME: constify endp and conn args in get_net_donwlink_format_cb() */
+       endp->cfg->get_net_downlink_format_cb((struct mgcp_endpoint *)endp,
+                                             &payload_type, &audio_name,
+                                             &fmtp_extra,
+                                             (struct mgcp_conn_rtp *)conn);
+
+       rc = msgb_printf(sdp,
+                        "v=0\r\n"
+                        "o=- %u 23 IN IP4 %s\r\n"
+                        "s=-\r\n"
+                        "c=IN IP4 %s\r\n"
+                        "t=0 0\r\n", conn->conn->id, addr, addr);
+
+       if (rc < 0)
+               goto buffer_too_small;
+
+       if (payload_type >= 0) {
+               rc = msgb_printf(sdp, "m=audio %d RTP/AVP %d\r\n",
+                                conn->end.local_port, payload_type);
+               if (rc < 0)
+                       goto buffer_too_small;
+
+               if (audio_name && endp->tcfg->audio_send_name) {
+                       rc = msgb_printf(sdp, "a=rtpmap:%d %s\r\n",
+                                        payload_type, audio_name);
+
+                       if (rc < 0)
+                               goto buffer_too_small;
+               }
+
+               if (fmtp_extra) {
+                       rc = msgb_printf(sdp, "%s\r\n", fmtp_extra);
+
+                       if (rc < 0)
+                               goto buffer_too_small;
+               }
+       }
+       if (conn->end.packet_duration_ms > 0 && endp->tcfg->audio_send_ptime) {
+               rc = msgb_printf(sdp, "a=ptime:%u\r\n",
+                                conn->end.packet_duration_ms);
+               if (rc < 0)
+                       goto buffer_too_small;
+       }
+
+       return 0;
+
+buffer_too_small:
+       LOGP(DLMGCP, LOGL_ERROR, "SDP messagebuffer too small\n");
+       return -1;
+}

-- 
To view, visit https://gerrit.osmocom.org/4006
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I9f88c93872ff913bc211f560b26901267f577324
Gerrit-PatchSet: 16
Gerrit-Project: osmo-mgw
Gerrit-Branch: master
Gerrit-Owner: Neels Hofmeyr <nhofm...@sysmocom.de>
Gerrit-Reviewer: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Neels Hofmeyr <nhofm...@sysmocom.de>
Gerrit-Reviewer: dexter <pma...@sysmocom.de>

Reply via email to