aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-02-03 11:03:45 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-02-03 11:03:45 +0100
commit62e836c53394acccc83283ba6b11d462ba8e8483 (patch)
tree1fa62b745fb8b570bf14dd59493e1b87890a4811 /openbsc
parent77f7afe08e2529ff7be301f6cf5298207370807f (diff)
[mgcp] Make the mgcp_protocol generate a struct msgb*
Do not directly send data from inside the mgcp_protocol.c implementation. Instead allocate and return a struct msgb*. The caller can then either wrap that into the IPA protcol or directly send it over the UDP socket.
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/mgcp.h12
-rw-r--r--openbsc/src/mgcp/mgcp_main.c16
-rw-r--r--openbsc/src/mgcp/mgcp_protocol.c125
3 files changed, 91 insertions, 62 deletions
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h
index 114b39546..ee721d88d 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -21,6 +21,11 @@
*
*/
+#ifndef OPENBSC_MGCP_H
+#define OPENBSC_MGCP_H
+
+#include "msgb.h"
+
#define RTP_PORT_DEFAULT 4000
extern unsigned int rtp_base_port;
@@ -49,8 +54,9 @@ static inline int rtp_calculate_port(int multiplex, int base)
}
int mgcp_parse_config(const char *config_file, struct gsm_network *dummy_network);
-int mgcp_handle_message(int fd, struct msgb *msg, struct sockaddr_in *source);
-int mgcp_send_rsip(int fd, struct sockaddr_in *source);
+
+struct msgb *mgcp_handle_message(struct msgb *msg);
+struct msgb *mgcp_create_rsip(void);
int mgcp_vty_init(void);
/* endpoint managed */
@@ -60,3 +66,5 @@ int mgcp_vty_init(void);
typedef int (*mgcp_change)(int endpoint, int state, int local_rtp, void *);
void mgcp_set_change_cb(mgcp_change cb, void *data);
+
+#endif
diff --git a/openbsc/src/mgcp/mgcp_main.c b/openbsc/src/mgcp/mgcp_main.c
index 134148c62..6d8b3e9c6 100644
--- a/openbsc/src/mgcp/mgcp_main.c
+++ b/openbsc/src/mgcp/mgcp_main.c
@@ -106,6 +106,7 @@ static int read_call_agent(struct bsc_fd *fd, unsigned int what)
struct sockaddr_in addr;
socklen_t slen = sizeof(addr);
struct msgb *msg;
+ struct msgb *resp;
msg = (struct msgb *) fd->data;
@@ -123,14 +124,25 @@ static int read_call_agent(struct bsc_fd *fd, unsigned int what)
if (first_request) {
first_request = 0;
- mgcp_send_rsip(bfd.fd, &addr);
+ resp = mgcp_create_rsip();
+
+ if (resp) {
+ sendto(bfd.fd, resp->l2h, msgb_l2len(resp), 0,
+ (struct sockaddr *) &addr, sizeof(addr));
+ msgb_free(resp);
+ }
return 0;
}
/* handle message now */
msg->l2h = msgb_put(msg, rc);
- mgcp_handle_message(bfd.fd, msg, &addr);
+ resp = mgcp_handle_message(msg);
msgb_reset(msg);
+
+ if (resp) {
+ sendto(bfd.fd, resp->l2h, msgb_l2len(resp), 0, (struct sockaddr *) &addr, sizeof(addr));
+ msgb_free(resp);
+ }
return 0;
}
diff --git a/openbsc/src/mgcp/mgcp_protocol.c b/openbsc/src/mgcp/mgcp_protocol.c
index d09615743..55edb00bf 100644
--- a/openbsc/src/mgcp/mgcp_protocol.c
+++ b/openbsc/src/mgcp/mgcp_protocol.c
@@ -150,17 +150,17 @@ struct mgcp_msg_ptr {
struct mgcp_request {
char *name;
- int (*handle_request) (int fd, struct msgb *msg, struct sockaddr_in *source);
+ struct msgb *(*handle_request) (struct msgb *msg);
char *debug_name;
};
#define MGCP_REQUEST(NAME, REQ, DEBUG_NAME) \
{ .name = NAME, .handle_request = REQ, .debug_name = DEBUG_NAME },
-static int handle_audit_endpoint(int fd, struct msgb *msg, struct sockaddr_in *source);
-static int handle_create_con(int fd, struct msgb *msg, struct sockaddr_in *source);
-static int handle_delete_con(int fd, struct msgb *msg, struct sockaddr_in *source);
-static int handle_modify_con(int fd, struct msgb *msg, struct sockaddr_in *source);
+static struct msgb *handle_audit_endpoint(struct msgb *msg);
+static struct msgb *handle_create_con(struct msgb *msg);
+static struct msgb *handle_delete_con(struct msgb *msg);
+static struct msgb *handle_modify_con(struct msgb *msg);
static mgcp_change change_cb;
static void *change_cb_data;
@@ -361,32 +361,43 @@ static const struct mgcp_request mgcp_requests [] = {
MGCP_REQUEST("MDCX", handle_modify_con, "ModifiyConnection")
};
-static int send_response_with_data(int fd, int code, const char *msg, const char *trans,
- const char *data, struct sockaddr_in *source)
+static struct msgb *mgcp_msgb_alloc(void)
+{
+ struct msgb *msg;
+ msg = msgb_alloc_headroom(4096, 128, "MGCP msg");
+ if (!msg)
+ LOGP(DMGCP, LOGL_ERROR, "Failed to msgb for MGCP data.\n");
+
+ return msg;
+}
+
+static struct msgb *send_response_with_data(int code, const char *msg, const char *trans,
+ const char *data)
{
- char buf[4096];
int len;
+ struct msgb *res;
+
+ res = mgcp_msgb_alloc();
+ if (!res)
+ return NULL;
if (data) {
- len = snprintf(buf, sizeof(buf), "%d %s\n%s", code, trans, data);
+ len = snprintf((char *) res->data, 2048, "%d %s\n%s", code, trans, data);
} else {
- len = snprintf(buf, sizeof(buf), "%d %s\n", code, trans);
+ len = snprintf((char *) res->data, 2048, "%d %s\n", code, trans);
}
- LOGP(DMGCP, LOGL_NOTICE, "Sending response: code: %d for '%s'\n", code, msg);
- if (source)
- return sendto(fd, buf, len, 0, (struct sockaddr *)source, sizeof(*source));
- else
- return write(fd, buf, len);
+ res->l2h = msgb_put(res, len);
+ LOGP(DMGCP, LOGL_NOTICE, "Sending response: code: %d for '%s'\n", code, res->l2h);
+ return res;
}
-static int send_response(int fd, int code, const char *msg,
- const char *trans, struct sockaddr_in *source)
+static struct msgb *send_response(int code, const char *msg, const char *trans)
{
- return send_response_with_data(fd, code, msg, trans, NULL, source);
+ return send_response_with_data(code, msg, trans, NULL);
}
-static int send_with_sdp(int fd, struct mgcp_endpoint *endp, const char *msg, const char *trans_id, struct sockaddr_in *source)
+static struct msgb *send_with_sdp(struct mgcp_endpoint *endp, const char *msg, const char *trans_id)
{
const char *addr = local_ip;
char sdp_record[4096];
@@ -402,28 +413,24 @@ static int send_with_sdp(int fd, struct mgcp_endpoint *endp, const char *msg, co
"a=rtpmap:%d %s\r\n",
endp->ci, addr, endp->rtp_port,
audio_payload, audio_payload, audio_name);
- return send_response_with_data(fd, 200, msg, trans_id, sdp_record, source);
+ return send_response_with_data(200, msg, trans_id, sdp_record);
}
/* send a static record */
-int mgcp_send_rsip(int fd, struct sockaddr_in *source)
+struct msgb *mgcp_create_rsip(void)
{
- char reset[4096];
- int len, rc;
+ struct msgb *msg;
+ int len;
+
+ msg = mgcp_msgb_alloc();
+ if (!msg)
+ return NULL;
- len = snprintf(reset, sizeof(reset) - 1,
+ len = snprintf((char *) msg->data, 2048,
"RSIP %u *@mgw MGCP 1.0\n"
"RM: restart\n", generate_transaction_id());
- if (source)
- rc = sendto(fd, reset, len, 0, (struct sockaddr *) source, sizeof(*source));
- else
- rc = write(fd, reset, len);
-
- if (rc < 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to send RSIP: %d\n", rc);
- }
-
- return rc;
+ msg->l2h = msgb_put(msg, len);
+ return msg;
}
/*
@@ -431,13 +438,14 @@ int mgcp_send_rsip(int fd, struct sockaddr_in *source)
* - this can be a command (four letters, space, transaction id)
* - or a response (three numbers, space, transaction id)
*/
-int mgcp_handle_message(int fd, struct msgb *msg, struct sockaddr_in *source)
+struct msgb *mgcp_handle_message(struct msgb *msg)
{
int code;
+ struct msgb *resp = NULL;
if (msg->len < 4) {
LOGP(DMGCP, LOGL_ERROR, "mgs too short: %d\n", msg->len);
- return -1;
+ return NULL;
}
/* attempt to treat it as a response */
@@ -449,14 +457,15 @@ int mgcp_handle_message(int fd, struct msgb *msg, struct sockaddr_in *source)
for (i = 0; i < ARRAY_SIZE(mgcp_requests); ++i)
if (strncmp(mgcp_requests[i].name, (const char *) &msg->data[0], 4) == 0) {
handled = 1;
- mgcp_requests[i].handle_request(fd, msg, source);
+ resp = mgcp_requests[i].handle_request(msg);
+ break;
}
if (!handled) {
LOGP(DMGCP, LOGL_NOTICE, "MSG with type: '%.4s' not handled\n", &msg->data[0]);
}
}
- return 0;
+ return resp;
}
/* string tokenizer for the poor */
@@ -572,7 +581,7 @@ static int verify_ci(const struct mgcp_endpoint *endp,
return 0;
}
-static int handle_audit_endpoint(int fd, struct msgb *msg, struct sockaddr_in *source)
+static struct msgb *handle_audit_endpoint(struct msgb *msg)
{
struct mgcp_msg_ptr data_ptrs[6];
int found, response;
@@ -585,7 +594,7 @@ static int handle_audit_endpoint(int fd, struct msgb *msg, struct sockaddr_in *s
else
response = 200;
- return send_response(fd, response, "AUEP", trans_id, source);
+ return send_response(response, "AUEP", trans_id);
}
static int parse_conn_mode(const char* msg, int *conn_mode)
@@ -603,7 +612,7 @@ static int parse_conn_mode(const char* msg, int *conn_mode)
return ret;
}
-static int handle_create_con(int fd, struct msgb *msg, struct sockaddr_in *source)
+static struct msgb *handle_create_con(struct msgb *msg)
{
struct mgcp_msg_ptr data_ptrs[6];
int found, i, line_start;
@@ -613,11 +622,11 @@ static int handle_create_con(int fd, struct msgb *msg, struct sockaddr_in *sourc
found = analyze_header(msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
if (found != 0)
- return send_response(fd, 500, "CRCX", trans_id, source);
+ return send_response(500, "CRCX", trans_id);
if (endp->ci != CI_UNUSED) {
LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n", ENDPOINT_NUMBER(endp));
- return send_response(fd, 500, "CRCX", trans_id, source);
+ return send_response(500, "CRCX", trans_id);
}
/* parse CallID C: and LocalParameters L: */
@@ -667,19 +676,19 @@ static int handle_create_con(int fd, struct msgb *msg, struct sockaddr_in *sourc
if (change_cb)
change_cb(ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX, endp->rtp_port, change_cb_data);
- return send_with_sdp(fd, endp, "CRCX", trans_id, source);
+ return send_with_sdp(endp, "CRCX", trans_id);
error:
LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d\n",
hexdump(msg->l3h, msgb_l3len(msg)),
ENDPOINT_NUMBER(endp), line_start, i);
- return send_response(fd, error_code, "CRCX", trans_id, source);
+ return send_response(error_code, "CRCX", trans_id);
error2:
LOGP(DMGCP, LOGL_NOTICE, "Resource error on 0x%x\n", ENDPOINT_NUMBER(endp));
- return send_response(fd, error_code, "CRCX", trans_id, source);
+ return send_response(error_code, "CRCX", trans_id);
}
-static int handle_modify_con(int fd, struct msgb *msg, struct sockaddr_in *source)
+static struct msgb *handle_modify_con(struct msgb *msg)
{
struct mgcp_msg_ptr data_ptrs[6];
int found, i, line_start;
@@ -689,11 +698,11 @@ static int handle_modify_con(int fd, struct msgb *msg, struct sockaddr_in *sourc
found = analyze_header(msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
if (found != 0)
- return send_response(fd, error_code, "MDCX", trans_id, source);
+ return send_response(error_code, "MDCX", trans_id);
if (endp->ci == CI_UNUSED) {
LOGP(DMGCP, LOGL_ERROR, "Endpoint is not holding a connection. 0x%x\n", ENDPOINT_NUMBER(endp));
- return send_response(fd, error_code, "MDCX", trans_id, source);
+ return send_response(error_code, "MDCX", trans_id);
}
MSG_TOKENIZE_START
@@ -760,19 +769,19 @@ static int handle_modify_con(int fd, struct msgb *msg, struct sockaddr_in *sourc
ENDPOINT_NUMBER(endp), inet_ntoa(endp->remote), endp->net_rtp);
if (change_cb)
change_cb(ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX, endp->rtp_port, change_cb_data);
- return send_with_sdp(fd, endp, "MDCX", trans_id, source);
+ return send_with_sdp(endp, "MDCX", trans_id);
error:
LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d %d\n",
hexdump(msg->l3h, msgb_l3len(msg)),
ENDPOINT_NUMBER(endp), line_start, i, msg->l3h[line_start]);
- return send_response(fd, error_code, "MDCX", trans_id, source);
+ return send_response(error_code, "MDCX", trans_id);
error3:
- return send_response(fd, error_code, "MDCX", trans_id, source);
+ return send_response(error_code, "MDCX", trans_id);
}
-static int handle_delete_con(int fd, struct msgb *msg, struct sockaddr_in *source)
+static struct msgb *handle_delete_con(struct msgb *msg)
{
struct mgcp_msg_ptr data_ptrs[6];
int found, i, line_start;
@@ -782,11 +791,11 @@ static int handle_delete_con(int fd, struct msgb *msg, struct sockaddr_in *sourc
found = analyze_header(msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
if (found != 0)
- return send_response(fd, error_code, "DLCX", trans_id, source);
+ return send_response(error_code, "DLCX", trans_id);
if (endp->ci == CI_UNUSED) {
LOGP(DMGCP, LOGL_ERROR, "Endpoint is not used. 0x%x\n", ENDPOINT_NUMBER(endp));
- return send_response(fd, error_code, "DLCX", trans_id, source);
+ return send_response(error_code, "DLCX", trans_id);
}
MSG_TOKENIZE_START
@@ -825,16 +834,16 @@ static int handle_delete_con(int fd, struct msgb *msg, struct sockaddr_in *sourc
if (change_cb)
change_cb(ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX, endp->rtp_port, change_cb_data);
- return send_response(fd, 250, "DLCX", trans_id, source);
+ return send_response(250, "DLCX", trans_id);
error:
LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d\n",
hexdump(msg->l3h, msgb_l3len(msg)),
ENDPOINT_NUMBER(endp), line_start, i);
- return send_response(fd, error_code, "DLCX", trans_id, source);
+ return send_response(error_code, "DLCX", trans_id);
error3:
- return send_response(fd, error_code, "DLCX", trans_id, source);
+ return send_response(error_code, "DLCX", trans_id);
}
/*