[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:
parent
77f7afe08e
commit
62e836c533
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue