Merge branch 'on-waves/mgcp'
This commit is contained in:
commit
91b5a31a2c
|
@ -10,7 +10,7 @@ rsip_resp = """200 321321332\r\n"""
|
|||
audit_packet = """AUEP %d 13@mgw MGCP 1.0\r\n"""
|
||||
crcx_packet = """CRCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nL: p:20, a:GSM-EFR, nt:IN\r\nM: recvonly\r\n"""
|
||||
dlcx_packet = """DLCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nI: %d\r\n"""
|
||||
mdcx_packet = """MDCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nI: %d\r\nL: p:20, a:GSM-EFR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 258696477 0 IN IP4 172.16.1.107\r\ns=-\r\nc=IN IP4 172.16.1.107\r\nt=0 0\r\nm=audio 4400 RTP/AVP 127\r\na=rtpmap:127 GSM-EFR/8000/1\r\na=ptime:20\r\na=recvonly\r\nm=image 4402 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n"""
|
||||
mdcx_packet = """MDCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nI: %d\r\nL: p:20, a:GSM-EFR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 258696477 0 IN IP4 172.16.1.107\r\ns=-\r\nc=IN IP4 172.16.1.107\r\nt=0 0\r\nm=audio 6666 RTP/AVP 127\r\na=rtpmap:127 GSM-EFR/8000/1\r\na=ptime:20\r\na=recvonly\r\nm=image 4402 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n"""
|
||||
|
||||
def hexdump(src, length=8):
|
||||
"""Recipe is from http://code.activestate.com/recipes/142812/"""
|
||||
|
@ -25,15 +25,24 @@ def hexdump(src, length=8):
|
|||
|
||||
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
server_socket.bind(("127.0.0.1", MGCP_CALLAGENT_PORT))
|
||||
server_socket.setblocking(0)
|
||||
server_socket.setblocking(1)
|
||||
|
||||
|
||||
def send_receive(packet):
|
||||
last_ci = 1
|
||||
def send_and_receive(packet):
|
||||
global last_ci
|
||||
server_socket.sendto(packet, ("127.0.0.1", MGCP_GATEWAY_PORT))
|
||||
try:
|
||||
data, addr = server_socket.recvfrom(4096)
|
||||
|
||||
# attempt to store the CI of the response
|
||||
list = data.split("\n")
|
||||
for item in list:
|
||||
if item.startswith("I: "):
|
||||
last_ci = int(item[3:])
|
||||
|
||||
print hexdump(data), addr
|
||||
except socket.error:
|
||||
except socket.error, e:
|
||||
print e
|
||||
pass
|
||||
|
||||
def generate_tid():
|
||||
|
@ -42,13 +51,10 @@ def generate_tid():
|
|||
|
||||
|
||||
|
||||
i = 1
|
||||
while True:
|
||||
send_receive(rsip_resp)
|
||||
send_receive(audit_packet)
|
||||
send_receive(crcx_packet % generate_tid() )
|
||||
send_receive(mdcx_packet % (generate_tid(), i))
|
||||
send_receive(dlcx_packet % (generate_tid(), i))
|
||||
i = i + 1
|
||||
send_and_receive(audit_packet % generate_tid())
|
||||
send_and_receive(crcx_packet % generate_tid() )
|
||||
send_and_receive(mdcx_packet % (generate_tid(), last_ci))
|
||||
send_and_receive(dlcx_packet % (generate_tid(), last_ci))
|
||||
|
||||
time.sleep(3)
|
||||
|
|
|
@ -77,6 +77,7 @@ struct mgcp_config;
|
|||
|
||||
typedef int (*mgcp_change)(struct mgcp_config *cfg, int endpoint, int state, int local_rtp);
|
||||
typedef int (*mgcp_policy)(struct mgcp_config *cfg, int endpoint, int state, const char *transactio_id);
|
||||
typedef int (*mgcp_reset)(struct mgcp_config *cfg);
|
||||
|
||||
struct mgcp_config {
|
||||
int source_port;
|
||||
|
@ -84,6 +85,7 @@ struct mgcp_config {
|
|||
char *source_addr;
|
||||
unsigned int number_endpoints;
|
||||
char *bts_ip;
|
||||
char *call_agent_addr;
|
||||
|
||||
struct in_addr bts_in;
|
||||
char *audio_name;
|
||||
|
@ -95,8 +97,12 @@ struct mgcp_config {
|
|||
char *forward_ip;
|
||||
int forward_port;
|
||||
|
||||
/* spec handling */
|
||||
int force_realloc;
|
||||
|
||||
mgcp_change change_cb;
|
||||
mgcp_policy policy_cb;
|
||||
mgcp_reset reset_cb;
|
||||
void *data;
|
||||
|
||||
struct mgcp_endpoint *endpoints;
|
||||
|
@ -115,8 +121,15 @@ void mgcp_free_endp(struct mgcp_endpoint *endp);
|
|||
* format helper functions
|
||||
*/
|
||||
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
|
||||
struct msgb *mgcp_create_rsip(void);
|
||||
struct msgb *mgcp_create_response_with_data(int code, const char *msg, const char *trans, const char *data);
|
||||
|
||||
/* adc helper */
|
||||
static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
|
||||
{
|
||||
if (timeslot == 0)
|
||||
timeslot = 1;
|
||||
return timeslot + (31 * multiplex);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,8 +57,21 @@ struct mgcp_endpoint {
|
|||
|
||||
/* backpointer */
|
||||
struct mgcp_config *cfg;
|
||||
|
||||
/* statistics */
|
||||
unsigned int in_bts;
|
||||
unsigned int in_remote;
|
||||
};
|
||||
|
||||
#define ENDPOINT_NUMBER(endp) abs(endp - endp->cfg->endpoints)
|
||||
|
||||
struct mgcp_msg_ptr {
|
||||
unsigned int start;
|
||||
unsigned int length;
|
||||
};
|
||||
|
||||
int mgcp_analyze_header(struct mgcp_config *cfg, struct msgb *msg,
|
||||
struct mgcp_msg_ptr *ptr, int size,
|
||||
const char **transaction_id, struct mgcp_endpoint **endp);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,8 +38,11 @@
|
|||
#include <openbsc/gsm_data.h>
|
||||
#include <osmocore/select.h>
|
||||
#include <openbsc/mgcp.h>
|
||||
#include <openbsc/mgcp_internal.h>
|
||||
#include <openbsc/telnet_interface.h>
|
||||
|
||||
#include <vty/command.h>
|
||||
|
||||
#include "../../bscconfig.h"
|
||||
|
||||
/* this is here for the vty... it will never be called */
|
||||
|
@ -51,8 +54,9 @@ void subscr_put() { abort(); }
|
|||
#warning "Make use of the rtp proxy code"
|
||||
|
||||
static struct bsc_fd bfd;
|
||||
static int first_request = 1;
|
||||
static struct mgcp_config *cfg;
|
||||
static int reset_endpoints = 0;
|
||||
|
||||
const char *openbsc_version = "OpenBSC MGCP " PACKAGE_VERSION;
|
||||
const char *openbsc_copyright =
|
||||
"Copyright (C) 2009-2010 Holger Freyther and On-Waves\n"
|
||||
|
@ -74,10 +78,10 @@ static void print_help()
|
|||
printf(" -c --config-file filename The config file to use.\n");
|
||||
}
|
||||
|
||||
static void print_version()
|
||||
static void print_mgcp_version()
|
||||
{
|
||||
printf("%s\n\n", openbsc_version);
|
||||
printf(openbsc_copyright);
|
||||
printf("%s", openbsc_copyright);
|
||||
}
|
||||
|
||||
static void handle_options(int argc, char** argv)
|
||||
|
@ -105,7 +109,7 @@ static void handle_options(int argc, char** argv)
|
|||
config_file = talloc_strdup(tall_bsc_ctx, optarg);
|
||||
break;
|
||||
case 'V':
|
||||
print_version();
|
||||
print_mgcp_version();
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
|
@ -115,12 +119,21 @@ static void handle_options(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
/* simply remember this */
|
||||
static int mgcp_rsip_cb(struct mgcp_config *cfg)
|
||||
{
|
||||
reset_endpoints = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
int i;
|
||||
|
||||
msg = (struct msgb *) fd->data;
|
||||
|
||||
|
@ -136,18 +149,6 @@ static int read_call_agent(struct bsc_fd *fd, unsigned int what)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (first_request) {
|
||||
first_request = 0;
|
||||
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);
|
||||
resp = mgcp_handle_message(cfg, msg);
|
||||
|
@ -157,6 +158,16 @@ static int read_call_agent(struct bsc_fd *fd, unsigned int what)
|
|||
sendto(bfd.fd, resp->l2h, msgb_l2len(resp), 0, (struct sockaddr *) &addr, sizeof(addr));
|
||||
msgb_free(resp);
|
||||
}
|
||||
|
||||
if (reset_endpoints) {
|
||||
LOGP(DMGCP, LOGL_NOTICE, "Asked to reset endpoints.\n");
|
||||
reset_endpoints = 0;
|
||||
|
||||
/* is checking in_addr.s_addr == INADDR_LOOPBACK making it more secure? */
|
||||
for (i = 1; i < cfg->number_endpoints; ++i)
|
||||
mgcp_free_endp(&cfg->endpoints[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -186,6 +197,8 @@ int main(int argc, char** argv)
|
|||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* set some callbacks */
|
||||
cfg->reset_cb = mgcp_rsip_cb;
|
||||
|
||||
/* we need to bind a socket */
|
||||
if (rc == 0) {
|
||||
|
@ -217,11 +230,11 @@ int main(int argc, char** argv)
|
|||
|
||||
|
||||
if (bsc_register_fd(&bfd) != 0) {
|
||||
DEBUGP(DMGCP, "Failed to register the fd\n");
|
||||
LOGP(DMGCP, LOGL_FATAL, "Failed to register the fd\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUGP(DMGCP, "Configured for MGCP.\n");
|
||||
LOGP(DMGCP, LOGL_NOTICE, "Configured for MGCP.\n");
|
||||
}
|
||||
|
||||
/* initialisation */
|
||||
|
@ -235,3 +248,14 @@ int main(int argc, char** argv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct gsm_network;
|
||||
int bsc_vty_init(struct gsm_network *dummy)
|
||||
{
|
||||
cmd_init(1);
|
||||
vty_init();
|
||||
|
||||
mgcp_vty_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
|
@ -90,6 +91,9 @@ static void patch_payload(int payload, char *data, int len)
|
|||
if (len < sizeof(*rtp_hdr))
|
||||
return;
|
||||
|
||||
if (payload < 0)
|
||||
return;
|
||||
|
||||
rtp_hdr = (struct rtp_hdr *) data;
|
||||
rtp_hdr->payload_type = payload;
|
||||
}
|
||||
|
@ -119,16 +123,14 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what)
|
|||
rc = recvfrom(fd->fd, &buf, sizeof(buf), 0,
|
||||
(struct sockaddr *) &addr, &slen);
|
||||
if (rc < 0) {
|
||||
LOGP(DMGCP, LOGL_ERROR, "Failed to receive message on: 0x%x\n",
|
||||
ENDPOINT_NUMBER(endp));
|
||||
LOGP(DMGCP, LOGL_ERROR, "Failed to receive message on: 0x%x errno: %d/%s\n",
|
||||
ENDPOINT_NUMBER(endp), errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* do not forward aynthing... maybe there is a packet from the bts */
|
||||
if (endp->ci == CI_UNUSED) {
|
||||
LOGP(DMGCP, LOGL_ERROR, "Unknown message on endpoint: 0x%x\n", ENDPOINT_NUMBER(endp));
|
||||
if (endp->ci == CI_UNUSED)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out where to forward it to. This code assumes that we
|
||||
|
@ -146,7 +148,9 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what)
|
|||
/* We have no idea who called us, maybe it is the BTS. */
|
||||
if (dest == DEST_NETWORK && (endp->bts_rtp == 0 || cfg->forward_ip)) {
|
||||
/* it was the BTS... */
|
||||
if (!cfg->bts_ip || memcmp(&addr.sin_addr, &cfg->bts_in, sizeof(cfg->bts_in)) == 0) {
|
||||
if (!cfg->bts_ip
|
||||
|| memcmp(&addr.sin_addr, &cfg->bts_in, sizeof(cfg->bts_in)) == 0
|
||||
|| memcmp(&addr.sin_addr, &endp->bts, sizeof(endp->bts)) == 0) {
|
||||
if (fd == &endp->local_rtp) {
|
||||
endp->bts_rtp = addr.sin_port;
|
||||
} else {
|
||||
|
@ -159,6 +163,12 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what)
|
|||
}
|
||||
}
|
||||
|
||||
/* do this before the loop handling */
|
||||
if (dest == DEST_NETWORK)
|
||||
++endp->in_bts;
|
||||
else
|
||||
++endp->in_remote;
|
||||
|
||||
/* dispatch */
|
||||
if (cfg->audio_loop)
|
||||
dest = !dest;
|
||||
|
|
|
@ -80,11 +80,6 @@ enum mgcp_connection_mode {
|
|||
}
|
||||
|
||||
|
||||
struct mgcp_msg_ptr {
|
||||
unsigned int start;
|
||||
unsigned int length;
|
||||
};
|
||||
|
||||
struct mgcp_request {
|
||||
char *name;
|
||||
struct msgb *(*handle_request) (struct mgcp_config *cfg, struct msgb *msg);
|
||||
|
@ -98,6 +93,7 @@ static struct msgb *handle_audit_endpoint(struct mgcp_config *cfg, struct msgb *
|
|||
static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg);
|
||||
static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg);
|
||||
static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg);
|
||||
static struct msgb *handle_rsip(struct mgcp_config *cfg, struct msgb *msg);
|
||||
|
||||
static int generate_call_id(struct mgcp_config *cfg)
|
||||
{
|
||||
|
@ -119,12 +115,6 @@ static int generate_call_id(struct mgcp_config *cfg)
|
|||
return cfg->last_call_id;
|
||||
}
|
||||
|
||||
/* FIXIME/TODO: need to have a list of pending transactions and check that */
|
||||
static unsigned int generate_transaction_id()
|
||||
{
|
||||
return abs(rand());
|
||||
}
|
||||
|
||||
/*
|
||||
* array of function pointers for handling various
|
||||
* messages. In the future this might be binary sorted
|
||||
|
@ -135,6 +125,9 @@ static const struct mgcp_request mgcp_requests [] = {
|
|||
MGCP_REQUEST("CRCX", handle_create_con, "CreateConnection")
|
||||
MGCP_REQUEST("DLCX", handle_delete_con, "DeleteConnection")
|
||||
MGCP_REQUEST("MDCX", handle_modify_con, "ModifiyConnection")
|
||||
|
||||
/* SPEC extension */
|
||||
MGCP_REQUEST("RSIP", handle_rsip, "ReSetInProgress")
|
||||
};
|
||||
|
||||
static struct msgb *mgcp_msgb_alloc(void)
|
||||
|
@ -194,23 +187,6 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
|
|||
return mgcp_create_response_with_data(200, msg, trans_id, sdp_record);
|
||||
}
|
||||
|
||||
/* send a static record */
|
||||
struct msgb *mgcp_create_rsip(void)
|
||||
{
|
||||
struct msgb *msg;
|
||||
int len;
|
||||
|
||||
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());
|
||||
msg->l2h = msgb_put(msg, len);
|
||||
return msg;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle incoming messages:
|
||||
* - this can be a command (four letters, space, transaction id)
|
||||
|
@ -221,25 +197,25 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
|
|||
int code;
|
||||
struct msgb *resp = NULL;
|
||||
|
||||
if (msg->len < 4) {
|
||||
if (msgb_l2len(msg) < 4) {
|
||||
LOGP(DMGCP, LOGL_ERROR, "mgs too short: %d\n", msg->len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* attempt to treat it as a response */
|
||||
if (sscanf((const char *)&msg->data[0], "%3d %*s", &code) == 1) {
|
||||
if (sscanf((const char *)&msg->l2h[0], "%3d %*s", &code) == 1) {
|
||||
LOGP(DMGCP, LOGL_DEBUG, "Response: Code: %d\n", code);
|
||||
} else {
|
||||
int i, handled = 0;
|
||||
msg->l3h = &msg->l2h[4];
|
||||
for (i = 0; i < ARRAY_SIZE(mgcp_requests); ++i)
|
||||
if (strncmp(mgcp_requests[i].name, (const char *) &msg->data[0], 4) == 0) {
|
||||
if (strncmp(mgcp_requests[i].name, (const char *) &msg->l2h[0], 4) == 0) {
|
||||
handled = 1;
|
||||
resp = mgcp_requests[i].handle_request(cfg, msg);
|
||||
break;
|
||||
}
|
||||
if (!handled) {
|
||||
LOGP(DMGCP, LOGL_NOTICE, "MSG with type: '%.4s' not handled\n", &msg->data[0]);
|
||||
LOGP(DMGCP, LOGL_NOTICE, "MSG with type: '%.4s' not handled\n", &msg->l2h[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,9 +272,9 @@ static struct mgcp_endpoint *find_endpoint(struct mgcp_config *cfg, const char *
|
|||
return &cfg->endpoints[gw];
|
||||
}
|
||||
|
||||
static int analyze_header(struct mgcp_config *cfg, struct msgb *msg,
|
||||
struct mgcp_msg_ptr *ptr, int size,
|
||||
const char **transaction_id, struct mgcp_endpoint **endp)
|
||||
int mgcp_analyze_header(struct mgcp_config *cfg, struct msgb *msg,
|
||||
struct mgcp_msg_ptr *ptr, int size,
|
||||
const char **transaction_id, struct mgcp_endpoint **endp)
|
||||
{
|
||||
int found;
|
||||
|
||||
|
@ -334,8 +310,11 @@ static int analyze_header(struct mgcp_config *cfg, struct msgb *msg,
|
|||
}
|
||||
|
||||
*transaction_id = (const char *)&msg->l3h[ptr[0].start];
|
||||
*endp = find_endpoint(cfg, (const char *)&msg->l3h[ptr[1].start]);
|
||||
return *endp == NULL;
|
||||
if (endp) {
|
||||
*endp = find_endpoint(cfg, (const char *)&msg->l3h[ptr[1].start]);
|
||||
return *endp == NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verify_call_id(const struct mgcp_endpoint *endp,
|
||||
|
@ -369,7 +348,7 @@ static struct msgb *handle_audit_endpoint(struct mgcp_config *cfg, struct msgb *
|
|||
const char *trans_id;
|
||||
struct mgcp_endpoint *endp;
|
||||
|
||||
found = analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
|
||||
found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
|
||||
if (found != 0)
|
||||
response = 500;
|
||||
else
|
||||
|
@ -402,13 +381,19 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg)
|
|||
int error_code = 500;
|
||||
int port;
|
||||
|
||||
found = analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
|
||||
found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
|
||||
if (found != 0)
|
||||
return create_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 create_response(500, "CRCX", trans_id);
|
||||
if (cfg->force_realloc) {
|
||||
LOGP(DMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n",
|
||||
ENDPOINT_NUMBER(endp));
|
||||
} else {
|
||||
LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n",
|
||||
ENDPOINT_NUMBER(endp));
|
||||
return create_response(500, "CRCX", trans_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* parse CallID C: and LocalParameters L: */
|
||||
|
@ -501,7 +486,7 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg)
|
|||
struct mgcp_endpoint *endp;
|
||||
int error_code = 500;
|
||||
|
||||
found = analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
|
||||
found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
|
||||
if (found != 0)
|
||||
return create_response(error_code, "MDCX", trans_id);
|
||||
|
||||
|
@ -614,7 +599,7 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg)
|
|||
struct mgcp_endpoint *endp;
|
||||
int error_code = 500;
|
||||
|
||||
found = analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
|
||||
found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
|
||||
if (found != 0)
|
||||
return create_response(error_code, "DLCX", trans_id);
|
||||
|
||||
|
@ -678,6 +663,13 @@ error3:
|
|||
return create_response(error_code, "DLCX", trans_id);
|
||||
}
|
||||
|
||||
static struct msgb *handle_rsip(struct mgcp_config *cfg, struct msgb *msg)
|
||||
{
|
||||
if (cfg->reset_cb)
|
||||
cfg->reset_cb(cfg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mgcp_config *mgcp_config_alloc(void)
|
||||
{
|
||||
struct mgcp_config *cfg;
|
||||
|
@ -722,7 +714,7 @@ int mgcp_endpoints_allocate(struct mgcp_config *cfg)
|
|||
|
||||
void mgcp_free_endp(struct mgcp_endpoint *endp)
|
||||
{
|
||||
LOGP(DMGCP, LOGL_NOTICE, "Deleting endpoint on: 0x%x\n", ENDPOINT_NUMBER(endp));
|
||||
LOGP(DMGCP, LOGL_DEBUG, "Deleting endpoint on: 0x%x\n", ENDPOINT_NUMBER(endp));
|
||||
endp->ci= CI_UNUSED;
|
||||
|
||||
if (endp->callid) {
|
||||
|
@ -732,7 +724,7 @@ void mgcp_free_endp(struct mgcp_endpoint *endp)
|
|||
|
||||
if (endp->local_options) {
|
||||
talloc_free(endp->local_options);
|
||||
endp->callid = NULL;
|
||||
endp->local_options = NULL;
|
||||
}
|
||||
|
||||
if (!endp->cfg->early_bind) {
|
||||
|
@ -742,4 +734,7 @@ void mgcp_free_endp(struct mgcp_endpoint *endp)
|
|||
|
||||
endp->net_rtp = endp->net_rtcp = endp->bts_rtp = endp->bts_rtcp = 0;
|
||||
endp->net_payload_type = endp->bts_payload_type = -1;
|
||||
endp->in_bts = endp->in_remote = 0;
|
||||
memset(&endp->remote, 0, sizeof(endp->remote));
|
||||
memset(&endp->bts, 0, sizeof(endp->bts));
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@ static int config_write_mgcp(struct vty *vty)
|
|||
vty_out(vty, " forward audio ip %s%s", g_cfg->forward_ip, VTY_NEWLINE);
|
||||
if (g_cfg->forward_port != 0)
|
||||
vty_out(vty, " forward audio port %d%s", g_cfg->forward_port, VTY_NEWLINE);
|
||||
if (g_cfg->call_agent_addr)
|
||||
vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
@ -75,10 +77,12 @@ DEFUN(show_mcgp, show_mgcp_cmd, "show mgcp",
|
|||
vty_out(vty, "MGCP is up and running with %u endpoints:%s", g_cfg->number_endpoints - 1, VTY_NEWLINE);
|
||||
for (i = 1; i < g_cfg->number_endpoints; ++i) {
|
||||
struct mgcp_endpoint *endp = &g_cfg->endpoints[i];
|
||||
vty_out(vty, " Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u%s",
|
||||
vty_out(vty, " Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u on %s traffic in :%u/%u%s",
|
||||
i, endp->ci,
|
||||
ntohs(endp->net_rtp), ntohs(endp->net_rtcp),
|
||||
ntohs(endp->bts_rtp), ntohs(endp->bts_rtcp), VTY_NEWLINE);
|
||||
ntohs(endp->bts_rtp), ntohs(endp->bts_rtcp),
|
||||
inet_ntoa(endp->bts), endp->in_bts, endp->in_remote,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
@ -237,6 +241,17 @@ DEFUN(cfg_mgcp_forward_port,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_agent_addr,
|
||||
cfg_mgcp_agent_addr_cmd,
|
||||
"call agent ip IP",
|
||||
"Set the address of the call agent.")
|
||||
{
|
||||
if (g_cfg->call_agent_addr)
|
||||
talloc_free(g_cfg->call_agent_addr);
|
||||
g_cfg->call_agent_addr = talloc_strdup(g_cfg, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int mgcp_vty_init(void)
|
||||
{
|
||||
install_element(VIEW_NODE, &show_mgcp_cmd);
|
||||
|
@ -256,6 +271,7 @@ int mgcp_vty_init(void)
|
|||
install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_forward_ip_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_forward_port_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -274,6 +290,11 @@ int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg)
|
|||
if (!g_cfg->bts_ip)
|
||||
fprintf(stderr, "No BTS ip address specified. This will allow everyone to connect.\n");
|
||||
|
||||
if (!g_cfg->source_addr) {
|
||||
fprintf(stderr, "You need to specify a bind address.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mgcp_endpoints_allocate(g_cfg) != 0) {
|
||||
fprintf(stderr, "Failed to allocate endpoints: %d. Quitting.\n", g_cfg->number_endpoints);
|
||||
return -1;
|
||||
|
@ -327,13 +348,3 @@ int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg)
|
|||
return !!g_cfg->forward_ip;
|
||||
}
|
||||
|
||||
struct gsm_network;
|
||||
int bsc_vty_init(struct gsm_network *dummy)
|
||||
{
|
||||
cmd_init(1);
|
||||
vty_init();
|
||||
|
||||
mgcp_vty_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue