mgcp: Include statistics at the end of a connection

Follow the MGCP specification and send the collected statistics
at the end of a call. Right now this does not include jitter, packet
loss and delay.
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h
index 751943a..d618f3c 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -168,6 +168,7 @@
 int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
 void mgcp_free_endp(struct mgcp_endpoint *endp);
 int mgcp_reset_transcoder(struct mgcp_config *cfg);
+void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size);
 
 /*
  * format helper functions
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index 719a4c7..d57ad00 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -107,9 +107,9 @@
 	return msg;
 }
 
-struct msgb *mgcp_create_response_with_data(int code, const char *txt,
-					    const char *msg, const char *trans,
-					    const char *data)
+static struct msgb *create_resp(int code, const char *txt, const char *msg,
+				const char *trans, const char *param,
+				const char *sdp)
 {
 	int len;
 	struct msgb *res;
@@ -118,10 +118,12 @@
 	if (!res)
 		return NULL;
 
-	if (data) {
-		len = snprintf((char *) res->data, 2048, "%d %s%s\r\n%s", code, trans, txt, data);
-	} else {
-		len = snprintf((char *) res->data, 2048, "%d %s%s\r\n", code, trans, txt);
+	len = snprintf((char *) res->data, 2048, "%d %s%s%s\r\n%s",
+			code, trans, txt, param ? param : "", sdp ? sdp : "");
+	if (len < 0) {
+		LOGP(DMGCP, LOGL_ERROR, "Failed to sprintf MGCP response.\n");
+		msgb_free(res);
+		return NULL;
 	}
 
 	res->l2h = msgb_put(res, len);
@@ -129,9 +131,22 @@
 	return res;
 }
 
+struct msgb *mgcp_create_response_with_data(int code, const char *txt,
+					    const char *msg, const char *trans,
+					    const char *data)
+{
+	return create_resp(code, txt, msg, trans, NULL, data);
+}
+
+static struct msgb *create_ok_resp_with_param(int code, const char *msg,
+					const char *trans, const char *param)
+{
+	return create_resp(code, " OK", msg, trans, param, NULL);
+}
+
 static struct msgb *create_ok_response(int code, const char *msg, const char *trans)
 {
-	return mgcp_create_response_with_data(code, " OK", msg, trans, NULL);
+	return create_ok_resp_with_param(code, msg, trans, NULL);
 }
 
 static struct msgb *create_err_response(int code, const char *msg, const char *trans)
@@ -707,6 +722,7 @@
 	int error_code = 400;
 	int silent = 0;
 	char *line, *save;
+	char stats[1048];
 
 	for_each_line((char *) msg->l3h, line, save) {
 		/* skip first line */
@@ -769,6 +785,9 @@
 	LOGP(DMGCP, LOGL_DEBUG, "Deleted endpoint on: 0x%x Server: %s:%u\n",
 		ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port));
 
+	/* save the statistics of the current call */
+	mgcp_format_stats(endp, stats, sizeof(stats));
+
 	delete_transcoder(endp);
 	mgcp_free_endp(endp);
 	if (cfg->change_cb)
@@ -776,7 +795,7 @@
 
 	if (silent)
 		goto out_silent;
-	return create_ok_response(250, "DLCX", trans_id);
+	return create_ok_resp_with_param(250, "DLCX", trans_id, stats);
 
 error3:
 	return create_err_response(error_code, "DLCX", trans_id);
@@ -1099,3 +1118,11 @@
 
 	return send_trans(cfg, mgcp_reset, sizeof mgcp_reset -1);
 }
+
+void mgcp_format_stats(struct mgcp_endpoint *endp, char *msg, size_t size)
+{
+	snprintf(msg, size, "\r\nP: PS=%u, OS=%u, PR=%u, OR=%u",
+			endp->bts_end.packets, endp->bts_end.octets,
+			endp->net_end.packets, endp->net_end.octets);
+	msg[size - 1] = '\0';
+}
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c
index d151ebb..41a51de 100644
--- a/openbsc/tests/mgcp/mgcp_test.c
+++ b/openbsc/tests/mgcp/mgcp_test.c
@@ -67,6 +67,13 @@
 		 "m=audio 5904 RTP/AVP 97\r"	\
 		 "a=rtpmap:97 GSM-EFR/8000\r"
 
+#define DLCX	 "DLCX 7 1@mgw MGCP 1.0\r\n"	\
+		 "C: 2\r\n"
+
+#define DLCX_RET "250 7 OK\r\n"			\
+		 "P: PS=0, OS=0, PR=0, OR=0\r\n"
+
+
 struct mgcp_test {
 	const char *name;
 	const char *req;
@@ -83,6 +90,7 @@
 	{ "SHORT2", SHORT2, SHORT2_RET },
 	{ "SHORT3", SHORT3, SHORT2_RET },
 	{ "SHORT4", SHORT4, SHORT2_RET },
+	{ "DLCX", DLCX, DLCX_RET },
 };
 
 static struct msgb *create_msg(const char *str)
diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok
index 45882a5..5e0e47c 100644
--- a/openbsc/tests/mgcp/mgcp_test.ok
+++ b/openbsc/tests/mgcp/mgcp_test.ok
@@ -7,4 +7,5 @@
 Testing SHORT2
 Testing SHORT3
 Testing SHORT4
+Testing DLCX
 Done