[PATCH] osmo-mgw[master]: client: add unified function to generate MGCP messages

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

dexter gerrit-no-reply at lists.osmocom.org
Thu Oct 12 13:41:49 UTC 2017


Hello Neels Hofmeyr, Harald Welte, Jenkins Builder,

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

    https://gerrit.osmocom.org/4146

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

client: add unified function to generate MGCP messages

currently the only way to generate MGCP messages is to use
mgcp_msg_crcx(), mgcp_msg_mdcx() and mgcp_msg_dlcx(). All
three function take a fixed set of parameters via their
parameter list. There is no way to add or leave away optional
parameters.

add function mgcp_msg_gen(), this function takes a unified
message struct. The struct features a presence bitmask which
allows to enable and disable parameters as needed. It is also
possible to add new parameters in the future without breaking
the API.

Depends: libosmocore I15e1af68616309555d0ed9ac5da027c9833d42e3

Change-Id: I29c5e2fb972896faeb771ba040f015592487fcbe
---
M include/osmocom/mgcp_client/mgcp_client.h
M src/libosmo-mgcp-client/mgcp_client.c
M tests/mgcp_client/mgcp_client_test.c
M tests/mgcp_client/mgcp_client_test.err
M tests/mgcp_client/mgcp_client_test.ok
5 files changed, 250 insertions(+), 4 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-mgw refs/changes/46/4146/6

diff --git a/include/osmocom/mgcp_client/mgcp_client.h b/include/osmocom/mgcp_client/mgcp_client.h
index efc1f76..21717e3 100644
--- a/include/osmocom/mgcp_client/mgcp_client.h
+++ b/include/osmocom/mgcp_client/mgcp_client.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <stdint.h>
+#include <arpa/inet.h>
 
 #include <osmocom/mgcp_client/mgcp_common.h>
 
@@ -37,6 +38,36 @@
 	uint16_t audio_port;
 };
 
+enum mgcp_verb {
+	MGCP_VERB_CRCX,
+	MGCP_VERB_MDCX,
+	MGCP_VERB_DLCX,
+	MGCP_VERB_AUEP,
+	MGCP_VERB_RSIP,
+};
+
+#define MGCP_MSG_PRESENCE_ENDPOINT	0x0001
+#define MGCP_MSG_PRESENCE_CALL_ID	0x0002
+#define MGCP_MSG_PRESENCE_CONN_ID	0x0004
+#define MGCP_MSG_PRESENCE_AUDIO_IP	0x0008
+#define MGCP_MSG_PRESENCE_AUDIO_PORT	0x0010
+#define MGCP_MSG_PRESENCE_CONN_MODE	0x0020
+
+/* See also RFC3435 section 3.2.1.3 */
+#define MGCP_ENDPOINT_MAXLEN (255*2+1+1)
+
+struct mgcp_msg {
+	enum mgcp_verb verb;
+	/* See MGCP_MSG_PRESENCE_* constants */
+	uint32_t presence;
+	char endpoint[MGCP_ENDPOINT_MAXLEN];
+	unsigned int call_id;
+	uint32_t conn_id;
+        uint16_t audio_port;
+        char *audio_ip;
+	enum mgcp_connection_mode conn_mode;
+};
+
 void mgcp_client_conf_init(struct mgcp_client_conf *conf);
 void mgcp_client_vty_init(void *talloc_ctx, int node, struct mgcp_client_conf *conf);
 int mgcp_client_config_write(struct vty *vty, const char *indent);
@@ -65,14 +96,19 @@
 
 struct msgb *mgcp_msg_crcx(struct mgcp_client *mgcp,
 			   uint16_t rtp_endpoint, unsigned int call_id,
-			   enum mgcp_connection_mode mode);
+			   enum mgcp_connection_mode mode)
+OSMO_DEPRECATED("Use mgcp_msg_gen() instead");
 
 struct msgb *mgcp_msg_mdcx(struct mgcp_client *mgcp,
 			   uint16_t rtp_endpoint, const char *rtp_conn_addr,
-			   uint16_t rtp_port, enum mgcp_connection_mode mode);
+			   uint16_t rtp_port, enum mgcp_connection_mode mode)
+OSMO_DEPRECATED("Use mgcp_msg_gen() instead");
 
 struct msgb *mgcp_msg_dlcx(struct mgcp_client *mgcp, uint16_t rtp_endpoint,
-			   unsigned int call_id);
+			   unsigned int call_id)
+OSMO_DEPRECATED("Use mgcp_msg_gen() instead");
+
+struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg);
 
 extern const struct value_string mgcp_client_connection_mode_strs[];
 static inline const char *mgcp_client_cmode_name(enum mgcp_connection_mode mode)
diff --git a/src/libosmo-mgcp-client/mgcp_client.c b/src/libosmo-mgcp-client/mgcp_client.c
index 1cd37be..c7cc989 100644
--- a/src/libosmo-mgcp-client/mgcp_client.c
+++ b/src/libosmo-mgcp-client/mgcp_client.c
@@ -23,6 +23,7 @@
 #include <osmocom/core/write_queue.h>
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/logging.h>
+#include <osmocom/core/byteswap.h>
 
 #include <osmocom/mgcp_client/mgcp_client.h>
 #include <osmocom/mgcp_client/mgcp_client_internal.h>
@@ -614,6 +615,109 @@
 				 "C: %x\r\n", trans_id, rtp_endpoint, call_id);
 }
 
+#define MGCP_CRCX_MANDATORY (MGCP_MSG_PRESENCE_ENDPOINT | \
+			     MGCP_MSG_PRESENCE_CALL_ID | \
+			     MGCP_MSG_PRESENCE_CONN_ID | \
+			     MGCP_MSG_PRESENCE_CONN_MODE)
+#define MGCP_MDCX_MANDATORY (MGCP_MSG_PRESENCE_ENDPOINT | \
+			     MGCP_MSG_PRESENCE_CONN_ID)
+#define MGCP_DLCX_MANDATORY (MGCP_MSG_PRESENCE_ENDPOINT)
+#define MGCP_AUEP_MANDATORY (MGCP_MSG_PRESENCE_ENDPOINT)
+#define MGCP_RSIP_MANDATORY 0	/* none */
+
+struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg)
+{
+	mgcp_trans_id_t trans_id = mgcp_client_next_trans_id(mgcp);
+	uint32_t mandatory_mask;
+	struct msgb *msg = msgb_alloc_headroom(4096, 128, "MGCP tx");
+	int rc = 0;
+
+	msg->l2h = msg->data;
+	msg->cb[MSGB_CB_MGCP_TRANS_ID] = trans_id;
+
+	/* Add command verb */
+	switch (mgcp_msg->verb) {
+	case MGCP_VERB_CRCX:
+		mandatory_mask = MGCP_CRCX_MANDATORY;
+		rc += msgb_printf(msg, "CRCX %u", trans_id);
+		break;
+	case MGCP_VERB_MDCX:
+		mandatory_mask = MGCP_MDCX_MANDATORY;
+		rc += msgb_printf(msg, "MDCX %u", trans_id);
+		break;
+	case MGCP_VERB_DLCX:
+		mandatory_mask = MGCP_DLCX_MANDATORY;
+		rc += msgb_printf(msg, "DLCX %u", trans_id);
+		break;
+	case MGCP_VERB_AUEP:
+		mandatory_mask = MGCP_AUEP_MANDATORY;
+		rc += msgb_printf(msg, "AUEP %u", trans_id);
+		break;
+	case MGCP_VERB_RSIP:
+		mandatory_mask = MGCP_RSIP_MANDATORY;
+		rc += msgb_printf(msg, "RSIP %u", trans_id);
+		break;
+	default:
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Invalid command verb, can not generate MGCP message\n");
+		msgb_free(msg);
+		return NULL;
+	}
+
+	/* Check if mandatory fields are missing */
+	if (!((mgcp_msg->presence & mandatory_mask) == mandatory_mask)) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "One or more missing mandatory fields, can not generate MGCP message\n");
+		msgb_free(msg);
+		return NULL;
+	}
+
+	/* Add endpoint name */
+	if (mgcp_msg->presence & MGCP_MSG_PRESENCE_ENDPOINT)
+		rc += msgb_printf(msg, " %s", mgcp_msg->endpoint);
+
+	/* Add protocol version */
+	rc += msgb_printf(msg, " MGCP 1.0\r\n");
+
+	/* Add call id */
+	if (mgcp_msg->presence & MGCP_MSG_PRESENCE_CALL_ID)
+		rc += msgb_printf(msg, "C: %x\r\n", mgcp_msg->call_id);
+
+	/* Add connection id */
+	if (mgcp_msg->presence & MGCP_MSG_PRESENCE_CONN_ID)
+		rc += msgb_printf(msg, "I: %u\r\n", mgcp_msg->conn_id);
+
+	/* Add local connection options */
+	if (mgcp_msg->presence & MGCP_MSG_PRESENCE_CONN_ID
+	    && mgcp_msg->verb == MGCP_VERB_CRCX)
+		rc += msgb_printf(msg, "L: p:20, a:AMR, nt:IN\r\n");
+
+	/* Add mode */
+	if (mgcp_msg->presence & MGCP_MSG_PRESENCE_CONN_MODE)
+		rc +=
+		    msgb_printf(msg, "M: %s\r\n",
+				mgcp_client_cmode_name(mgcp_msg->conn_mode));
+
+	/* Add RTP address and port (SDP) */
+	if (mgcp_msg->presence & MGCP_MSG_PRESENCE_AUDIO_IP
+	    && mgcp_msg->presence & MGCP_MSG_PRESENCE_AUDIO_PORT) {
+		rc += msgb_printf(msg, "\r\n");
+		rc += msgb_printf(msg, "c=IN IP4 %s\r\n", mgcp_msg->audio_ip);
+		rc +=
+		    msgb_printf(msg, "m=audio %u RTP/AVP 255\r\n",
+				mgcp_msg->audio_port);
+	}
+
+	if (rc != 0) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "message buffer to small, can not generate MGCP message\n");
+		msgb_free(msg);
+		msg = NULL;
+	}
+
+	return msg;
+}
+
 struct mgcp_client_conf *mgcp_client_conf_actual(struct mgcp_client *mgcp)
 {
 	return &mgcp->actual;
diff --git a/tests/mgcp_client/mgcp_client_test.c b/tests/mgcp_client/mgcp_client_test.c
index f2f0e0f..1420959 100644
--- a/tests/mgcp_client/mgcp_client_test.c
+++ b/tests/mgcp_client/mgcp_client_test.c
@@ -149,6 +149,80 @@
 		"a=ptime:20\r\n");
 }
 
+void test_mgcp_msg(void)
+{
+	struct msgb *msg;
+	char audio_ip_overflow[5000];
+
+	/* A message struct prefilled with some arbitary values */
+	struct mgcp_msg mgcp_msg = {
+		.audio_ip = "192.168.100.23",
+		.endpoint = "23 at mgw",
+		.audio_port = 1234,
+		.call_id = 47,
+		.conn_id = 11,
+		.conn_mode = MGCP_CONN_RECV_SEND
+	};
+
+	if (mgcp)
+		talloc_free(mgcp);
+	mgcp = mgcp_client_init(ctx, &conf);
+
+	printf("\n");
+
+	printf("Generated CRCX message:\n");
+	mgcp_msg.verb = MGCP_VERB_CRCX;
+	mgcp_msg.presence =
+	    (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
+	     MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE);
+	msg = mgcp_msg_gen(mgcp, &mgcp_msg);
+	printf("%s\n", (char *)msg->data);
+
+	printf("Generated MDCX message:\n");
+	mgcp_msg.verb = MGCP_VERB_MDCX;
+	mgcp_msg.presence =
+	    (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
+	     MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
+	     MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
+	msg = mgcp_msg_gen(mgcp, &mgcp_msg);
+	printf("%s\n", (char *)msg->data);
+
+	printf("Generated DLCX message:\n");
+	mgcp_msg.verb = MGCP_VERB_DLCX;
+	mgcp_msg.presence =
+	    (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
+	     MGCP_MSG_PRESENCE_CONN_ID);
+	msg = mgcp_msg_gen(mgcp, &mgcp_msg);
+	printf("%s\n", (char *)msg->data);
+
+	printf("Generated AUEP message:\n");
+	mgcp_msg.verb = MGCP_VERB_AUEP;
+	mgcp_msg.presence = (MGCP_MSG_PRESENCE_ENDPOINT);
+	msg = mgcp_msg_gen(mgcp, &mgcp_msg);
+	printf("%s\n", msg->data);
+
+	printf("Generated RSIP message:\n");
+	mgcp_msg.verb = MGCP_VERB_RSIP;
+	mgcp_msg.presence = (MGCP_MSG_PRESENCE_ENDPOINT);
+	msg = mgcp_msg_gen(mgcp, &mgcp_msg);
+	printf("%s\n", (char *)msg->data);
+
+	printf("Overfolow test:\n");
+	mgcp_msg.verb = MGCP_VERB_MDCX;
+	mgcp_msg.presence =
+	    (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
+	     MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
+	     MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
+	memset(audio_ip_overflow, 'X', sizeof(audio_ip_overflow));
+	audio_ip_overflow[sizeof(audio_ip_overflow) - 1] = '\0';
+	mgcp_msg.audio_ip = audio_ip_overflow;
+	msg = mgcp_msg_gen(mgcp, &mgcp_msg);
+	OSMO_ASSERT(msg == NULL);
+
+	printf("\n");
+	msgb_free(msg);
+}
+
 static const struct log_info_cat log_categories[] = {
 };
 
@@ -167,6 +241,7 @@
 	mgcp_client_conf_init(&conf);
 
 	test_crcx();
+	test_mgcp_msg();
 
 	printf("Done\n");
 	fprintf(stderr, "Done\n");
diff --git a/tests/mgcp_client/mgcp_client_test.err b/tests/mgcp_client/mgcp_client_test.err
index a965a70..5e23799 100644
--- a/tests/mgcp_client/mgcp_client_test.err
+++ b/tests/mgcp_client/mgcp_client_test.err
@@ -1 +1,2 @@
-Done
+<0010> mgcp_client.c:746 message buffer to small, can not generate MGCP message
+Done
diff --git a/tests/mgcp_client/mgcp_client_test.ok b/tests/mgcp_client/mgcp_client_test.ok
index d35f2d6..e3b6113 100644
--- a/tests/mgcp_client/mgcp_client_test.ok
+++ b/tests/mgcp_client/mgcp_client_test.ok
@@ -28,4 +28,34 @@
   head.trans_id = 1
   head.comment = OK
   audio_port = 16002
+
+Generated CRCX message:
+CRCX 1 23 at mgw MGCP 1.0
+C: 2f
+I: 11
+L: p:20, a:AMR, nt:IN
+M: sendrecv
+
+Generated MDCX message:
+MDCX 2 23 at mgw MGCP 1.0
+C: 2f
+I: 11
+M: sendrecv
+
+c=IN IP4 192.168.100.23
+m=audio 1234 RTP/AVP 255
+
+Generated DLCX message:
+DLCX 3 23 at mgw MGCP 1.0
+C: 2f
+I: 11
+
+Generated AUEP message:
+AUEP 4 23 at mgw MGCP 1.0
+
+Generated RSIP message:
+RSIP 5 23 at mgw MGCP 1.0
+
+Overfolow test:
+
 Done

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

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I29c5e2fb972896faeb771ba040f015592487fcbe
Gerrit-PatchSet: 6
Gerrit-Project: osmo-mgw
Gerrit-Branch: master
Gerrit-Owner: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>



More information about the gerrit-log mailing list