[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
Tue Oct 10 14:58:04 UTC 2017


Hello Jenkins Builder,

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

    https://gerrit.osmocom.org/4146

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

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.

This commit depends on libosmocore Change:
Change-Id 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.ok
4 files changed, 223 insertions(+), 0 deletions(-)


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

diff --git a/include/osmocom/mgcp_client/mgcp_client.h b/include/osmocom/mgcp_client/mgcp_client.h
index efc1f76..1e92da7 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_* constands above */
+	uint32_t presence;
+	char endpoint[MGCP_ENDPOINT_MAXLEN];
+	unsigned int call_id;
+	uint32_t conn_id;
+        uint16_t audio_port;
+        char audio_ip[INET_ADDRSTRLEN];
+	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);
@@ -63,17 +94,22 @@
 
 enum mgcp_connection_mode;
 
+OSMO_DEPRECATED("Use mgcp_msg_gen() instead")
 struct msgb *mgcp_msg_crcx(struct mgcp_client *mgcp,
 			   uint16_t rtp_endpoint, unsigned int call_id,
 			   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);
 
+OSMO_DEPRECATED("Use mgcp_msg_gen() instead")
 struct msgb *mgcp_msg_dlcx(struct mgcp_client *mgcp, uint16_t rtp_endpoint,
 			   unsigned int call_id);
 
+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..2bb669e 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,104 @@
 				 "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;
+
+	/* 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");
+		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");
+		return NULL;
+	}
+
+	/* Add endpoint name */
+	if (mgcp_msg->presence & MGCP_MSG_PRESENCE_ENDPOINT)
+		rc += msgb_printf(msg, " %s", mgcp_msg->endpoint);
+
+	/* Add protocol version */
+	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");
+		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..750aa0e 100644
--- a/tests/mgcp_client/mgcp_client_test.c
+++ b/tests/mgcp_client/mgcp_client_test.c
@@ -149,6 +149,65 @@
 		"a=ptime:20\r\n");
 }
 
+void test_mgcp_msg(void)
+{
+	struct msgb *msg;
+
+	struct mgcp_msg mgcp_msg;
+
+	if (mgcp)
+		talloc_free(mgcp);
+	mgcp = mgcp_client_init(ctx, &conf);
+
+	/* Pre-fill the message struct with some arbitary values */
+	strcpy(mgcp_msg.audio_ip, "192.168.100.23");
+	strcpy(mgcp_msg.endpoint, "23 at mgw");
+	mgcp_msg.call_id = 47;
+	mgcp_msg.conn_id = 11;
+	mgcp_msg.conn_mode = MGCP_CONN_RECV_SEND;
+
+	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", 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", 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", 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", msg->data);
+
+	msgb_free(msg);
+}
+
 static const struct log_info_cat log_categories[] = {
 };
 
@@ -167,6 +226,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.ok b/tests/mgcp_client/mgcp_client_test.ok
index d35f2d6..7c4819d 100644
--- a/tests/mgcp_client/mgcp_client_test.ok
+++ b/tests/mgcp_client/mgcp_client_test.ok
@@ -28,4 +28,32 @@
   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
+
 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: 3
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