diff options
Diffstat (limited to 'src/libmgcp')
-rw-r--r-- | src/libmgcp/mgcp_protocol.c | 44 | ||||
-rw-r--r-- | src/libmgcp/mgcpgw_client.c | 95 | ||||
-rw-r--r-- | src/libmgcp/mgcpgw_client_vty.c | 51 |
3 files changed, 175 insertions, 15 deletions
diff --git a/src/libmgcp/mgcp_protocol.c b/src/libmgcp/mgcp_protocol.c index 96542c5a0..c8b6e8660 100644 --- a/src/libmgcp/mgcp_protocol.c +++ b/src/libmgcp/mgcp_protocol.c @@ -66,6 +66,45 @@ static int setup_rtp_processing(struct mgcp_endpoint *endp); static int mgcp_analyze_header(struct mgcp_parse_data *parse, char *data); +/* Display an mgcp message on the log output */ +void display_mgcp_message(unsigned char *message, unsigned int len, + char *preamble) +{ + unsigned char line[80]; + unsigned char *ptr; + unsigned int consumed = 0; + unsigned int consumed_line = 0; + unsigned int line_count = 0; + + if (!log_check_level(DMGCP, LOGL_DEBUG)) + return; + + while (1) { + memset(line, 0, sizeof(line)); + ptr = line; + consumed_line = 0; + do { + if (*message != '\n' && *message != '\r') { + *ptr = *message; + ptr++; + } + message++; + consumed++; + consumed_line++; + } while (*message != '\n' && consumed < len + && consumed_line < sizeof(line)); + + if (strlen((const char *)line)) { + LOGP(DMGCP, LOGL_DEBUG, "%s: line #%02u: %s\n", + preamble, line_count, line); + line_count++; + } + + if (consumed >= len) + return; + } +} + static int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line) { const size_t line_len = strlen(line); @@ -157,7 +196,8 @@ static struct msgb *create_resp(struct mgcp_endpoint *endp, int code, } res->l2h = msgb_put(res, len); - LOGP(DMGCP, LOGL_DEBUG, "Generated response: code: %d for '%s'\n", code, res->l2h); + LOGP(DMGCP, LOGL_DEBUG, "Generated response: code=%d\n", code); + display_mgcp_message(res->l2h, msgb_l2len(res), "Generated response"); /* * Remember the last transmission per endpoint. @@ -329,6 +369,8 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg) if (mgcp_msg_terminate_nul(msg)) return NULL; + display_mgcp_message(msg->l2h, msgb_l2len(msg), "Received message"); + /* attempt to treat it as a response */ if (sscanf((const char *)&msg->l2h[0], "%3d %*s", &code) == 1) { LOGP(DMGCP, LOGL_DEBUG, "Response: Code: %d\n", code); diff --git a/src/libmgcp/mgcpgw_client.c b/src/libmgcp/mgcpgw_client.c index 9f0c84de2..1910a9f35 100644 --- a/src/libmgcp/mgcpgw_client.c +++ b/src/libmgcp/mgcpgw_client.c @@ -35,15 +35,6 @@ #include <unistd.h> #include <string.h> -struct mgcpgw_client { - struct mgcpgw_client_conf actual; - uint32_t remote_addr; - struct osmo_wqueue wq; - mgcp_trans_id_t next_trans_id; - uint16_t next_endpoint; - struct llist_head responses_pending; -}; - void mgcpgw_client_conf_init(struct mgcpgw_client_conf *conf) { /* NULL and -1 default to MGCPGW_CLIENT_*_DEFAULT values */ @@ -52,12 +43,68 @@ void mgcpgw_client_conf_init(struct mgcpgw_client_conf *conf) .local_port = -1, .remote_addr = NULL, .remote_port = -1, + .first_endpoint = 0, + .last_endpoint = 0, + .bts_base = 0, }; } -unsigned int mgcpgw_client_next_endpoint(struct mgcpgw_client *client) +/* Test if a given endpoint id is currently in use */ +static bool endpoint_in_use(uint16_t id, struct mgcpgw_client *client) { - return client->next_endpoint ++; + struct mgcp_inuse_endpoint *endpoint; + llist_for_each_entry(endpoint, &client->inuse_endpoints, entry) { + if (endpoint->id == id) + return true; + } + + return false; +} + +/* Find and seize an unsused endpoint id */ +int mgcpgw_client_next_endpoint(struct mgcpgw_client *client) +{ + int i; + uint16_t first_endpoint = client->actual.first_endpoint; + uint16_t last_endpoint = client->actual.last_endpoint; + struct mgcp_inuse_endpoint *endpoint; + + /* Use the maximum permitted range if the VTY + * configuration does not specify a range */ + if (client->actual.last_endpoint == 0) { + first_endpoint = 1; + last_endpoint = 65534; + } + + /* Test the permitted endpoint range for an endpoint + * number that is not in use. When a suitable endpoint + * number can be found, seize it by adding it to the + * inuse list. */ + for (i=first_endpoint;i<last_endpoint;i++) + { + if (endpoint_in_use(i,client) == false) { + endpoint = talloc_zero(client, struct mgcp_inuse_endpoint); + endpoint->id = i; + llist_add_tail(&endpoint->entry, &client->inuse_endpoints); + return endpoint->id; + } + } + + /* All endpoints are busy! */ + return -EINVAL; +} + +/* Release a seized endpoint id to make it available again for other calls */ +void mgcpgw_client_release_endpoint(uint16_t id, struct mgcpgw_client *client) +{ + struct mgcp_inuse_endpoint *endpoint; + struct mgcp_inuse_endpoint *endpoint_tmp; + llist_for_each_entry_safe(endpoint, endpoint_tmp, &client->inuse_endpoints, entry) { + if (endpoint->id == id) { + llist_del(&endpoint->entry); + talloc_free(endpoint); + } + } } static void mgcpgw_client_handle_response(struct mgcpgw_client *mgcp, @@ -257,9 +304,16 @@ static int mgcp_do_write(struct osmo_fd *fd, struct msgb *msg) { int ret; static char strbuf[4096]; - unsigned int l = msg->len < sizeof(strbuf)-1 ? msg->len : sizeof(strbuf)-1; + unsigned int l = msg->len < sizeof(strbuf) ? msg->len : sizeof(strbuf); + unsigned int i; + strncpy(strbuf, (const char*)msg->data, l); - strbuf[l] = '\0'; + for (i = 0; i < sizeof(strbuf); i++) { + if (strbuf[i] == '\n' || strbuf[i] == '\r') { + strbuf[i] = '\0'; + break; + } + } DEBUGP(DMGCP, "Tx MGCP msg to MGCP GW: '%s'\n", strbuf); LOGP(DMGCP, LOGL_DEBUG, "Sending msg to MGCP GW size: %u\n", msg->len); @@ -280,9 +334,9 @@ struct mgcpgw_client *mgcpgw_client_init(void *ctx, mgcp = talloc_zero(ctx, struct mgcpgw_client); INIT_LLIST_HEAD(&mgcp->responses_pending); + INIT_LLIST_HEAD(&mgcp->inuse_endpoints); mgcp->next_trans_id = 1; - mgcp->next_endpoint = 1; mgcp->actual.local_addr = conf->local_addr ? conf->local_addr : MGCPGW_CLIENT_LOCAL_ADDR_DEFAULT; @@ -294,6 +348,10 @@ struct mgcpgw_client *mgcpgw_client_init(void *ctx, mgcp->actual.remote_port = conf->remote_port >= 0 ? (uint16_t)conf->remote_port : MGCPGW_CLIENT_REMOTE_PORT_DEFAULT; + mgcp->actual.first_endpoint = conf->first_endpoint > 0 ? (uint16_t)conf->first_endpoint : 0; + mgcp->actual.last_endpoint = conf->last_endpoint > 0 ? (uint16_t)conf->last_endpoint : 0; + mgcp->actual.bts_base = conf->bts_base > 0 ? (uint16_t)conf->bts_base : 4000; + return mgcp; } @@ -547,3 +605,12 @@ struct msgb *mgcp_msg_mdcx(struct mgcpgw_client *mgcp, rtp_conn_addr, rtp_port); } + +struct msgb *mgcp_msg_dlcx(struct mgcpgw_client *mgcp, uint16_t rtp_endpoint, + unsigned int call_id) +{ + mgcp_trans_id_t trans_id = mgcpgw_client_next_trans_id(mgcp); + return mgcp_msg_from_str(trans_id, + "DLCX %u %x@mgw MGCP 1.0\r\n" + "C: %x\r\n", trans_id, rtp_endpoint, call_id); +} diff --git a/src/libmgcp/mgcpgw_client_vty.c b/src/libmgcp/mgcpgw_client_vty.c index a42ee4e5d..806800078 100644 --- a/src/libmgcp/mgcpgw_client_vty.c +++ b/src/libmgcp/mgcpgw_client_vty.c @@ -79,10 +79,46 @@ DEFUN(cfg_mgcpgw_remote_port, cfg_mgcpgw_remote_port_cmd, return CMD_SUCCESS; } +DEFUN(cfg_mgcpgw_endpoint_range, cfg_mgcpgw_endpoint_range_cmd, + "mgcpgw endpoint-range <1-65534> <1-65534>", + MGCPGW_STR "usable range of endpoint identifiers\n" + "set first useable endpoint identifier\n" + "set the last useable endpoint identifier\n") +{ + uint16_t first_endpoint = atoi(argv[0]); + uint16_t last_endpoint = atoi(argv[1]); + + if (last_endpoint < first_endpoint) { + vty_out(vty, "last endpoint must be greater than first endpoint!%s", + VTY_NEWLINE); + return CMD_SUCCESS; + } + + global_mgcpgw_client_conf->first_endpoint = first_endpoint; + global_mgcpgw_client_conf->last_endpoint = last_endpoint; + return CMD_SUCCESS; +} + +#define BTS_START_STR "First UDP port allocated for the BTS side\n" +#define UDP_PORT_STR "UDP Port number\n" +DEFUN(cfg_mgcp_rtp_bts_base_port, + cfg_mgcp_rtp_bts_base_port_cmd, + "mgcpgw bts-base <0-65534>", + MGCPGW_STR + BTS_START_STR + UDP_PORT_STR) +{ + global_mgcpgw_client_conf->bts_base = atoi(argv[0]); + return CMD_SUCCESS; +} + int mgcpgw_client_config_write(struct vty *vty, const char *indent) { const char *addr; int port; + uint16_t first_endpoint; + uint16_t last_endpoint; + uint16_t bts_base; addr = global_mgcpgw_client_conf->local_addr; if (addr) @@ -102,6 +138,19 @@ int mgcpgw_client_config_write(struct vty *vty, const char *indent) vty_out(vty, "%smgcpgw remote-port %u%s", indent, (uint16_t)port, VTY_NEWLINE); + first_endpoint = global_mgcpgw_client_conf->first_endpoint; + last_endpoint = global_mgcpgw_client_conf->last_endpoint; + if (last_endpoint != 0) { + vty_out(vty, "%smgcpgw endpoint-range %u %u%s", indent, + first_endpoint, last_endpoint, VTY_NEWLINE); + } + + bts_base = global_mgcpgw_client_conf->bts_base; + if (bts_base) { + vty_out(vty, "%smgcpgw bts-base %u%s", indent, + bts_base, VTY_NEWLINE); + } + return CMD_SUCCESS; } @@ -113,4 +162,6 @@ void mgcpgw_client_vty_init(int node, struct mgcpgw_client_conf *conf) install_element(node, &cfg_mgcpgw_local_port_cmd); install_element(node, &cfg_mgcpgw_remote_ip_cmd); install_element(node, &cfg_mgcpgw_remote_port_cmd); + install_element(node, &cfg_mgcpgw_endpoint_range_cmd); + install_element(node, &cfg_mgcp_rtp_bts_base_port_cmd); } |