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.orgHello 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 (#11). 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/11 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 +[0;mDone 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: 11 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>