diff options
Diffstat (limited to 'channels/chan_mgcp.c')
-rwxr-xr-x | channels/chan_mgcp.c | 131 |
1 files changed, 110 insertions, 21 deletions
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index 83df5d6b7..0db0e42b2 100755 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -75,6 +75,8 @@ static char ourhost[256]; static struct in_addr __ourip; static int ourport; +static int mgcpdebug = 0; + static struct sched_context *sched; static struct io_context *io; /* The private structures of the mgcp channels are linked for @@ -141,7 +143,10 @@ struct mgcp_gateway { /* A gateway containing one or more endpoints */ char name[80]; struct sockaddr_in addr; + struct sockaddr_in defaddr; struct in_addr ourip; + int dynamic; + int expire; /* XXX Should we ever expire dynamic registrations? XXX */ struct mgcp_endpoint *endpoints; struct ast_ha *ha; struct mgcp_gateway *next; @@ -162,7 +167,10 @@ static int transmit_notify_request_with_callerid(struct mgcp_endpoint *p, char * static int __mgcp_xmit(struct mgcp_endpoint *p, char *data, int len) { int res; - res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&p->parent->addr, sizeof(struct sockaddr_in)); + if (p->parent->addr.sin_addr.s_addr) + res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&p->parent->addr, sizeof(struct sockaddr_in)); + else + res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&p->parent->defaddr, sizeof(struct sockaddr_in)); if (res != len) { ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno)); } @@ -172,7 +180,8 @@ static int __mgcp_xmit(struct mgcp_endpoint *p, char *data, int len) static int send_response(struct mgcp_endpoint *p, struct mgcp_request *req) { int res; - printf("Transmitting:\n%s\n to %s:%d\n", req->data, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); + if (mgcpdebug) + ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); res = __mgcp_xmit(p, req->data, req->len); if (res > 0) res = 0; @@ -182,7 +191,8 @@ static int send_response(struct mgcp_endpoint *p, struct mgcp_request *req) static int send_request(struct mgcp_endpoint *p, struct mgcp_request *req) { int res; - printf("XXX Need to handle Retransmitting XXX:\n%s to %s:%d\n", req->data, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); + if (mgcpdebug) + ast_verbose("XXX Need to handle Retransmitting XXX:\n%s to %s:%d\n", req->data, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); res = __mgcp_xmit(p, req->data, req->len); return res; } @@ -291,9 +301,11 @@ static struct in_addr *myaddrfor(struct in_addr *them) #endif if (((remote_ip & mask) ^ dest) == 0) { - printf("Interface is %s\n",iface); + if (mgcpdebug) + ast_verbose("Interface is %s\n",iface); temp = lookup_iface(iface); - printf("IP Address is %s\n",inet_ntoa(*temp)); + if (mgcpdebug) + ast_verbose("IP Address is %s\n",inet_ntoa(*temp)); break; } } @@ -349,7 +361,7 @@ static int mgcp_show_endpoints(int fd, int argc, char *argv[]) g = gateways; while(g) { e = g->endpoints; - ast_cli(fd, "Gateway '%s' at %s\n", g->name, inet_ntoa(g->addr.sin_addr)); + ast_cli(fd, "Gateway '%s' at %s (%s)\n", g->name, g->addr.sin_addr.s_addr ? inet_ntoa(g->addr.sin_addr) : inet_ntoa(g->defaddr.sin_addr), g->dynamic ? "Dynamic" : "Static"); while(e) { ast_cli(fd, " -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->owner ? "active" : "idle"); hasendpoints = 1; @@ -634,8 +646,18 @@ static struct mgcp_endpoint *find_endpoint(char *name, int msgid, struct sockadd ast_pthread_mutex_lock(&gatelock); g = gateways; while(g) { - if (!name || !strcasecmp(g->name, at)) { - /* Found the gateway -- now for the endpoint */ + if ((!name || !strcasecmp(g->name, at)) && + (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) { + /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */ + if (sin && g->dynamic) { + if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || + (g->addr.sin_port != sin->sin_port)) { + memcpy(&g->addr, sin, sizeof(g->addr)); + memcpy(&g->ourip, myaddrfor(&g->addr.sin_addr), sizeof(g->ourip)); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Registered MGCP gateway '%s' at %s port %d\n", g->name, inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port)); + } + } p = g->endpoints; while(p) { if ((name && !strcasecmp(p->name, tmp)) || @@ -753,9 +775,11 @@ static void parse(struct mgcp_request *req) } } - printf("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n", + if (mgcpdebug) { + ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n", req->verb, req->identifier, req->endpoint, req->version); - printf("%d headers, %d lines\n", req->headers, req->lines); + ast_verbose("%d headers, %d lines\n", req->headers, req->lines); + } if (*c) ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c); } @@ -817,7 +841,8 @@ static int process_sdp(struct mgcp_endpoint *p, struct mgcp_request *req) codecs += len; } p->capability = capability & peercapability; - printf("Capabilities: us - %d, them - %d, combined - %d\n", + if (mgcpdebug) + ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n", capability, peercapability, p->capability); if (!p->capability) { ast_log(LOG_WARNING, "No compatible codecs!\n"); @@ -966,7 +991,8 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_endpoint *p, struct as dest.sin_port = sin.sin_port; } } - printf("We're at %s port %d\n", inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); + if (mgcpdebug) + ast_verbose("We're at %s port %d\n", inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); snprintf(v, sizeof(v), "v=0\r\n"); snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), inet_ntoa(dest.sin_addr)); snprintf(s, sizeof(s), "s=session\r\n"); @@ -975,7 +1001,8 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_endpoint *p, struct as snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) { if (p->capability & x) { - printf("Answering with capability %d\n", x); + if (mgcpdebug) + ast_verbose("Answering with capability %d\n", x); if ((codec = ast2rtp(x)) > -1) { snprintf(costr, sizeof(costr), " %d", codec); strcat(m, costr); @@ -1192,7 +1219,8 @@ static int handle_request(struct mgcp_endpoint *p, struct mgcp_request *req, str struct ast_channel *c; pthread_t t; struct ast_frame f = { 0, }; - printf("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name); + if (mgcpdebug) + ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name); /* Clear out potential response */ if (!strcasecmp(req->verb, "RSIP")) { if (option_verbose > 2) @@ -1282,7 +1310,8 @@ static int mgcpsock_read(int *id, int fd, short events, void *ignore) } req.data[res] = '\0'; req.len = res; - printf("MGCP read: \n%s\n", req.data); + if (mgcpdebug) + ast_verbose("MGCP read: \n%s\nfrom %s:%d", req.data, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); parse(&req); if (req.headers < 1) { /* Must have at least one header */ @@ -1431,6 +1460,7 @@ static struct ast_channel *mgcp_request(char *type, int format, void *data) ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp); return NULL; } + /* Must be busy */ if (p->owner) return NULL; @@ -1453,10 +1483,32 @@ struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) gw = malloc(sizeof(struct mgcp_gateway)); if (gw) { memset(gw, 0, sizeof(struct mgcp_gateway)); + gw->expire = -1; strncpy(gw->name, cat, sizeof(gw->name) - 1); while(v) { if (!strcasecmp(v->name, "host")) { - if (ast_get_ip(&gw->addr, v->value)) { + if (!strcasecmp(v->value, "dynamic")) { + /* They'll register with us */ + gw->dynamic = 1; + memset(&gw->addr.sin_addr, 0, 4); + if (gw->addr.sin_port) { + /* If we've already got a port, make it the default rather than absolute */ + gw->defaddr.sin_port = gw->addr.sin_port; + gw->addr.sin_port = 0; + } + } else { + /* Non-dynamic. Make sure we become that way if we're not */ + if (gw->expire > -1) + ast_sched_del(sched, gw->expire); + gw->expire = -1; + gw->dynamic = 0; + if (ast_get_ip(&gw->addr, v->value)) { + free(gw); + return NULL; + } + } + } else if (!strcasecmp(v->name, "defaultip")) { + if (ast_get_ip(&gw->defaddr, v->value)) { free(gw); return NULL; } @@ -1503,14 +1555,17 @@ struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) } } - if (!ntohl(gw->addr.sin_addr.s_addr)) { - ast_log(LOG_WARNING, "Gateway '%s' lacks IP address\n", gw->name); + if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) { + ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name); free(gw); - gw = NULL; - } else if (!ntohs(gw->addr.sin_port)) { + return NULL; + } + if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) + gw->defaddr.sin_port = htons(DEFAULT_MGCP_PORT); + if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) gw->addr.sin_port = htons(DEFAULT_MGCP_PORT); + if (gw->addr.sin_addr.s_addr) memcpy(&gw->ourip, myaddrfor(&gw->addr.sin_addr), sizeof(gw->ourip)); - } return gw; } @@ -1539,6 +1594,38 @@ static struct ast_rtp_protocol mgcp_rtp = { set_rtp_peer: mgcp_set_rtp_peer, }; +static int mgcp_do_debug(int fd, int argc, char *argv[]) +{ + if (argc != 2) + return RESULT_SHOWUSAGE; + mgcpdebug = 1; + ast_cli(fd, "MGCP Debugging Enabled\n"); + return RESULT_SUCCESS; +} + +static int mgcp_no_debug(int fd, int argc, char *argv[]) +{ + if (argc != 3) + return RESULT_SHOWUSAGE; + mgcpdebug = 0; + ast_cli(fd, "MGCP Debugging Disabled\n"); + return RESULT_SUCCESS; +} + +static char debug_usage[] = +"Usage: mgcp debug\n" +" Enables dumping of MGCP packets for debugging purposes\n"; + +static char no_debug_usage[] = +"Usage: mgcp no debug\n" +" Disables dumping of MGCP packets for debugging purposes\n"; + +static struct ast_cli_entry cli_debug = + { { "mgcp", "debug", NULL }, mgcp_do_debug, "Enable MGCP debugging", debug_usage }; +static struct ast_cli_entry cli_no_debug = + { { "mgcp", "no", "debug", NULL }, mgcp_no_debug, "Disable MGCP debugging", no_debug_usage }; + + int load_module() { struct ast_config *cfg; @@ -1649,6 +1736,8 @@ int load_module() mgcp_rtp.type = type; ast_rtp_proto_register(&mgcp_rtp); ast_cli_register(&cli_show_endpoints); + ast_cli_register(&cli_debug); + ast_cli_register(&cli_no_debug); /* And start the monitor for the first time */ restart_monitor(); return 0; |