mgcp_client: simpler error handling
add_sdp(), add_lco():
- do not msgb_free() within these functions. Just return error, and move
the msgb_free() to the caller.
- when failing to write to the msgb, directly return error.
Change-Id: I904d56f56053952c2ebbbe5dca744fafa32b333e
diff --git a/src/libosmo-mgcp-client/mgcp_client.c b/src/libosmo-mgcp-client/mgcp_client.c
index 670910b..3df9ccf 100644
--- a/src/libosmo-mgcp-client/mgcp_client.c
+++ b/src/libosmo-mgcp-client/mgcp_client.c
@@ -1135,87 +1135,87 @@
static int add_lco(struct msgb *msg, struct mgcp_msg *mgcp_msg)
{
unsigned int i;
- int rc = 0;
const char *codec;
unsigned int pt;
- rc |= msgb_printf(msg, "L:");
+#define MSGB_PRINTF_OR_RET(FMT, ARGS...) do { \
+ if (msgb_printf(msg, FMT, ##ARGS) != 0) { \
+ LOGP(DLMGCP, LOGL_ERROR, "Message buffer too small, can not generate MGCP/SDP message\n"); \
+ return -ENOBUFS; \
+ } \
+ } while (0)
+
+ MSGB_PRINTF_OR_RET("L:");
if (mgcp_msg->ptime)
- rc |= msgb_printf(msg, " p:%u,", mgcp_msg->ptime);
+ MSGB_PRINTF_OR_RET(" p:%u,", mgcp_msg->ptime);
if (mgcp_msg->codecs_len) {
- rc |= msgb_printf(msg, " a:");
+ MSGB_PRINTF_OR_RET(" a:");
for (i = 0; i < mgcp_msg->codecs_len; i++) {
pt = mgcp_msg->codecs[i];
codec = get_value_string_or_null(osmo_mgcpc_codec_names, pt);
/* Note: Use codec descriptors from enum mgcp_codecs
* in mgcp_client only! */
- if (!codec) {
- msgb_free(msg);
+ if (!codec)
return -EINVAL;
- }
- rc |= msgb_printf(msg, "%s", extract_codec_name(codec));
+ MSGB_PRINTF_OR_RET("%s", extract_codec_name(codec));
if (i < mgcp_msg->codecs_len - 1)
- rc |= msgb_printf(msg, ";");
+ MSGB_PRINTF_OR_RET(";");
}
- rc |= msgb_printf(msg, ",");
+ MSGB_PRINTF_OR_RET(",");
}
- rc |= msgb_printf(msg, " nt:IN\r\n");
-
- if (rc != 0) {
- LOGP(DLMGCP, LOGL_ERROR,
- "message buffer to small, can not generate MGCP message (LCO)\n");
- msgb_free(msg);
- return -ENOBUFS;
- }
+ MSGB_PRINTF_OR_RET(" nt:IN\r\n");
return 0;
+
+#undef MSGB_PRINTF_OR_RET
}
/* Helper function for mgcp_msg_gen(): Add SDP information to MGCP message */
static int add_sdp(struct msgb *msg, struct mgcp_msg *mgcp_msg, struct mgcp_client *mgcp)
{
unsigned int i;
- int rc = 0;
char local_ip[INET6_ADDRSTRLEN];
int local_ip_family, audio_ip_family;
const char *codec;
unsigned int pt;
+#define MSGB_PRINTF_OR_RET(FMT, ARGS...) do { \
+ if (msgb_printf(msg, FMT, ##ARGS) != 0) { \
+ LOGPMGW(mgcp, LOGL_ERROR, "Message buffer too small, can not generate MGCP message (SDP)\n"); \
+ return -ENOBUFS; \
+ } \
+ } while (0)
+
/* Add separator to mark the beginning of the SDP block */
- rc |= msgb_printf(msg, "\r\n");
+ MSGB_PRINTF_OR_RET("\r\n");
/* Add SDP protocol version */
- rc |= msgb_printf(msg, "v=0\r\n");
+ MSGB_PRINTF_OR_RET("v=0\r\n");
/* Determine local IP-Address */
if (osmo_sock_local_ip(local_ip, mgcp->actual.remote_addr) < 0) {
LOGPMGW(mgcp, LOGL_ERROR,
"Could not determine local IP-Address!\n");
- msgb_free(msg);
return -EINVAL;
}
local_ip_family = osmo_ip_str_type(local_ip);
- if (local_ip_family == AF_UNSPEC) {
- msgb_free(msg);
+ if (local_ip_family == AF_UNSPEC)
return -EINVAL;
- }
audio_ip_family = osmo_ip_str_type(mgcp_msg->audio_ip);
- if (audio_ip_family == AF_UNSPEC) {
- msgb_free(msg);
+ if (audio_ip_family == AF_UNSPEC)
return -EINVAL;
- }
/* Add owner/creator (SDP) */
- rc |= msgb_printf(msg, "o=- %x 23 IN IP%c %s\r\n", mgcp_msg->call_id,
+ MSGB_PRINTF_OR_RET("o=- %x 23 IN IP%c %s\r\n", mgcp_msg->call_id,
local_ip_family == AF_INET6 ? '6' : '4',
local_ip);
/* Add session name (none) */
- rc |= msgb_printf(msg, "s=-\r\n");
+ MSGB_PRINTF_OR_RET("s=-\r\n");
/* Add RTP address and port */
if (mgcp_msg->audio_port == 0) {
@@ -1230,20 +1230,20 @@
msgb_free(msg);
return -EINVAL;
}
- rc |= msgb_printf(msg, "c=IN IP%c %s\r\n",
+ MSGB_PRINTF_OR_RET("c=IN IP%c %s\r\n",
audio_ip_family == AF_INET6 ? '6' : '4',
mgcp_msg->audio_ip);
/* Add time description, active time (SDP) */
- rc |= msgb_printf(msg, "t=0 0\r\n");
+ MSGB_PRINTF_OR_RET("t=0 0\r\n");
- rc |= msgb_printf(msg, "m=audio %u RTP/AVP", mgcp_msg->audio_port);
+ MSGB_PRINTF_OR_RET("m=audio %u RTP/AVP", mgcp_msg->audio_port);
for (i = 0; i < mgcp_msg->codecs_len; i++) {
pt = map_codec_to_pt(mgcp_msg->ptmap, mgcp_msg->ptmap_len, mgcp_msg->codecs[i]);
- rc |= msgb_printf(msg, " %u", pt);
+ MSGB_PRINTF_OR_RET(" %u", pt);
}
- rc |= msgb_printf(msg, "\r\n");
+ MSGB_PRINTF_OR_RET("\r\n");
/* Add optional codec parameters (fmtp) */
if (mgcp_msg->param_present) {
@@ -1253,9 +1253,9 @@
continue;
pt = map_codec_to_pt(mgcp_msg->ptmap, mgcp_msg->ptmap_len, mgcp_msg->codecs[i]);
if (mgcp_msg->param.amr_octet_aligned_present && mgcp_msg->param.amr_octet_aligned)
- rc |= msgb_printf(msg, "a=fmtp:%u octet-align=1\r\n", pt);
+ MSGB_PRINTF_OR_RET("a=fmtp:%u octet-align=1\r\n", pt);
else if (mgcp_msg->param.amr_octet_aligned_present && !mgcp_msg->param.amr_octet_aligned)
- rc |= msgb_printf(msg, "a=fmtp:%u octet-align=0\r\n", pt);
+ MSGB_PRINTF_OR_RET("a=fmtp:%u octet-align=0\r\n", pt);
}
}
@@ -1270,25 +1270,18 @@
/* Note: Use codec descriptors from enum mgcp_codecs
* in mgcp_client only! */
- if (!codec) {
- msgb_free(msg);
+ if (!codec)
return -EINVAL;
- }
- rc |= msgb_printf(msg, "a=rtpmap:%u %s\r\n", pt, codec);
+ MSGB_PRINTF_OR_RET("a=rtpmap:%u %s\r\n", pt, codec);
}
}
if (mgcp_msg->ptime)
- rc |= msgb_printf(msg, "a=ptime:%u\r\n", mgcp_msg->ptime);
-
- if (rc != 0) {
- LOGPMGW(mgcp, LOGL_ERROR, "Message buffer to small, can not generate MGCP message (SDP)\n");
- msgb_free(msg);
- return -ENOBUFS;
- }
+ MSGB_PRINTF_OR_RET("a=ptime:%u\r\n", mgcp_msg->ptime);
return 0;
+#undef MSGB_PRINTF_OR_RET
}
/*! Generate an MGCP message
@@ -1300,10 +1293,16 @@
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;
bool use_sdp = false;
char buf[32];
+#define MSGB_PRINTF_OR_RET(FMT, ARGS...) do { \
+ if (msgb_printf(msg, FMT, ##ARGS) != 0) { \
+ LOGPMGW(mgcp, LOGL_ERROR, "Message buffer too small, can not generate MGCP/SDP message\n"); \
+ goto exit_error; \
+ } \
+ } while (0)
+
msg->l2h = msg->data;
msg->cb[MSGB_CB_MGCP_TRANS_ID] = trans_id;
@@ -1311,72 +1310,67 @@
switch (mgcp_msg->verb) {
case MGCP_VERB_CRCX:
mandatory_mask = MGCP_CRCX_MANDATORY;
- rc |= msgb_printf(msg, "CRCX %u", trans_id);
+ MSGB_PRINTF_OR_RET("CRCX %u", trans_id);
break;
case MGCP_VERB_MDCX:
mandatory_mask = MGCP_MDCX_MANDATORY;
- rc |= msgb_printf(msg, "MDCX %u", trans_id);
+ MSGB_PRINTF_OR_RET("MDCX %u", trans_id);
break;
case MGCP_VERB_DLCX:
mandatory_mask = MGCP_DLCX_MANDATORY;
- rc |= msgb_printf(msg, "DLCX %u", trans_id);
+ MSGB_PRINTF_OR_RET("DLCX %u", trans_id);
break;
case MGCP_VERB_AUEP:
mandatory_mask = MGCP_AUEP_MANDATORY;
- rc |= msgb_printf(msg, "AUEP %u", trans_id);
+ MSGB_PRINTF_OR_RET("AUEP %u", trans_id);
break;
case MGCP_VERB_RSIP:
mandatory_mask = MGCP_RSIP_MANDATORY;
- rc |= msgb_printf(msg, "RSIP %u", trans_id);
+ MSGB_PRINTF_OR_RET("RSIP %u", trans_id);
break;
default:
LOGPMGW(mgcp, LOGL_ERROR, "Invalid command verb, can not generate MGCP message\n");
- msgb_free(msg);
- return NULL;
+ goto exit_error;
}
/* Check if mandatory fields are missing */
if (!((mgcp_msg->presence & mandatory_mask) == mandatory_mask)) {
LOGPMGW(mgcp, LOGL_ERROR,
"One or more missing mandatory fields, can not generate MGCP message\n");
- msgb_free(msg);
- return NULL;
+ goto exit_error;
}
/* Add endpoint name */
if (mgcp_msg->presence & MGCP_MSG_PRESENCE_ENDPOINT) {
if (strlen(mgcp_msg->endpoint) <= 0) {
LOGPMGW(mgcp, LOGL_ERROR, "Empty endpoint name, can not generate MGCP message\n");
- msgb_free(msg);
- return NULL;
+ goto exit_error;
}
if (strstr(mgcp_msg->endpoint, "@") == NULL) {
LOGPMGW(mgcp, LOGL_ERROR,
"Endpoint name (%s) lacks separator (@), can not generate MGCP message\n",
mgcp_msg->endpoint);
- msgb_free(msg);
- return NULL;
+ goto exit_error;
}
- rc |= msgb_printf(msg, " %s", mgcp_msg->endpoint);
+ MSGB_PRINTF_OR_RET(" %s", mgcp_msg->endpoint);
}
/* Add protocol version */
- rc |= msgb_printf(msg, " MGCP 1.0\r\n");
+ MSGB_PRINTF_OR_RET(" 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);
+ MSGB_PRINTF_OR_RET("C: %x\r\n", mgcp_msg->call_id);
/* Add connection id */
if (mgcp_msg->presence & MGCP_MSG_PRESENCE_CONN_ID) {
if (strlen(mgcp_msg->conn_id) <= 0) {
LOGPMGW(mgcp, LOGL_ERROR, "Empty connection id, can not generate MGCP message\n");
- msgb_free(msg);
- return NULL;
+ goto exit_error;
}
- rc |= msgb_printf(msg, "I: %s\r\n", mgcp_msg->conn_id);
+ MSGB_PRINTF_OR_RET("I: %s\r\n", mgcp_msg->conn_id);
}
/* Using SDP makes sense when a valid IP/Port combination is specifiec,
@@ -1391,35 +1385,30 @@
|| mgcp_msg->verb == MGCP_VERB_MDCX)) {
if (add_lco(msg, mgcp_msg) < 0) {
LOGPMGW(mgcp, LOGL_ERROR, "Failed to add LCO, can not generate MGCP message\n");
- return NULL;
+ goto exit_error;
}
}
/* 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));
+ MSGB_PRINTF_OR_RET("M: %s\r\n", mgcp_client_cmode_name(mgcp_msg->conn_mode));
/* Add X-Osmo-IGN */
if ((mgcp_msg->presence & MGCP_MSG_PRESENCE_X_OSMO_IGN)
&& (mgcp_msg->x_osmo_ign != 0))
- rc |=
- msgb_printf(msg, MGCP_X_OSMO_IGN_HEADER "%s\r\n",
- mgcp_msg->x_osmo_ign & MGCP_X_OSMO_IGN_CALLID ? " C": "");
+ MSGB_PRINTF_OR_RET(MGCP_X_OSMO_IGN_HEADER "%s\r\n",
+ mgcp_msg->x_osmo_ign & MGCP_X_OSMO_IGN_CALLID ? " C" : "");
/* Add X-Osmo-Osmux */
if ((mgcp_msg->presence & MGCP_MSG_PRESENCE_X_OSMO_OSMUX_CID)) {
if (mgcp_msg->x_osmo_osmux_cid < -1 || mgcp_msg->x_osmo_osmux_cid > OSMUX_CID_MAX) {
LOGPMGW(mgcp, LOGL_ERROR, "Wrong Osmux CID %d, can not generate MGCP message\n",
mgcp_msg->x_osmo_osmux_cid);
- msgb_free(msg);
- return NULL;
+ goto exit_error;
}
snprintf(buf, sizeof(buf), " %d", mgcp_msg->x_osmo_osmux_cid);
- rc |=
- msgb_printf(msg, MGCP_X_OSMO_OSMUX_HEADER "%s\r\n",
- mgcp_msg->x_osmo_osmux_cid == -1 ? " *": buf);
+ MSGB_PRINTF_OR_RET(MGCP_X_OSMO_OSMUX_HEADER "%s\r\n",
+ mgcp_msg->x_osmo_osmux_cid == -1 ? " *" : buf);
}
@@ -1429,17 +1418,16 @@
|| mgcp_msg->verb == MGCP_VERB_MDCX)) {
if (add_sdp(msg, mgcp_msg, mgcp) < 0) {
LOGPMGW(mgcp, LOGL_ERROR, "Failed to add SDP, can not generate MGCP message\n");
- return NULL;
+ goto exit_error;
}
}
- if (rc != 0) {
- LOGPMGW(mgcp, LOGL_ERROR, "Message buffer to small, can not generate MGCP message\n");
- msgb_free(msg);
- msg = NULL;
- }
-
return msg;
+
+exit_error:
+ msgb_free(msg);
+ return NULL;
+#undef MSGB_PRINTF_OR_RET
}
/*! Retrieve the MGCP transaction ID from a msgb generated by mgcp_msg_gen()
diff --git a/tests/mgcp_client/mgcp_client_test.err b/tests/mgcp_client/mgcp_client_test.err
index d666cba..0bf6d8f 100644
--- a/tests/mgcp_client/mgcp_client_test.err
+++ b/tests/mgcp_client/mgcp_client_test.err
@@ -1,5 +1,5 @@
DLMGCP MGW(mgw) MGCP client: using endpoint domain '@mgw'
-DLMGCP MGW(mgw) Message buffer to small, can not generate MGCP message (SDP)
+DLMGCP MGW(mgw) Message buffer too small, can not generate MGCP message (SDP)
DLMGCP MGW(mgw) Failed to add SDP, can not generate MGCP message
test_mgcp_client_cancel():