[asterisk-dev] NCS PacketCable Patch
Jason Burton
jburton at picriverisp.net
Fri Oct 20 10:26:36 MST 2006
Skipped content of type multipart/alternative-------------- next part --------------
--- chan_mgcp.c.orig 2005-06-21 06:54:23.000000000 +0200
+++ chan_mgcp.c 2005-06-24 18:03:40.000000000 +0200
@@ -171,6 +171,8 @@
static int dtmfmode = 0;
static int nat = 0;
+static int ncs = 0;
+
/* Not used. Dosn't hurt for us to always send cid */
/* to the mgcp box. */
/*static int use_callerid = 1;*/
@@ -195,7 +197,7 @@
/* to the mgcp box. */
/*static int callwaitingcallerid = 0;*/
-/*static int hidecallerid = 0;*/
+static int hidecallerid = 0;
static int callreturn = 0;
@@ -392,6 +394,7 @@
int hidecallerid;
int dtmfmode;
int amaflags;
+ int ncs;
int type;
int slowsequence; /* MS: Sequence the endpoint as a whole */
int group;
@@ -446,7 +449,7 @@
int delme; /* SC: needed for reload */
struct mgcp_response *responses;
struct mgcp_gateway *next;
-} *gateways;
+} *gateways = NULL, *gatetemplate = NULL;
AST_MUTEX_DEFINE_STATIC(mgcp_reload_lock);
static int mgcp_reloading = 0;
@@ -965,6 +968,7 @@
{
struct mgcp_subchannel *sub = ast->tech_pvt;
struct mgcp_endpoint *p = sub->parent;
+ int unhidecallerid = 0;
if (option_debug) {
ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
@@ -1043,7 +1047,11 @@
/* SC: Decrement use count */
if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
+
+ if (p->hidecallerid) unhidecallerid = 1;
+
p->hidecallerid = 0;
+
if (p->hascallwaiting && !p->callwaiting) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on %s\n", ast->name);
@@ -1062,6 +1070,8 @@
}
transmit_notify_request(sub, "L/vmwi(-)");
}
+
+ if (unhidecallerid) p->hidecallerid = 1;
}
ast_mutex_unlock(&sub->lock);
return 0;
@@ -1344,14 +1354,14 @@
#ifdef DLINK_BUGGY_FIRMWARE
transmit_notify_request(sub, "rt");
#else
- transmit_notify_request(sub, "G/rt");
+ transmit_notify_request(sub, sub->parent->ncs ? "L/rt" : "G/rt");
#endif
break;
case AST_CONTROL_BUSY:
transmit_notify_request(sub, "L/bz");
break;
case AST_CONTROL_CONGESTION:
- transmit_notify_request(sub, "G/cg");
+ transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg");
break;
case -1:
transmit_notify_request(sub, "");
@@ -1477,7 +1487,7 @@
return "";
}
-static char *__get_header(struct mgcp_request *req, char *name, int *start)
+static char *__get_header(struct mgcp_request *req, char *name, int *start, char *def)
{
int x;
int len = strlen(name);
@@ -1493,13 +1503,19 @@
}
}
/* Don't return NULL, so get_header is always a valid pointer */
- return "";
+ return def;
}
static char *get_header(struct mgcp_request *req, char *name)
{
int start = 0;
- return __get_header(req, name, &start);
+ return __get_header(req, name, &start, "");
+}
+
+static char *get_header_default(struct mgcp_request *req, char *name, char *def)
+{
+ int start = 0;
+ return __get_header(req, name, &start, def);
}
/* SC: get comma separated value */
@@ -1524,7 +1540,50 @@
return s;
}
-static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
+static struct mgcp_gateway *clone_gateway(struct mgcp_gateway *gw, char *at)
+{
+ struct mgcp_gateway *gw_new;
+ struct mgcp_endpoint *e, *e_new;
+ struct mgcp_subchannel *sub, *sub_new;
+
+ if ((gw_new = malloc(sizeof(struct mgcp_gateway)))) {
+ memcpy(gw_new, gw, sizeof (struct mgcp_gateway));
+ strncpy(gw_new->name, at, 79);
+ gw_new->endpoints = NULL;
+ gw_new->dynamic = 1;
+ for (e = gw->endpoints; e; e = e->next) {
+ if ((e_new = malloc(sizeof(struct mgcp_endpoint)))) {
+ if (mgcpdebug)
+ ast_verbose("Cloning endpoint %s@%s\n", e_new->name, gw_new->name);
+ e_new->parent = gw_new;
+ e_new->sub = NULL;
+ e_new->next = gw_new->endpoints;
+ gw_new->endpoints = e_new;
+ for (sub = e->sub; sub; sub = sub->next) {
+ if ((sub_new = malloc(sizeof(struct mgcp_subchannel)))) {
+ memcpy(sub_new, sub, sizeof(struct mgcp_subchannel));
+ if (mgcpdebug)
+ ast_verbose("Cloning subchannel %d of endpoint %s@%s\n", sub_new->id, e_new->name, gw_new->name);
+ sub_new->parent = e_new;
+ sub_new->next = e_new->sub;
+ e_new->sub = sub_new;
+ }
+ //fix circular reference
+ if (sub->next == e->sub) {
+ while(sub_new->next){
+ sub_new = sub_new->next;
+ }
+ sub_new->next = e_new->sub;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return gw_new;
+}
+
+static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin, struct mgcp_gateway *gt)
{
struct mgcp_endpoint *p = NULL;
struct mgcp_subchannel *sub = NULL;
@@ -1624,7 +1683,7 @@
p = p->next;
}
if (sub && found) {
- ast_mutex_lock(&sub->lock);
+ ast_mutex_lock(&sub->lock);
break;
}
}
@@ -1633,10 +1692,20 @@
ast_mutex_unlock(&gatelock);
if (!sub) {
if (name) {
- if (g)
- ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
- else
- ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
+ if (g) {
+ ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
+ } else {
+ if (gt && (g = clone_gateway(gt, at))) {
+ ast_mutex_lock(&gatelock);
+ g->next = gateways;
+ gateways = g;
+ ast_mutex_unlock(&gatelock);
+ ast_log(LOG_NOTICE, "Gateway '%s' dynamically allocated\n", at);
+ return find_subchannel_and_lock(name, msgid, sin, NULL);
+ } else {
+ ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
+ }
+ }
}
}
return sub;
@@ -1901,9 +1970,11 @@
req->header[req->headers] = req->data + req->len;
/* SC: check if we need brackets around the gw name */
if (p->parent->isnamedottedip)
- snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
+// snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
+ snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : "");
else
- snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
+// snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
+ snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : "");
req->len += strlen(req->header[req->headers]);
if (req->headers < MGCP_MAX_HEADERS)
req->headers++;
@@ -2065,7 +2136,7 @@
ast_rtp_get_peer(rtp, &sub->tmpdest);
return 0;
}
- snprintf(local, sizeof(local), "p:20");
+ snprintf(local, sizeof(local), "p:20, s:off, e:on");
for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
if (p->capability & x) {
snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
@@ -2096,7 +2167,7 @@
int x;
struct mgcp_endpoint *p = sub->parent;
- snprintf(local, sizeof(local), "p:20");
+ snprintf(local, sizeof(local), "p:20, s:off, e:on");
for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
if (p->capability & x) {
snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
@@ -2139,7 +2210,7 @@
add_header(&resp, "R", "L/hd(N)");
break;
case MGCP_OFFHOOK:
- add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+ add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : (p->ncs ? "L/hu(N), L/hf(N), L/[0-9#*](N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)"));
break;
}
if (!ast_strlen_zero(tone)) {
@@ -2182,7 +2253,7 @@
add_header(&resp, "R", "L/hd(N)");
break;
case MGCP_OFFHOOK:
- add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+ add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : (p->ncs ? "L/hu(N), L/hf(N), L/[0-9#*](N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)"));
break;
}
if (!ast_strlen_zero(tone2)) {
@@ -2223,7 +2294,7 @@
add_header(&resp, "R", "L/hd(N)");
break;
case MGCP_OFFHOOK:
- add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N), L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+ add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : (p->ncs ? "L/hu(N), L/hf(N), L/[0-9#*](N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)"));
break;
}
/* SC: fill in new fields */
@@ -2401,6 +2472,10 @@
break;
}
if (sub) {
+ if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) {
+ ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result);
+ transmit_connection_del(sub);
+ }
if (sub->owner) {
ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
result, p->name, p->parent->name, sub ? sub->id:-1);
@@ -2424,6 +2499,14 @@
}
if (resp) {
+ /* responseAck: */
+ if ((req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) {
+ if ((c = get_header_default(resp, "K", NULL))) {
+ if (c == '\0') {
+ transmit_response(sub, "000", resp, "OK");
+ }
+ }
+ }
if (req->cmd == MGCP_CMD_CRCX) {
if ((c = get_header(resp, "I"))) {
if (!ast_strlen_zero(c) && sub) {
@@ -2616,6 +2699,15 @@
if (chan->cid.cid_name)
free(chan->cid.cid_name);
chan->cid.cid_name = strdup(p->cid_name);
+ } else {
+ /* SC: free existing chan->callerid */
+ if (chan->cid.cid_num)
+ free(chan->cid.cid_num);
+ chan->cid.cid_num = NULL;
+ /* SC: free existing chan->callerid */
+ if (chan->cid.cid_name)
+ free(chan->cid.cid_name);
+ chan->cid.cid_name = "private";
}
if (chan->cid.cid_ani)
free(chan->cid.cid_ani);
@@ -2632,7 +2724,7 @@
ast_log(LOG_WARNING, "PBX exited non-zero\n");
/*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
/*transmit_notify_request(p, "nbz", 1);*/
- transmit_notify_request(sub, "G/cg");
+ transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
}
return NULL;
}
@@ -2644,7 +2736,7 @@
} else if (res == 0) {
ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
/*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
- transmit_notify_request(sub, "G/cg");
+ transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
/*zt_wait_event(p->subs[index].zfd);*/
ast_hangup(chan);
return NULL;
@@ -2667,7 +2759,7 @@
if (ast_pickup_call(chan)) {
ast_log(LOG_WARNING, "No call pickup possible...\n");
/*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
- transmit_notify_request(sub, "G/cg");
+ transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
}
ast_hangup(chan);
return NULL;
@@ -2922,12 +3014,12 @@
#ifdef DLINK_BUGGY_FIRMWARE
transmit_notify_request(sub, "rt");
#else
- transmit_notify_request(sub, "G/rt");
+ transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt");
#endif
c = mgcp_new(sub, AST_STATE_RING);
if (!c) {
ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
- transmit_notify_request(sub, "G/cg");
+ transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
ast_hangup(c);
}
} else {
@@ -2977,6 +3069,7 @@
struct mgcp_gateway *g = NULL;
char iabuf[INET_ADDRSTRLEN];
int res;
+ int unhidecallerid = 0;
if (mgcpdebug) {
ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
@@ -3192,6 +3285,9 @@
}
}
if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
+
+ if (p->hidecallerid) unhidecallerid = 1;
+
p->hidecallerid = 0;
if (p->hascallwaiting && !p->callwaiting) {
if (option_verbose > 2)
@@ -3209,6 +3305,8 @@
}
transmit_notify_request(sub, "L/vmwi(-)");
}
+
+ if (unhidecallerid) p->hidecallerid = 1;
}
} else if ((strlen(ev) == 1) &&
(((ev[0] >= '0') && (ev[0] <= '9')) ||
@@ -3309,8 +3407,12 @@
}
if (sscanf(req.verb, "%d", &result) && sscanf(req.identifier, "%d", &ident)) {
+ if (result < 200) {
+ ast_log(LOG_DEBUG, "Ignoring provisional response on transaction %d\n", ident);
+ return 1;
+ }
/* Try to find who this message is for, if it's important */
- sub = find_subchannel_and_lock(NULL, ident, &sin);
+ sub = find_subchannel_and_lock(NULL, ident, &sin, gatetemplate);
if (sub) {
struct mgcp_gateway *gw = sub->parent->parent;
struct mgcp_message *cur, *prev;
@@ -3352,7 +3454,7 @@
return 1;
}
/* Process request, with iflock held */
- sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
+ sub = find_subchannel_and_lock(req.endpoint, 0, &sin, gatetemplate);
if (sub) {
/* look first to find a matching response in the queue */
if (!find_and_retrans(sub, &req))
@@ -3504,7 +3606,7 @@
ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
return NULL;
}
- sub = find_subchannel_and_lock(tmp, 0, NULL);
+ sub = find_subchannel_and_lock(tmp, 0, NULL, gatetemplate);
if (!sub) {
ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
*cause = AST_CAUSE_UNREGISTERED;
@@ -3630,6 +3732,8 @@
ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
} else if (!strcasecmp(v->name, "nat")) {
nat = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "ncs")) {
+ ncs = ast_true(v->value);
} else if (!strcasecmp(v->name, "callerid")) {
if (!strcasecmp(v->value, "asreceived")) {
cid_num[0] = '\0';
@@ -3658,6 +3762,8 @@
immediate = ast_true(v->value);
} else if (!strcasecmp(v->name, "cancallforward")) {
cancallforward = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "hidecallerid")) {
+ hidecallerid = ast_true(v->value);
} else if (!strcasecmp(v->name, "singlepath")) {
singlepath = ast_true(v->value);
} else if (!strcasecmp(v->name, "canreinvite")) {
@@ -3712,6 +3818,7 @@
strncpy(e->cid_num, cid_num, sizeof(e->cid_num) - 1);
strncpy(e->cid_name, cid_name, sizeof(e->cid_name) - 1);
strncpy(e->language, language, sizeof(e->language) - 1);
+ strncpy(e->accountcode, accountcode, sizeof(e->accountcode) - 1);
strncpy(e->musicclass, musicclass, sizeof(e->musicclass) - 1);
strncpy(e->mailbox, mailbox, sizeof(e->mailbox) - 1);
snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08x", rand());
@@ -3719,6 +3826,7 @@
e->amaflags = amaflags;
e->capability = capability;
e->parent = gw;
+ e->hidecallerid = hidecallerid;
e->dtmfmode = dtmfmode;
if (!ep_reload && e->sub && e->sub->rtp)
e->dtmfmode |= MGCP_DTMF_INBAND;
@@ -3810,6 +3918,7 @@
strncpy(e->cid_num, cid_num, sizeof(e->cid_num) - 1);
strncpy(e->cid_name, cid_name, sizeof(e->cid_name) - 1);
strncpy(e->language, language, sizeof(e->language) - 1);
+ strncpy(e->accountcode, accountcode, sizeof(e->accountcode) - 1);
strncpy(e->musicclass, musicclass, sizeof(e->musicclass) - 1);
strncpy(e->mailbox, mailbox, sizeof(e->mailbox)-1);
if (!ast_strlen_zero(mailbox)) {
@@ -3823,6 +3932,7 @@
e->amaflags = amaflags;
e->capability = capability;
e->dtmfmode = dtmfmode;
+ e->ncs = ncs;
e->adsi = adsi;
if (!strcasecmp(v->name, "trunk"))
e->type = TYPE_TRUNK;
@@ -3834,6 +3944,7 @@
e->pickupgroup=cur_pickupgroup;
e->callreturn = callreturn;
e->cancallforward = cancallforward;
+ e->hidecallerid = hidecallerid;
e->canreinvite = canreinvite;
e->singlepath = singlepath;
e->callwaiting = callwaiting;
@@ -4167,20 +4278,30 @@
cat = ast_category_browse(cfg, NULL);
while(cat) {
if (strcasecmp(cat, "general")) {
+ if (!(strcasecmp(cat, "template"))) {
+ ast_mutex_lock(&gatelock);
+ gatetemplate = build_gateway(cat, ast_variable_browse(cfg, cat));
+ if (gatetemplate) {
+ if (option_verbose > 2) {
+ ast_verbose(VERBOSE_PREFIX_3 "Added template gateway\n");
+ }
+ }
+ ast_mutex_unlock(&gatelock);
+ } else {
ast_mutex_lock(&gatelock);
g = build_gateway(cat, ast_variable_browse(cfg, cat));
if (g) {
- if (option_verbose > 2) {
- ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
- }
- g->next = gateways;
- gateways = g;
+ if (option_verbose > 2) {
+ ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
+ }
+ g->next = gateways;
+ gateways = g;
}
ast_mutex_unlock(&gatelock);
-
- /* FS: process queue and IO */
- if (monitor_thread == pthread_self()) {
- if (sched) ast_sched_runq(sched);
+ }
+ /* FS: process queue and IO */
+ if (monitor_thread == pthread_self()) {
+ if (sched) ast_sched_runq(sched);
if (io) ast_io_wait(io, 10);
}
}
More information about the asterisk-dev
mailing list