[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.
This commit is contained in:
Holger Hans Peter Freyther 2010-02-03 11:03:45 +01:00
parent 77f7afe08e
commit 62e836c533
3 changed files with 91 additions and 62 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}
/*