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; - len = snprintf(reset, sizeof(reset) - 1, + msg = mgcp_msgb_alloc(); + if (!msg) + return NULL; + + 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); } /*