aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authormmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2009-04-03 22:41:46 +0000
committermmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2009-04-03 22:41:46 +0000
commitf00656db9ebcc7db98c0e3a3abf9a83791d8bcdb (patch)
tree2e466f746a2e29094d6dcc3c6f2577f4dd85f4c0 /channels
parent531f260b1278edd05dcabd04422b6a072e75f821 (diff)
This commit introduces COLP/CONP and Redirecting party information into Asterisk.
The channel drivers which have been most heavily tested with these enhancements are chan_sip and chan_misdn. Further work is being done to add Q.SIG support and will be introduced in a later commit. chan_skinny has code added to it here, but according to user pj, the support on chan_skinny is not working as of now. This will be fixed in a later commit. A special thanks goes out to bugtracker user gareth for getting the ball rolling and providing the initial support for this work. Without his initial work on this, this would not have been nearly as painless as it was. This functionality has been tested by Digium's product quality department, as well as a customer site running thousands of calls every day. In addition, many many many many bugtracker users have tested this, too. (closes issue #8824) Reported by: gareth Review: http://reviewboard.digium.com/r/201 git-svn-id: http://svn.digium.com/svn/asterisk/trunk@186525 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_agent.c3
-rw-r--r--channels/chan_dahdi.c32
-rw-r--r--channels/chan_h323.c12
-rw-r--r--channels/chan_iax2.c108
-rw-r--r--channels/chan_local.c75
-rw-r--r--channels/chan_mgcp.c2
-rw-r--r--channels/chan_misdn.c1553
-rw-r--r--channels/chan_phone.c8
-rw-r--r--channels/chan_sip.c1111
-rw-r--r--channels/chan_skinny.c54
-rw-r--r--channels/chan_unistim.c12
-rw-r--r--channels/misdn/chan_misdn_config.h10
-rw-r--r--channels/misdn/isdn_lib.c196
-rw-r--r--channels/misdn/isdn_lib.h202
-rw-r--r--channels/misdn/isdn_lib_intern.h1
-rw-r--r--channels/misdn/isdn_msg_parser.c395
-rw-r--r--channels/misdn_config.c113
17 files changed, 2813 insertions, 1074 deletions
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index b15f7a04e..818f61935 100644
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -757,8 +757,7 @@ static int agent_call(struct ast_channel *ast, char *dest, int timeout)
time(&p->start);
/* Call on this agent */
ast_verb(3, "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name);
- ast_set_callerid(p->chan,
- ast->cid.cid_num, ast->cid.cid_name, NULL);
+ ast_channel_set_connected_line(p->chan, &ast->connected);
ast_channel_inherit_variables(ast, p->chan);
res = ast_call(p->chan, p->loginchan, 0);
CLEANUP(ast,p);
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index f520e32f7..f6d3fb9ad 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -3156,7 +3156,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
}
p->callwaitcas = 0;
if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
- p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
+ p->cidlen = ast_callerid_generate(p->cidspill, ast->connected.id.name, ast->connected.id.number, AST_LAW(p));
p->cidpos = 0;
send_callerid(p);
}
@@ -3197,12 +3197,12 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
} else {
/* Call waiting call */
p->callwaitrings = 0;
- if (ast->cid.cid_num)
- ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
+ if (ast->connected.id.number)
+ ast_copy_string(p->callwait_num, ast->connected.id.number, sizeof(p->callwait_num));
else
p->callwait_num[0] = '\0';
- if (ast->cid.cid_name)
- ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
+ if (ast->connected.id.name)
+ ast_copy_string(p->callwait_name, ast->connected.id.name, sizeof(p->callwait_name));
else
p->callwait_name[0] = '\0';
/* Call waiting tone instead */
@@ -3214,8 +3214,8 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
}
- n = ast->cid.cid_name;
- l = ast->cid.cid_num;
+ n = ast->connected.id.name;
+ l = ast->connected.id.number;
if (l)
ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
else
@@ -3281,14 +3281,14 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
switch (mysig) {
case SIG_FEATD:
- l = ast->cid.cid_num;
+ l = ast->connected.id.number;
if (l)
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
else
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
break;
case SIG_FEATDMF:
- l = ast->cid.cid_num;
+ l = ast->connected.id.number;
if (l)
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
else
@@ -3423,7 +3423,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
}
if (!p->hidecallerid) {
- l = ast->cid.cid_num;
+ l = ast->connected.id.number;
} else {
l = NULL;
}
@@ -3472,10 +3472,10 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
}
}
isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
- p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
- p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
+ p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number_presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
+ p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number_presentation) : SS7_SCREENING_USER_PROVIDED );
- isup_set_oli(p->ss7call, ast->cid.cid_ani2);
+ isup_set_oli(p->ss7call, ast->connected.ani2);
isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
ast_channel_lock(ast);
@@ -3587,9 +3587,9 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
l = NULL;
n = NULL;
if (!p->hidecallerid) {
- l = ast->cid.cid_num;
+ l = ast->connected.id.number;
if (!p->hidecalleridname) {
- n = ast->cid.cid_name;
+ n = ast->connected.id.name;
}
}
@@ -3803,7 +3803,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
}
}
pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
- p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
+ p->use_callingpres ? ast->connected.id.number_presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
if (!strcasecmp(rr_str, "UNKNOWN"))
redirect_reason = 0;
diff --git a/channels/chan_h323.c b/channels/chan_h323.c
index c3e074d14..0445497b4 100644
--- a/channels/chan_h323.c
+++ b/channels/chan_h323.c
@@ -606,18 +606,18 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
/* make sure null terminated */
called_addr[sizeof(called_addr) - 1] = '\0';
- if (c->cid.cid_num)
- ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));
+ if (c->connected.id.number)
+ ast_copy_string(pvt->options.cid_num, c->connected.id.number, sizeof(pvt->options.cid_num));
- if (c->cid.cid_name)
- ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
+ if (c->connected.id.name)
+ ast_copy_string(pvt->options.cid_name, c->connected.id.name, sizeof(pvt->options.cid_name));
if (c->cid.cid_rdnis) {
ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));
}
- pvt->options.presentation = c->cid.cid_pres;
- pvt->options.type_of_number = c->cid.cid_ton;
+ pvt->options.presentation = c->connected.id.number_presentation;
+ pvt->options.type_of_number = c->connected.id.number_type;
if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
if (!strcasecmp(addr, "UNKNOWN"))
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 860e1d614..d594498f6 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -380,7 +380,9 @@ enum iax2_flags {
them before sending voice or anything else*/
IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */
IAX_IMMEDIATE = (1 << 27), /*!< Allow immediate off-hook to extension s */
- IAX_FORCE_ENCRYPT = (1 << 28), /*!< Forces call encryption, if encryption not possible hangup */
+ IAX_SENDCONNECTEDLINE = (1 << 28), /*!< Allow sending of connected line updates */
+ IAX_RECVCONNECTEDLINE = (1 << 29), /*!< Allow receiving of connected line updates */
+ IAX_FORCE_ENCRYPT = (1 << 30), /*!< Forces call encryption, if encryption not possible hangup */
};
static int global_rtautoclear = 120;
@@ -1976,7 +1978,7 @@ static int __find_callno(unsigned short callno, unsigned short dcallno, struct s
iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
iaxs[x]->amaflags = amaflags;
- ast_copy_flags(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_FORCE_ENCRYPT);
+ ast_copy_flags(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
ast_string_field_set(iaxs[x], accountcode, accountcode);
ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
@@ -3601,6 +3603,8 @@ struct create_addr_info {
char outkey[80];
char timezone[80];
char prefs[32];
+ char cid_num[80];
+ char cid_name[80];
char context[AST_MAX_CONTEXT];
char peercontext[AST_MAX_CONTEXT];
char mohinterpret[MAX_MUSICCLASS];
@@ -3644,7 +3648,7 @@ static int create_addr(const char *peername, struct ast_channel *c, struct socka
if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
goto return_unref;
- ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_FORCE_ENCRYPT);
+ ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
cai->maxtime = peer->maxms;
cai->capability = peer->capability;
cai->encmethods = peer->encmethods;
@@ -3662,6 +3666,8 @@ static int create_addr(const char *peername, struct ast_channel *c, struct socka
ast_copy_string(cai->username, peer->username, sizeof(cai->username));
ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
+ ast_copy_string(cai->cid_num, peer->cid_num, sizeof(cai->cid_num));
+ ast_copy_string(cai->cid_name, peer->cid_name, sizeof(cai->cid_name));
ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
if (ast_strlen_zero(peer->dbsecret)) {
@@ -3870,8 +3876,8 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
if (pds.port)
sin.sin_port = htons(atoi(pds.port));
- l = c->cid.cid_num;
- n = c->cid.cid_name;
+ l = c->connected.id.number;
+ n = c->connected.id.name;
/* Now build request */
memset(&ied, 0, sizeof(ied));
@@ -3888,21 +3894,21 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
if (l) {
iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
- iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
+ iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->connected.id.number_presentation);
} else {
if (n)
- iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
+ iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->connected.id.number_presentation);
else
iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
}
- iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
+ iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->connected.id.number_type);
iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
if (n)
iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
- if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
- iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
+ if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->connected.ani)
+ iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->connected.ani);
if (!ast_strlen_zero(c->language))
iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
@@ -4398,6 +4404,11 @@ static int iax2_indicate(struct ast_channel *c, int condition, const void *data,
ast_moh_stop(c);
goto done;
}
+ break;
+ case AST_CONTROL_CONNECTED_LINE:
+ if (!ast_test_flag(pvt, IAX_SENDCONNECTEDLINE))
+ goto done;
+ break;
}
res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
@@ -6381,7 +6392,7 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies
iaxs[callno]->amaflags = user->amaflags;
if (!ast_strlen_zero(user->language))
ast_string_field_set(iaxs[callno], language, user->language);
- ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
+ ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
/* Keep this check last */
if (!ast_strlen_zero(user->dbsecret)) {
char *family, *key=NULL;
@@ -9954,6 +9965,31 @@ immediatedial:
ast_mutex_unlock(&iaxsl[fr->callno]);
return 1;
}
+ /* Don't allow connected line updates unless we are configured to */
+ if (f.frametype == AST_FRAME_CONTROL && f.subclass == AST_CONTROL_CONNECTED_LINE) {
+ struct ast_party_connected_line connected;
+
+ if (!ast_test_flag(iaxs[fr->callno], IAX_RECVCONNECTEDLINE)) {
+ ast_mutex_unlock(&iaxsl[fr->callno]);
+ return 1;
+ }
+
+ /* Initialize defaults */
+ ast_party_connected_line_init(&connected);
+ connected.id.number_presentation = iaxs[fr->callno]->calling_pres;
+
+ if (!ast_connected_line_parse_data(f.data.ptr, f.datalen, &connected)) {
+ ast_string_field_set(iaxs[fr->callno], cid_num, connected.id.number);
+ ast_string_field_set(iaxs[fr->callno], cid_name, connected.id.name);
+ iaxs[fr->callno]->calling_pres = connected.id.number_presentation;
+
+ if (iaxs[fr->callno]->owner) {
+ ast_set_callerid(iaxs[fr->callno]->owner, S_OR(connected.id.number, ""), S_OR(connected.id.name, ""), NULL);
+ iaxs[fr->callno]->owner->cid.cid_pres = connected.id.number_presentation;
+ }
+ }
+ ast_party_connected_line_free(&connected);
+ }
/* Common things */
f.src = "IAX2";
f.mallocd = 0;
@@ -10449,7 +10485,7 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data
memset(&cai, 0, sizeof(cai));
cai.capability = iax2_capability;
- ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
+ ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
/* Populate our address from the given */
if (create_addr(pds.peer, NULL, &sin, &cai)) {
@@ -10468,7 +10504,7 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data
}
/* If this is a trunk, update it now */
- ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
+ ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
if (ast_test_flag(&cai, IAX_TRUNK)) {
int new_callno;
if ((new_callno = make_trunk(callno, 1)) != -1)
@@ -10731,7 +10767,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
if (peer) {
if (firstpass) {
- ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_FORCE_ENCRYPT);
+ ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
peer->encmethods = iax2_encryption;
peer->adsi = adsi;
ast_string_field_set(peer,secret,"");
@@ -10904,6 +10940,18 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
ast_string_field_set(peer, zonetag, v->value);
} else if (!strcasecmp(v->name, "adsi")) {
peer->adsi = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "connectedline")) {
+ if (ast_true(v->value)) {
+ ast_set_flag(peer, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ } else if (!strcasecmp(v->value, "send")) {
+ ast_clear_flag(peer, IAX_RECVCONNECTEDLINE);
+ ast_set_flag(peer, IAX_SENDCONNECTEDLINE);
+ } else if (!strcasecmp(v->value, "receive")) {
+ ast_clear_flag(peer, IAX_SENDCONNECTEDLINE);
+ ast_set_flag(peer, IAX_RECVCONNECTEDLINE);
+ } else {
+ ast_clear_flag(peer, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ }
}/* else if (strcasecmp(v->name,"type")) */
/* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
v = v->next;
@@ -11002,7 +11050,7 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st
user->adsi = adsi;
ast_string_field_set(user, name, name);
ast_string_field_set(user, language, language);
- ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_FORCE_ENCRYPT);
+ ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
ast_clear_flag(user, IAX_HASCALLERID);
ast_string_field_set(user, cid_name, "");
ast_string_field_set(user, cid_num, "");
@@ -11147,6 +11195,18 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st
user->maxauthreq = 0;
} else if (!strcasecmp(v->name, "adsi")) {
user->adsi = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "connectedline")) {
+ if (ast_true(v->value)) {
+ ast_set_flag(user, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ } else if (!strcasecmp(v->value, "send")) {
+ ast_clear_flag(user, IAX_RECVCONNECTEDLINE);
+ ast_set_flag(user, IAX_SENDCONNECTEDLINE);
+ } else if (!strcasecmp(v->value, "receive")) {
+ ast_clear_flag(user, IAX_SENDCONNECTEDLINE);
+ ast_set_flag(user, IAX_RECVCONNECTEDLINE);
+ } else {
+ ast_clear_flag(user, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ }
}/* else if (strcasecmp(v->name,"type")) */
/* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
v = v->next;
@@ -11262,10 +11322,8 @@ static void set_config_destroy(void)
trunkmaxsize = MAX_TRUNKDATA;
amaflags = 0;
delayreject = 0;
- ast_clear_flag((&globalflags), IAX_NOTRANSFER);
- ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA);
- ast_clear_flag((&globalflags), IAX_USEJITTERBUF);
- ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);
+ ast_clear_flag((&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF |
+ IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
delete_users();
}
@@ -11569,6 +11627,18 @@ static int set_config(char *config_file, int reload)
adsi = ast_true(v->value);
} else if (!strcasecmp(v->name, "srvlookup")) {
srvlookup = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "connectedline")) {
+ if (ast_true(v->value)) {
+ ast_set_flag((&globalflags), IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ } else if (!strcasecmp(v->value, "send")) {
+ ast_clear_flag((&globalflags), IAX_RECVCONNECTEDLINE);
+ ast_set_flag((&globalflags), IAX_SENDCONNECTEDLINE);
+ } else if (!strcasecmp(v->value, "receive")) {
+ ast_clear_flag((&globalflags), IAX_SENDCONNECTEDLINE);
+ ast_set_flag((&globalflags), IAX_RECVCONNECTEDLINE);
+ } else {
+ ast_clear_flag((&globalflags), IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ }
} /*else if (strcasecmp(v->name,"type")) */
/* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
v = v->next;
diff --git a/channels/chan_local.c b/channels/chan_local.c
index e426e10fa..509e69b10 100644
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -406,6 +406,37 @@ static int local_indicate(struct ast_channel *ast, int condition, const void *da
ast_moh_start(ast, data, NULL);
} else if (condition == AST_CONTROL_UNHOLD) {
ast_moh_stop(ast);
+ } else if (condition == AST_CONTROL_CONNECTED_LINE || condition == AST_CONTROL_REDIRECTING) {
+ struct ast_channel *this_channel;
+ struct ast_channel *the_other_channel;
+ /* A connected line update frame may only contain a partial amount of data, such
+ * as just a source, or just a ton, and not the full amount of information. However,
+ * the collected information is all stored in the outgoing channel's connectedline
+ * structure, so when receiving a connected line update on an outgoing local channel,
+ * we need to transmit the collected connected line information instead of whatever
+ * happens to be in this control frame. The same applies for redirecting information, which
+ * is why it is handled here as well.*/
+ isoutbound = IS_OUTBOUND(ast, p);
+ if (isoutbound) {
+ this_channel = p->chan;
+ the_other_channel = p->owner;
+ } else {
+ this_channel = p->owner;
+ the_other_channel = p->chan;
+ }
+ if (the_other_channel) {
+ unsigned char frame_data[1024];
+ if (condition == AST_CONTROL_CONNECTED_LINE) {
+ f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data), &this_channel->connected);
+ } else {
+ f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data), &this_channel->redirecting);
+ }
+ f.subclass = condition;
+ f.data.ptr = frame_data;
+ if (!(res = local_queue_frame(p, isoutbound, &f, ast, 1))) {
+ ast_mutex_unlock(&p->lock);
+ }
+ }
} else {
/* Queue up a frame representing the indication as a control frame */
ast_mutex_lock(&p->lock);
@@ -509,22 +540,45 @@ static int local_call(struct ast_channel *ast, char *dest, int timeout)
if (!p)
return -1;
-
- ast_mutex_lock(&p->lock);
+
+ /* If you value your sanity, please don't look at this code */
+start_over:
+ while (ast_channel_trylock(p->chan)) {
+ ast_channel_unlock(p->owner);
+ usleep(1);
+ ast_channel_lock(p->owner);
+ }
+
+ /* p->owner and p->chan are locked now. Let's get p locked */
+ if (ast_mutex_trylock(&p->lock)) {
+ /* @#$&$@ */
+ ast_channel_unlock(p->chan);
+ ast_channel_unlock(p->owner);
+ usleep(1);
+ ast_channel_lock(p->owner);
+ goto start_over;
+ }
/*
* Note that cid_num and cid_name aren't passed in the ast_channel_alloc
* call, so it's done here instead.
+ *
+ * All these failure points just return -1. The individual strings will
+ * be cleared when we destroy the channel.
*/
- p->chan->cid.cid_dnid = ast_strdup(p->owner->cid.cid_dnid);
- p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
- p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
- p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
- p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
- p->chan->cid.cid_pres = p->owner->cid.cid_pres;
- p->chan->cid.cid_ani2 = p->owner->cid.cid_ani2;
- p->chan->cid.cid_ton = p->owner->cid.cid_ton;
+ if (!(p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis))) {
+ return -1;
+ }
+ ast_party_redirecting_copy(&p->chan->redirecting, &p->owner->redirecting);
+
+ if (!(p->chan->cid.cid_dnid = ast_strdup(p->owner->cid.cid_dnid))) {
+ return -1;
+ }
p->chan->cid.cid_tns = p->owner->cid.cid_tns;
+
+ ast_connected_line_copy_to_caller(&p->chan->cid, &p->owner->connected);
+ ast_connected_line_copy_from_caller(&p->chan->connected, &p->owner->cid);
+
ast_string_field_set(p->chan, language, p->owner->language);
ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
ast_string_field_set(p->chan, musicclass, p->owner->musicclass);
@@ -560,6 +614,7 @@ static int local_call(struct ast_channel *ast, char *dest, int timeout)
ast_set_flag(p, LOCAL_LAUNCHED_PBX);
ast_mutex_unlock(&p->lock);
+ ast_channel_unlock(p->chan);
return res;
}
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index cad9d9497..83a2e61b4 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -915,7 +915,7 @@ static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
transmit_modify_request(sub->next);
}
- transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
+ transmit_notify_request_with_callerid(sub, tone, ast->connected.id.number, ast->connected.id.name);
ast_setstate(ast, AST_STATE_RINGING);
if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index 599bcef82..52b8f1d9f 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <signal.h>
#include <sys/file.h>
#include <semaphore.h>
+#include <ctype.h>
#include "asterisk/channel.h"
#include "asterisk/config.h"
@@ -88,8 +89,6 @@ struct misdn_jb{
ast_mutex_t mutexjb;
};
-
-
/*! \brief allocates the jb-structure and initialize the elements */
struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
@@ -340,10 +339,6 @@ struct chan_list {
*/
char mohinterpret[MAX_MUSICCLASS];
-#if 0
- int zero_read_cnt; /* Not used */
-#endif
-
/*!
* \brief Number of outgoing audio frames dropped since last debug gripe message.
*/
@@ -401,18 +396,10 @@ struct chan_list {
*/
struct timeval overlap_tv;
-#if 0
- struct chan_list *peer; /* Not used */
-#endif
-
/*!
* \brief Next channel call record in the list.
*/
struct chan_list *next;
-#if 0
- struct chan_list *prev; /* Not used */
- struct chan_list *first; /* Not used */
-#endif
};
@@ -423,13 +410,14 @@ void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_
void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
-static struct robin_list {
+struct robin_list {
char *group;
int port;
int channel;
struct robin_list *next;
struct robin_list *prev;
-} *robin = NULL;
+};
+static struct robin_list *robin = NULL;
static inline void free_robin_list_r(struct robin_list *r)
@@ -538,7 +526,7 @@ static int misdn_facility_exec(struct ast_channel *chan, void *data);
int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
-void debug_numplan(int port, int numplan, char *type);
+void debug_numtype(int port, int numtype, char *type);
int add_out_calls(int port);
int add_in_calls(int port);
@@ -580,6 +568,534 @@ static struct chan_list * get_chan_by_ast_name(char *name)
return NULL;
}
+/*!
+ * \internal
+ * \brief Convert the mISDN type of number code to a string
+ *
+ * \param number_type mISDN type of number code.
+ *
+ * \return The mISDN type of number code as a string
+ */
+static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
+{
+ const char *str;
+
+ switch (number_type) {
+ default:
+ case NUMTYPE_UNKNOWN:
+ str = "Unknown";
+ break;
+
+ case NUMTYPE_INTERNATIONAL:
+ str = "International";
+ break;
+
+ case NUMTYPE_NATIONAL:
+ str = "National";
+ break;
+
+ case NUMTYPE_NETWORK_SPECIFIC:
+ str = "Network Specific";
+ break;
+
+ case NUMTYPE_SUBSCRIBER:
+ str = "Subscriber";
+ break;
+
+ case NUMTYPE_ABBREVIATED:
+ str = "Abbreviated";
+ break;
+ }
+
+ return str;
+}
+
+/*!
+ * \internal
+ * \brief Convert the mISDN type of number code to Asterisk type of number code
+ *
+ * \param number_type mISDN type of number code.
+ *
+ * \return Asterisk type of number code
+ */
+static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
+{
+ int ast_number_type;
+
+ switch (number_type) {
+ default:
+ case NUMTYPE_UNKNOWN:
+ ast_number_type = NUMTYPE_UNKNOWN << 4;
+ break;
+
+ case NUMTYPE_INTERNATIONAL:
+ ast_number_type = NUMTYPE_INTERNATIONAL << 4;
+ break;
+
+ case NUMTYPE_NATIONAL:
+ ast_number_type = NUMTYPE_NATIONAL << 4;
+ break;
+
+ case NUMTYPE_NETWORK_SPECIFIC:
+ ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
+ break;
+
+ case NUMTYPE_SUBSCRIBER:
+ ast_number_type = NUMTYPE_SUBSCRIBER << 4;
+ break;
+
+ case NUMTYPE_ABBREVIATED:
+ ast_number_type = NUMTYPE_ABBREVIATED << 4;
+ break;
+ }
+
+ return ast_number_type;
+}
+
+/*!
+ * \internal
+ * \brief Convert the Asterisk type of number code to mISDN type of number code
+ *
+ * \param ast_number_type Asterisk type of number code.
+ *
+ * \return mISDN type of number code
+ */
+static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
+{
+ enum mISDN_NUMBER_TYPE number_type;
+
+ switch ((ast_number_type >> 4) & 0x07) {
+ default:
+ case NUMTYPE_UNKNOWN:
+ number_type = NUMTYPE_UNKNOWN;
+ break;
+
+ case NUMTYPE_INTERNATIONAL:
+ number_type = NUMTYPE_INTERNATIONAL;
+ break;
+
+ case NUMTYPE_NATIONAL:
+ number_type = NUMTYPE_NATIONAL;
+ break;
+
+ case NUMTYPE_NETWORK_SPECIFIC:
+ number_type = NUMTYPE_NETWORK_SPECIFIC;
+ break;
+
+ case NUMTYPE_SUBSCRIBER:
+ number_type = NUMTYPE_SUBSCRIBER;
+ break;
+
+ case NUMTYPE_ABBREVIATED:
+ number_type = NUMTYPE_ABBREVIATED;
+ break;
+ }
+
+ return number_type;
+}
+
+/*!
+ * \internal
+ * \brief Convert the mISDN numbering plan code to a string
+ *
+ * \param number_plan mISDN numbering plan code.
+ *
+ * \return The mISDN numbering plan code as a string
+ */
+static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
+{
+ const char *str;
+
+ switch (number_plan) {
+ default:
+ case NUMPLAN_UNKNOWN:
+ str = "Unknown";
+ break;
+
+ case NUMPLAN_ISDN:
+ str = "ISDN";
+ break;
+
+ case NUMPLAN_DATA:
+ str = "Data";
+ break;
+
+ case NUMPLAN_TELEX:
+ str = "Telex";
+ break;
+
+ case NUMPLAN_NATIONAL:
+ str = "National";
+ break;
+
+ case NUMPLAN_PRIVATE:
+ str = "Private";
+ break;
+ }
+
+ return str;
+}
+
+/*!
+ * \internal
+ * \brief Convert the mISDN numbering plan code to Asterisk numbering plan code
+ *
+ * \param number_plan mISDN numbering plan code.
+ *
+ * \return Asterisk numbering plan code
+ */
+static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
+{
+ int ast_number_plan;
+
+ switch (number_plan) {
+ default:
+ case NUMPLAN_UNKNOWN:
+ ast_number_plan = NUMPLAN_UNKNOWN;
+ break;
+
+ case NUMPLAN_ISDN:
+ ast_number_plan = NUMPLAN_ISDN;
+ break;
+
+ case NUMPLAN_DATA:
+ ast_number_plan = NUMPLAN_DATA;
+ break;
+
+ case NUMPLAN_TELEX:
+ ast_number_plan = NUMPLAN_TELEX;
+ break;
+
+ case NUMPLAN_NATIONAL:
+ ast_number_plan = NUMPLAN_NATIONAL;
+ break;
+
+ case NUMPLAN_PRIVATE:
+ ast_number_plan = NUMPLAN_PRIVATE;
+ break;
+ }
+
+ return ast_number_plan;
+}
+
+/*!
+ * \internal
+ * \brief Convert the Asterisk numbering plan code to mISDN numbering plan code
+ *
+ * \param ast_number_plan Asterisk numbering plan code.
+ *
+ * \return mISDN numbering plan code
+ */
+static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
+{
+ enum mISDN_NUMBER_PLAN number_plan;
+
+ switch (ast_number_plan & 0x0F) {
+ default:
+ case NUMPLAN_UNKNOWN:
+ number_plan = NUMPLAN_UNKNOWN;
+ break;
+
+ case NUMPLAN_ISDN:
+ number_plan = NUMPLAN_ISDN;
+ break;
+
+ case NUMPLAN_DATA:
+ number_plan = NUMPLAN_DATA;
+ break;
+
+ case NUMPLAN_TELEX:
+ number_plan = NUMPLAN_TELEX;
+ break;
+
+ case NUMPLAN_NATIONAL:
+ number_plan = NUMPLAN_NATIONAL;
+ break;
+
+ case NUMPLAN_PRIVATE:
+ number_plan = NUMPLAN_PRIVATE;
+ break;
+ }
+
+ return number_plan;
+}
+
+/*!
+ * \internal
+ * \brief Convert the mISDN presentation code to a string
+ *
+ * \param presentation mISDN number presentation restriction code.
+ *
+ * \return The mISDN presentation code as a string
+ */
+static const char *misdn_to_str_pres(int presentation)
+{
+ const char *str;
+
+ switch (presentation) {
+ case 0:
+ str = "Allowed";
+ break;
+
+ case 1:
+ str = "Restricted";
+ break;
+
+ case 2:
+ str = "Unavailable";
+ break;
+
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ return str;
+}
+
+/*!
+ * \internal
+ * \brief Convert the mISDN presentation code to Asterisk presentation code
+ *
+ * \param presentation mISDN number presentation restriction code.
+ *
+ * \return Asterisk presentation code
+ */
+static int misdn_to_ast_pres(int presentation)
+{
+ switch (presentation) {
+ default:
+ case 0:
+ presentation = AST_PRES_ALLOWED;
+ break;
+
+ case 1:
+ presentation = AST_PRES_RESTRICTED;
+ break;
+
+ case 2:
+ presentation = AST_PRES_UNAVAILABLE;
+ break;
+ }
+
+ return presentation;
+}
+
+/*!
+ * \internal
+ * \brief Convert the Asterisk presentation code to mISDN presentation code
+ *
+ * \param presentation Asterisk number presentation restriction code.
+ *
+ * \return mISDN presentation code
+ */
+static int ast_to_misdn_pres(int presentation)
+{
+ switch (presentation & AST_PRES_RESTRICTION) {
+ default:
+ case AST_PRES_ALLOWED:
+ presentation = 0;
+ break;
+
+ case AST_PRES_RESTRICTED:
+ presentation = 1;
+ break;
+
+ case AST_PRES_UNAVAILABLE:
+ presentation = 2;
+ break;
+ }
+
+ return presentation;
+}
+
+/*!
+ * \internal
+ * \brief Convert the mISDN screening code to a string
+ *
+ * \param screening mISDN number screening code.
+ *
+ * \return The mISDN screening code as a string
+ */
+static const char *misdn_to_str_screen(int screening)
+{
+ const char *str;
+
+ switch (screening) {
+ case 0:
+ str = "Unscreened";
+ break;
+
+ case 1:
+ str = "Passed Screen";
+ break;
+
+ case 2:
+ str = "Failed Screen";
+ break;
+
+ case 3:
+ str = "Network Number";
+ break;
+
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ return str;
+}
+
+/*!
+ * \internal
+ * \brief Convert the mISDN screening code to Asterisk screening code
+ *
+ * \param screening mISDN number screening code.
+ *
+ * \return Asterisk screening code
+ */
+static int misdn_to_ast_screen(int screening)
+{
+ switch (screening) {
+ default:
+ case 0:
+ screening = AST_PRES_USER_NUMBER_UNSCREENED;
+ break;
+
+ case 1:
+ screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
+ break;
+
+ case 2:
+ screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
+ break;
+
+ case 3:
+ screening = AST_PRES_NETWORK_NUMBER;
+ break;
+ }
+
+ return screening;
+}
+
+/*!
+ * \internal
+ * \brief Convert the Asterisk screening code to mISDN screening code
+ *
+ * \param screening Asterisk number screening code.
+ *
+ * \return mISDN screening code
+ */
+static int ast_to_misdn_screen(int screening)
+{
+ switch (screening & AST_PRES_NUMBER_TYPE) {
+ default:
+ case AST_PRES_USER_NUMBER_UNSCREENED:
+ screening = 0;
+ break;
+
+ case AST_PRES_USER_NUMBER_PASSED_SCREEN:
+ screening = 1;
+ break;
+
+ case AST_PRES_USER_NUMBER_FAILED_SCREEN:
+ screening = 2;
+ break;
+
+ case AST_PRES_NETWORK_NUMBER:
+ screening = 3;
+ break;
+ }
+
+ return screening;
+}
+
+/*!
+ * \internal
+ * \brief Convert Asterisk redirecting reason to mISDN redirecting reason code.
+ *
+ * \param ast Asterisk redirecting reason code.
+ *
+ * \return mISDN reason code
+ */
+static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
+{
+ unsigned index;
+
+ static const struct misdn_reasons {
+ enum AST_REDIRECTING_REASON ast;
+ enum mISDN_REDIRECTING_REASON q931;
+ } misdn_reason_table[] = {
+ /* *INDENT-OFF* */
+ { AST_REDIRECTING_REASON_UNKNOWN, mISDN_REDIRECTING_REASON_UNKNOWN },
+ { AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
+ { AST_REDIRECTING_REASON_NO_ANSWER, mISDN_REDIRECTING_REASON_NO_REPLY },
+ { AST_REDIRECTING_REASON_UNAVAILABLE, mISDN_REDIRECTING_REASON_NO_REPLY },
+ { AST_REDIRECTING_REASON_UNCONDITIONAL, mISDN_REDIRECTING_REASON_CALL_FWD },
+ { AST_REDIRECTING_REASON_TIME_OF_DAY, mISDN_REDIRECTING_REASON_UNKNOWN },
+ { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
+ { AST_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_DEFLECTION },
+ { AST_REDIRECTING_REASON_FOLLOW_ME, mISDN_REDIRECTING_REASON_UNKNOWN },
+ { AST_REDIRECTING_REASON_OUT_OF_ORDER, mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
+ { AST_REDIRECTING_REASON_AWAY, mISDN_REDIRECTING_REASON_UNKNOWN },
+ { AST_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
+ /* *INDENT-ON* */
+ };
+
+ for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
+ if (misdn_reason_table[index].ast == ast) {
+ return misdn_reason_table[index].q931;
+ }
+ }
+ return mISDN_REDIRECTING_REASON_UNKNOWN;
+}
+
+/*!
+ * \internal
+ * \brief Convert the mISDN redirecting reason to Asterisk redirecting reason code
+ *
+ * \param q931 mISDN redirecting reason code.
+ *
+ * \return Asterisk redirecting reason code
+ */
+static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
+{
+ enum AST_REDIRECTING_REASON ast;
+
+ switch (q931) {
+ default:
+ case mISDN_REDIRECTING_REASON_UNKNOWN:
+ ast = AST_REDIRECTING_REASON_UNKNOWN;
+ break;
+
+ case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
+ ast = AST_REDIRECTING_REASON_USER_BUSY;
+ break;
+
+ case mISDN_REDIRECTING_REASON_NO_REPLY:
+ ast = AST_REDIRECTING_REASON_NO_ANSWER;
+ break;
+
+ case mISDN_REDIRECTING_REASON_DEFLECTION:
+ ast = AST_REDIRECTING_REASON_DEFLECTION;
+ break;
+
+ case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
+ ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
+ break;
+
+ case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
+ ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
+ break;
+
+ case mISDN_REDIRECTING_REASON_CALL_FWD:
+ ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
+ break;
+ }
+
+ return ast;
+}
+
struct allowed_bearers {
@@ -590,7 +1106,7 @@ struct allowed_bearers {
};
/* *INDENT-OFF* */
-static const struct allowed_bearers allowed_bearers_array[]= {
+static const struct allowed_bearers allowed_bearers_array[] = {
/* Name, Displayable Name Bearer Capability, Deprecated */
{ "speech", "Speech", INFO_CAPABILITY_SPEECH, 0 },
{ "3_1khz", "3.1KHz Audio", INFO_CAPABILITY_AUDIO_3_1K, 0 },
@@ -609,7 +1125,7 @@ static const char *bearer2str(int cap)
if (allowed_bearers_array[index].cap == cap) {
return allowed_bearers_array[index].display;
}
- } /* end for */
+ }
return "Unknown Bearer";
}
@@ -682,6 +1198,95 @@ static void print_bearer(struct misdn_bchannel *bc)
}
}
+/*!
+ * \internal
+ * \brief Prefix a string to another string in place.
+ *
+ * \param str_prefix String to prefix to the main string.
+ * \param str_main String to get the prefix added to it.
+ * \param size Buffer size of the main string (Includes null terminator).
+ *
+ * \note The str_main buffer size must be greater than one.
+ *
+ * \return Nothing
+ */
+static void misdn_prefix_string(const char *str_prefix, char *str_main, size_t size)
+{
+ size_t len_over;
+ size_t len_total;
+ size_t len_main;
+ size_t len_prefix;
+
+ len_prefix = strlen(str_prefix);
+ if (!len_prefix) {
+ /* There is no prefix to prepend. */
+ return;
+ }
+ len_main = strlen(str_main);
+ len_total = len_prefix + len_main;
+ if (size <= len_total) {
+ /* We need to truncate since the buffer is too small. */
+ len_over = len_total + 1 - size;
+ if (len_over <= len_main) {
+ len_main -= len_over;
+ } else {
+ len_over -= len_main;
+ len_main = 0;
+ len_prefix -= len_over;
+ }
+ }
+ if (len_main) {
+ memmove(str_main + len_prefix, str_main, len_main);
+ }
+ memcpy(str_main, str_prefix, len_prefix);
+ str_main[len_prefix + len_main] = '\0';
+}
+
+/*!
+ * \internal
+ * \brief Add a configured prefix to the given number.
+ *
+ * \param port Logical port number
+ * \param number_type Type-of-number passed in.
+ * \param number Given number string to add prefix
+ * \param size Buffer size number string occupies.
+ *
+ * \return Nothing
+ */
+static void misdn_add_number_prefix(int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
+{
+ enum misdn_cfg_elements type_prefix;
+ char num_prefix[MISDN_MAX_NUMBER_LEN];
+
+ /* Get prefix string. */
+ switch (number_type) {
+ case NUMTYPE_UNKNOWN:
+ type_prefix = MISDN_CFG_TON_PREFIX_UNKNOWN;
+ break;
+ case NUMTYPE_INTERNATIONAL:
+ type_prefix = MISDN_CFG_TON_PREFIX_INTERNATIONAL;
+ break;
+ case NUMTYPE_NATIONAL:
+ type_prefix = MISDN_CFG_TON_PREFIX_NATIONAL;
+ break;
+ case NUMTYPE_NETWORK_SPECIFIC:
+ type_prefix = MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC;
+ break;
+ case NUMTYPE_SUBSCRIBER:
+ type_prefix = MISDN_CFG_TON_PREFIX_SUBSCRIBER;
+ break;
+ case NUMTYPE_ABBREVIATED:
+ type_prefix = MISDN_CFG_TON_PREFIX_ABBREVIATED;
+ break;
+ default:
+ /* Type-of-number does not have a prefix that can be added. */
+ return;
+ }
+ misdn_cfg_get(port, type_prefix, num_prefix, sizeof(num_prefix));
+
+ misdn_prefix_string(num_prefix, number, size);
+}
+
static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
{
char buf[128];
@@ -691,7 +1296,8 @@ static void export_aoc_vars(int originator, struct ast_channel *ast, struct misd
}
if (originator == ORG_AST) {
- if (!(ast = ast_bridged_channel(ast))) {
+ ast = ast_bridged_channel(ast);
+ if (!ast) {
return;
}
}
@@ -745,7 +1351,8 @@ static void export_aoc_vars(int originator, struct ast_channel *ast, struct misd
/*************** Helpers END *************/
static void sighandler(int sig)
-{}
+{
+}
static void *misdn_tasks_thread_func(void *data)
{
@@ -840,6 +1447,7 @@ static void misdn_tasks_remove(int task_id)
static int misdn_l1_task(const void *vdata)
{
const int *data = vdata;
+
misdn_lib_isdn_l1watcher(*data);
chan_misdn_log(5, *data, "L1watcher timeout\n");
return 1;
@@ -866,21 +1474,22 @@ static int misdn_overlap_dial_task(const void *data)
tv_end.tv_sec += ch->overlap_dial;
tv_now = ast_tvnow();
- if ((diff = ast_tvdiff_ms(tv_end, tv_now)) > 100) {
+ diff = ast_tvdiff_ms(tv_end, tv_now);
+ if (100 < diff) {
return diff;
}
/* if we are 100ms near the timeout, we are satisfied.. */
stop_indicate(ch);
- if (ast_strlen_zero(ch->bc->dad)) {
+ if (ast_strlen_zero(ch->bc->dialed.number)) {
dad = "s";
- ast_copy_string(ch->ast->exten, "s", sizeof(ch->ast->exten));
+ strcpy(ch->ast->exten, dad);
} else {
- dad = ch->bc->dad;
+ dad = ch->bc->dialed.number;
}
- if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) {
+ if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->caller.number)) {
ch->state = MISDN_DIALING;
if (pbx_start_chan(ch) < 0) {
chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
@@ -957,8 +1566,10 @@ static char *handle_cli_misdn_set_debug(struct ast_cli_entry *e, int cmd, struct
level = 1;
} else if (!strcasecmp(a->argv[3], "off")) {
level = 0;
- } else {
+ } else if (isdigit(a->argv[3][0])) {
level = atoi(a->argv[3]);
+ } else {
+ return CLI_SHOWUSAGE;
}
switch (a->argc) {
@@ -1293,27 +1904,29 @@ struct state_struct {
};
static struct state_struct state_array[] = {
+/* *INDENT-OFF* */
{ MISDN_NOTHING, "NOTHING" }, /* at beginning */
- { MISDN_WAITING4DIGS, "WAITING4DIGS" }, /* when waiting for infos */
- { MISDN_EXTCANTMATCH, "EXTCANTMATCH" }, /* when asterisk couldn't match our ext */
- { MISDN_INCOMING_SETUP, "INCOMING SETUP" }, /* when pbx_start */
- { MISDN_DIALING, "DIALING" }, /* when pbx_start */
- { MISDN_PROGRESS, "PROGRESS" }, /* when pbx_start */
- { MISDN_PROCEEDING, "PROCEEDING" }, /* when pbx_start */
- { MISDN_CALLING, "CALLING" }, /* when misdn_call is called */
- { MISDN_CALLING_ACKNOWLEDGE, "CALLING_ACKNOWLEDGE" }, /* when misdn_call is called */
- { MISDN_ALERTING, "ALERTING" }, /* when Alerting */
- { MISDN_BUSY, "BUSY" }, /* when BUSY */
- { MISDN_CONNECTED, "CONNECTED" }, /* when connected */
- { MISDN_PRECONNECTED, "PRECONNECTED" }, /* when connected */
- { MISDN_DISCONNECTED, "DISCONNECTED" }, /* when connected */
- { MISDN_RELEASED, "RELEASED" }, /* when connected */
- { MISDN_BRIDGED, "BRIDGED" }, /* when bridged */
+ { MISDN_WAITING4DIGS, "WAITING4DIGS" }, /* when waiting for infos */
+ { MISDN_EXTCANTMATCH, "EXTCANTMATCH" }, /* when asterisk couldn't match our ext */
+ { MISDN_INCOMING_SETUP, "INCOMING SETUP" }, /* when pbx_start */
+ { MISDN_DIALING, "DIALING" }, /* when pbx_start */
+ { MISDN_PROGRESS, "PROGRESS" }, /* when pbx_start */
+ { MISDN_PROCEEDING, "PROCEEDING" }, /* when pbx_start */
+ { MISDN_CALLING, "CALLING" }, /* when misdn_call is called */
+ { MISDN_CALLING_ACKNOWLEDGE, "CALLING_ACKNOWLEDGE" }, /* when misdn_call is called */
+ { MISDN_ALERTING, "ALERTING" }, /* when Alerting */
+ { MISDN_BUSY, "BUSY" }, /* when BUSY */
+ { MISDN_CONNECTED, "CONNECTED" }, /* when connected */
+ { MISDN_PRECONNECTED, "PRECONNECTED" }, /* when connected */
+ { MISDN_DISCONNECTED, "DISCONNECTED" }, /* when connected */
+ { MISDN_RELEASED, "RELEASED" }, /* when connected */
+ { MISDN_BRIDGED, "BRIDGED" }, /* when bridged */
{ MISDN_CLEANING, "CLEANING" }, /* when hangup from * but we were connected before */
- { MISDN_HUNGUP_FROM_MISDN, "HUNGUP_FROM_MISDN" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
- { MISDN_HOLDED, "HOLDED" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
- { MISDN_HOLD_DISCONNECT, "HOLD_DISCONNECT" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
+ { MISDN_HUNGUP_FROM_MISDN, "HUNGUP_FROM_MISDN" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
+ { MISDN_HOLDED, "HOLDED" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
+ { MISDN_HOLD_DISCONNECT, "HOLD_DISCONNECT" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
{ MISDN_HUNGUP_FROM_AST, "HUNGUP_FROM_AST" }, /* when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
+/* *INDENT-ON* */
};
static const char *misdn_get_ch_state(struct chan_list *p)
@@ -1384,18 +1997,24 @@ static char *handle_cli_misdn_reload(struct ast_cli_entry *e, int cmd, struct as
static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel *bc)
{
struct ast_channel *ast = help->ast;
- ast_cli(fd,
- "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
- bc->pid, bc->port, bc->channel,
+ ast_cli(fd,
+ "* Pid:%d Port:%d Ch:%d Mode:%s Orig:%s dialed:%s\n"
+ " --> caller:\"%s\" <%s>\n"
+ " --> redirecting:\"%s\" <%s>\n"
+ " --> context:%s state:%s\n",
+ bc->pid,
+ bc->port,
+ bc->channel,
bc->nt ? "NT" : "TE",
help->originator == ORG_AST ? "*" : "I",
- ast ? ast->exten : NULL,
- ast ? ast->cid.cid_num : NULL,
- bc->rad,
- ast ? ast->context : NULL,
- misdn_get_ch_state(help)
- );
+ ast ? ast->exten : "",
+ (ast && ast->cid.cid_name) ? ast->cid.cid_name : "",
+ (ast && ast->cid.cid_num) ? ast->cid.cid_num : "",
+ bc->redirecting.from.name,
+ bc->redirecting.from.number,
+ ast ? ast->context : "",
+ misdn_get_ch_state(help));
if (misdn_debug[bc->port] > 0) {
ast_cli(fd,
" --> astname: %s\n"
@@ -1418,21 +2037,18 @@ static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel
help->l3id,
help->addr,
bc->addr,
- bc ? bc->l3_id : -1,
+ bc->l3_id,
bc->display,
-
bc->active,
bc_state2str(bc->bc_state),
bearer2str(bc->capability),
#ifdef MISDN_1_2
bc->pipeline,
#else
- bc->ec_enable,
+ bc->ec_enable,
#endif
-
help->norxtone, help->notxtone,
- bc->holded
- );
+ bc->holded);
}
}
@@ -1480,15 +2096,17 @@ static char *handle_cli_misdn_show_channels(struct ast_cli_entry *e, int cmd, st
if (help->state == MISDN_HOLDED) {
ast_cli(a->fd, "ITS A HOLDED BC:\n");
ast_cli(a->fd, " --> l3_id: %x\n"
- " --> dad:%s oad:%s\n"
- " --> hold_port: %d\n"
- " --> hold_channel: %d\n",
- help->l3id,
- ast->exten,
- ast->cid.cid_num,
- help->hold_info.port,
- help->hold_info.channel
- );
+ " --> dialed:%s\n"
+ " --> caller:\"%s\" <%s>\n"
+ " --> hold_port: %d\n"
+ " --> hold_channel: %d\n",
+ help->l3id,
+ ast->exten,
+ ast->cid.cid_name ? ast->cid.cid_name : "",
+ ast->cid.cid_num ? ast->cid.cid_num : "",
+ help->hold_info.port,
+ help->hold_info.channel
+ );
} else {
ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
}
@@ -1693,7 +2311,7 @@ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, st
return 0;
}
tmp->bc->fac_out.Function = Fac_CD;
- ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
+ ast_copy_string((char *) tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
} else if (strstr(a->argv[3], "CFActivate")) {
if (a->argc < 7) {
@@ -1718,7 +2336,7 @@ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, st
} else if (strstr(a->argv[3], "CFDeactivate")) {
if (a->argc < 6) {
- ast_verbose("CFActivate requires 1 arg: FromNumber\n\n");
+ ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
return 0;
}
port = atoi(a->argv[4]);
@@ -1728,10 +2346,10 @@ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, st
ast_verbose("Sending CFDeactivate Port:(%d) FromNr. (%s)\n", port, served_nr);
bc->fac_out.Function = Fac_CFDeactivate;
- bc->fac_out.u.CFDeactivate.BasicService = 0; //All Services
- bc->fac_out.u.CFDeactivate.Procedure = 0; //Unconditional
+ bc->fac_out.u.CFDeactivate.BasicService = 0; /* All Services */
+ bc->fac_out.u.CFDeactivate.Procedure = 0; /* Unconditional */
+ ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
- ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
misdn_lib_send_event(bc, EVENT_FACILITY);
}
@@ -2009,23 +2627,25 @@ static struct ast_cli_entry chan_misdn_clis[] = {
};
/*! \brief Updates caller ID information from config */
-static int update_config(struct chan_list *ch, int orig)
+static void update_config(struct chan_list *ch)
{
struct ast_channel *ast;
struct misdn_bchannel *bc;
- int port, hdlc = 0;
- int pres, screen;
+ int port;
+ int hdlc = 0;
+ int pres;
+ int screen;
if (!ch) {
ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
- return -1;
+ return;
}
ast = ch->ast;
bc = ch->bc;
if (! ast || ! bc) {
ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
- return -1;
+ return;
}
port = bc->port;
@@ -2033,7 +2653,6 @@ static int update_config(struct chan_list *ch, int orig)
chan_misdn_log(7, port, "update_config: Getting Config\n");
misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
-
if (hdlc) {
switch (bc->capability) {
case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
@@ -2050,48 +2669,17 @@ static int update_config(struct chan_list *ch, int orig)
chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
if (pres < 0 || screen < 0) {
- chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
+ chan_misdn_log(2, port, " --> pres: %x\n", ast->connected.id.number_presentation);
- switch (ast->cid.cid_pres & 0x60) {
- case AST_PRES_RESTRICTED:
- bc->pres = 1;
- chan_misdn_log(2, port, " --> PRES: Restricted (1)\n");
- break;
- case AST_PRES_UNAVAILABLE:
- bc->pres = 2;
- chan_misdn_log(2, port, " --> PRES: Unavailable (2)\n");
- break;
- default:
- bc->pres = 0;
- chan_misdn_log(2, port, " --> PRES: Allowed (0)\n");
- break;
- }
+ bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
+ chan_misdn_log(2, port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
- switch (ast->cid.cid_pres & 0x3) {
- default:
- case AST_PRES_USER_NUMBER_UNSCREENED:
- bc->screen = 0;
- chan_misdn_log(2, port, " --> SCREEN: Unscreened (0)\n");
- break;
- case AST_PRES_USER_NUMBER_PASSED_SCREEN:
- bc->screen = 1;
- chan_misdn_log(2, port, " --> SCREEN: Passed Screen (1)\n");
- break;
- case AST_PRES_USER_NUMBER_FAILED_SCREEN:
- bc->screen = 2;
- chan_misdn_log(2, port, " --> SCREEN: Failed Screen (2)\n");
- break;
- case AST_PRES_NETWORK_NUMBER:
- bc->screen = 3;
- chan_misdn_log(2, port, " --> SCREEN: Network Nr. (3)\n");
- break;
- }
+ bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
+ chan_misdn_log(2, port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
} else {
- bc->screen = screen;
- bc->pres = pres;
+ bc->caller.screening = screen;
+ bc->caller.presentation = pres;
}
-
- return 0;
}
@@ -2130,20 +2718,26 @@ static void config_jitterbuffer(struct chan_list *ch)
}
-void debug_numplan(int port, int numplan, char *type)
+void debug_numtype(int port, int numtype, char *type)
{
- switch (numplan) {
- case NUMPLAN_INTERNATIONAL:
+ switch (numtype) {
+ case NUMTYPE_UNKNOWN:
+ chan_misdn_log(2, port, " --> %s: Unknown\n", type);
+ break;
+ case NUMTYPE_INTERNATIONAL:
chan_misdn_log(2, port, " --> %s: International\n", type);
break;
- case NUMPLAN_NATIONAL:
+ case NUMTYPE_NATIONAL:
chan_misdn_log(2, port, " --> %s: National\n", type);
break;
- case NUMPLAN_SUBSCRIBER:
+ case NUMTYPE_NETWORK_SPECIFIC:
+ chan_misdn_log(2, port, " --> %s: Network Specific\n", type);
+ break;
+ case NUMTYPE_SUBSCRIBER:
chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
break;
- case NUMPLAN_UNKNOWN:
- chan_misdn_log(2, port, " --> %s: Unknown\n", type);
+ case NUMTYPE_ABBREVIATED:
+ chan_misdn_log(2, port, " --> %s: Abbreviated\n", type);
break;
/* Maybe we should cut off the prefix if present ? */
default:
@@ -2193,7 +2787,7 @@ static int update_ec_config(struct misdn_bchannel *bc)
#endif
-static int read_config(struct chan_list *ch, int orig)
+static int read_config(struct chan_list *ch)
{
struct ast_channel *ast;
struct misdn_bchannel *bc;
@@ -2234,7 +2828,6 @@ static int read_config(struct chan_list *ch, int orig)
misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
-
if (ch->ast_dsp) {
ch->ignore_dtmf = 1;
}
@@ -2251,7 +2844,6 @@ static int read_config(struct chan_list *ch, int orig)
misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
-
if (hdlc) {
switch (bc->capability) {
case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
@@ -2280,14 +2872,16 @@ static int read_config(struct chan_list *ch, int orig)
misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
+ misdn_cfg_get(port, MISDN_CFG_DISPLAY_CONNECTED, &bc->display_connected, sizeof(bc->display_connected));
+ misdn_cfg_get(port, MISDN_CFG_DISPLAY_SETUP, &bc->display_setup, sizeof(bc->display_setup));
+
misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
-
chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
ast->pickupgroup = pg;
ast->callgroup = cg;
- if (orig == ORG_AST) {
+ if (ch->originator == ORG_AST) {
char callerid[BUFFERSIZE + 1];
/* ORIGINATOR Asterisk (outgoing call) */
@@ -2300,80 +2894,46 @@ static int read_config(struct chan_list *ch, int orig)
misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
if (!ast_strlen_zero(callerid)) {
- chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
- ast_copy_string(bc->oad, callerid, sizeof(bc->oad));
+ char *cid_name = NULL;
+ char *cid_num = NULL;
+
+ ast_callerid_parse(callerid, &cid_name, &cid_num);
+ if (cid_name) {
+ ast_copy_string(bc->caller.name, cid_name, sizeof(bc->caller.name));
+ } else {
+ bc->caller.name[0] = '\0';
+ }
+ if (cid_num) {
+ ast_copy_string(bc->caller.number, cid_num, sizeof(bc->caller.number));
+ } else {
+ bc->caller.number[0] = '\0';
+ }
+ chan_misdn_log(1, port, " --> * Setting caller to \"%s\" <%s>\n", bc->caller.name, bc->caller.number);
}
- misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(bc->dnumplan));
- misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(bc->onumplan));
- misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
- debug_numplan(port, bc->dnumplan, "TON");
- debug_numplan(port, bc->onumplan, "LTON");
- debug_numplan(port, bc->cpnnumplan, "CTON");
+ misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dialed.number_type, sizeof(bc->dialed.number_type));
+ bc->dialed.number_plan = NUMPLAN_ISDN;
+ debug_numtype(port, bc->dialed.number_type, "TON");
ch->overlap_dial = 0;
} else {
/* ORIGINATOR MISDN (incoming call) */
- char prefix[BUFFERSIZE + 1] = "";
if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
ch->faxdetect = (strstr(faxdetect, "nojump")) ? 2 : 1;
}
- misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
- debug_numplan(port, bc->cpnnumplan, "CTON");
-
- switch (bc->onumplan) {
- case NUMPLAN_INTERNATIONAL:
- misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
- break;
+ /* Add configured prefix to caller.number */
+ misdn_add_number_prefix(bc->port, bc->caller.number_type, bc->caller.number, sizeof(bc->caller.number));
- case NUMPLAN_NATIONAL:
- misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
- break;
- default:
- break;
- }
-
- ast_copy_string(buf, bc->oad, sizeof(buf));
- snprintf(bc->oad, sizeof(bc->oad), "%s%s", prefix, buf);
-
- if (!ast_strlen_zero(bc->dad)) {
- ast_copy_string(bc->orig_dad, bc->dad, sizeof(bc->orig_dad));
+ if (ast_strlen_zero(bc->dialed.number) && !ast_strlen_zero(bc->keypad)) {
+ ast_copy_string(bc->dialed.number, bc->keypad, sizeof(bc->dialed.number));
}
- if (ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
- ast_copy_string(bc->dad, bc->keypad, sizeof(bc->dad));
- }
+ /* Add configured prefix to dialed.number */
+ misdn_add_number_prefix(bc->port, bc->dialed.number_type, bc->dialed.number, sizeof(bc->dialed.number));
- prefix[0] = 0;
-
- switch (bc->dnumplan) {
- case NUMPLAN_INTERNATIONAL:
- misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
- break;
- case NUMPLAN_NATIONAL:
- misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
- break;
- default:
- break;
- }
-
- ast_copy_string(buf, bc->dad, sizeof(buf));
- snprintf(bc->dad, sizeof(bc->dad), "%s%s", prefix, buf);
-
- if (strcmp(bc->dad, ast->exten)) {
- ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
- }
-
- ast_set_callerid(ast, bc->oad, NULL, bc->oad);
-
- if ( !ast_strlen_zero(bc->rad) ) {
- if (ast->cid.cid_rdnis) {
- ast_free(ast->cid.cid_rdnis);
- }
- ast->cid.cid_rdnis = ast_strdup(bc->rad);
- }
+ ast_copy_string(ast->exten, bc->dialed.number, sizeof(ast->exten));
misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
ast_mutex_init(&ch->overlap_tv_lock);
@@ -2400,6 +2960,79 @@ static int read_config(struct chan_list *ch, int orig)
return 0;
}
+/*!
+ * \internal
+ * \brief Notify peer that the connected line has changed.
+ *
+ * \param ast Current Asterisk channel
+ * \param bc Associated B channel
+ * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
+ *
+ * \return Nothing
+ */
+static void misdn_update_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
+{
+ int number_type;
+
+ if (originator == ORG_MISDN) {
+ /* ORIGINATOR MISDN (incoming call) */
+
+ ast_copy_string(bc->connected.name, S_OR(ast->connected.id.name, ""), sizeof(bc->connected.name));
+ ast_copy_string(bc->connected.number, S_OR(ast->connected.id.number, ""), sizeof(bc->connected.number));
+ bc->connected.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
+ bc->connected.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
+
+ misdn_cfg_get(bc->port, MISDN_CFG_CPNDIALPLAN, &number_type, sizeof(number_type));
+ if (number_type < 0) {
+ bc->connected.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
+ bc->connected.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
+ } else {
+ /* Force us to send in CONNECT message */
+ bc->connected.number_type = number_type;
+ bc->connected.number_plan = NUMPLAN_ISDN;
+ }
+ debug_numtype(bc->port, bc->connected.number_type, "CTON");
+ } else {
+ /* ORIGINATOR Asterisk (outgoing call) */
+
+ ast_copy_string(bc->caller.name, S_OR(ast->connected.id.name, ""), sizeof(bc->caller.name));
+ ast_copy_string(bc->caller.number, S_OR(ast->connected.id.number, ""), sizeof(bc->caller.number));
+ bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
+ bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
+
+ misdn_cfg_get(bc->port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
+ if (number_type < 0) {
+ bc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
+ bc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
+ } else {
+ /* Force us to send in SETUP message */
+ bc->caller.number_type = number_type;
+ bc->caller.number_plan = NUMPLAN_ISDN;
+ }
+ debug_numtype(bc->port, bc->caller.number_type, "LTON");
+ }
+}
+
+/*!
+ * \internal
+ * \brief Copy the redirecting info out of the Asterisk channel
+ *
+ * \param bc Associated B channel
+ * \param ast Current Asterisk channel
+ *
+ * \return Nothing
+ */
+static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct ast_channel *ast)
+{
+ ast_copy_string(bc->redirecting.from.name, S_OR(ast->redirecting.from.name, ""), sizeof(bc->redirecting.from.name));
+ ast_copy_string(bc->redirecting.from.number, S_OR(ast->cid.cid_rdnis, ""), sizeof(bc->redirecting.from.number));
+ bc->redirecting.from.presentation = ast_to_misdn_pres(ast->redirecting.from.number_presentation);
+ bc->redirecting.from.screening = ast_to_misdn_screen(ast->redirecting.from.number_presentation);
+ bc->redirecting.from.number_type = ast_to_misdn_ton(ast->redirecting.from.number_type);
+ bc->redirecting.from.number_plan = ast_to_misdn_plan(ast->redirecting.from.number_type);
+ bc->redirecting.reason = ast_to_misdn_reason(ast->redirecting.reason);
+}
+
/*****************************/
/*** AST Indications Start ***/
@@ -2411,22 +3044,17 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
int r;
int exceed;
int bridging;
- struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(ast);
+ int number_type;
+ struct chan_list *ch;
struct misdn_bchannel *newbc;
- char *dest_cp = ast_strdupa(dest);
+ char *dest_cp;
+
AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(type);
- AST_APP_ARG(ext);
- AST_APP_ARG(opts);
+ AST_APP_ARG(intf); /* The interface token is discarded. */
+ AST_APP_ARG(ext); /* extension token */
+ AST_APP_ARG(opts); /* options token */
);
- AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
-
- if (ast_strlen_zero(args.ext)) {
- chan_misdn_log(0, 0, "misdn_call: No Extension given!\n");
- return -1;
- }
-
if (!ast) {
ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
return -1;
@@ -2439,47 +3067,74 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
return -1;
}
+ ch = MISDN_ASTERISK_TECH_PVT(ast);
if (!ch) {
- ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
+ ast_log(LOG_WARNING, " --> ! misdn_call called on %s, chan_list *ch==NULL\n", ast->name);
ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
newbc = ch->bc;
-
if (!newbc) {
- ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
+ ast_log(LOG_WARNING, " --> ! misdn_call called on %s, newbc==NULL\n", ast->name);
ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
+ /*
+ * dest is ---v
+ * Dial(mISDN/g:group_name[/extension[/options]])
+ * Dial(mISDN/port[:preselected_channel][/extension[/options]])
+ *
+ * The dial extension could be empty if you are using MISDN_KEYPAD
+ * to control ISDN provider features.
+ */
+ dest_cp = ast_strdupa(dest);
+ AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
+ if (!args.ext) {
+ args.ext = "";
+ }
+
port = newbc->port;
- if ((exceed = add_out_calls(port))) {
+ exceed = add_out_calls(port);
+ if (exceed != 0) {
char tmp[16];
snprintf(tmp, sizeof(tmp), "%d", exceed);
pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
+ ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
+ ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
chan_misdn_log(1, port, "* CALL: %s\n", dest);
- chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n", ast->exten, ast->name, ast->context);
+ chan_misdn_log(2, port, " --> * dialed:%s tech:%s context:%s\n", args.ext, ast->name, ast->context);
- chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
- if (ast->exten) {
- ast_copy_string(ast->exten, args.ext, sizeof(ast->exten));
- ast_copy_string(newbc->dad, args.ext, sizeof(newbc->dad));
- }
+ ast_copy_string(ast->exten, args.ext, sizeof(ast->exten));
+ ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number));
- ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
+ if (ast_strlen_zero(newbc->caller.name) && !ast_strlen_zero(ast->connected.id.name)) {
+ ast_copy_string(newbc->caller.name, ast->connected.id.name, sizeof(newbc->caller.name));
+ chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
+ }
+ if (ast_strlen_zero(newbc->caller.number) && !ast_strlen_zero(ast->connected.id.number)) {
+ ast_copy_string(newbc->caller.number, ast->connected.id.number, sizeof(newbc->caller.number));
+ chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
+ }
- chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
- if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
- ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
+ misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
+ if (number_type < 0) {
+ newbc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
+ newbc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
+ } else {
+ /* Force us to send in SETUP message */
+ newbc->caller.number_type = number_type;
+ newbc->caller.number_plan = NUMPLAN_ISDN;
}
+ debug_numtype(port, newbc->caller.number_type, "LTON");
newbc->capability = ast->transfercapability;
pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
@@ -2487,10 +3142,10 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
chan_misdn_log(2, port, " --> * Call with flag Digital\n");
}
- /* update screening and presentation */
- update_config(ch, ORG_AST);
+ /* update caller screening and presentation */
+ update_config(ch);
- /* fill in some ies from channel vary */
+ /* fill in some ies from channel dialplan variables */
import_ch(ast, newbc, ch);
/* Finally The Options Override Everything */
@@ -2499,6 +3154,11 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
} else {
chan_misdn_log(2, port, "NO OPTS GIVEN\n");
}
+ if (newbc->set_presentation) {
+ newbc->caller.presentation = newbc->presentation;
+ }
+
+ misdn_copy_redirecting_from_ast(newbc, ast);
/*check for bridging*/
misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
@@ -2519,7 +3179,7 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
/** we should have l3id after sending setup **/
ch->l3id = newbc->l3_id;
- if (r == -ENOCHAN ) {
+ if (r == -ENOCHAN) {
chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
@@ -2585,9 +3245,19 @@ static int misdn_answer(struct ast_channel *ast)
p->state = MISDN_CONNECTED;
stop_indicate(p);
- if ( ast_strlen_zero(p->bc->cad) ) {
- chan_misdn_log(2, p->bc->port, " --> empty cad using dad\n");
- ast_copy_string(p->bc->cad, p->bc->dad, sizeof(p->bc->cad));
+ if (ast_strlen_zero(p->bc->connected.number)) {
+ chan_misdn_log(2,p->bc->port," --> empty connected number using dialed number\n");
+ ast_copy_string(p->bc->connected.number, p->bc->dialed.number, sizeof(p->bc->connected.number));
+
+ /*
+ * Use the misdn_set_opt() application to set the presentation
+ * before we answer or you can use the CONECTEDLINE() function
+ * to set everything before using the Answer() application.
+ */
+ p->bc->connected.presentation = p->bc->presentation;
+ p->bc->connected.screening = 0; /* unscreened */
+ p->bc->connected.number_type = p->bc->dialed.number_type;
+ p->bc->connected.number_plan = p->bc->dialed.number_plan;
}
misdn_lib_send_event(p->bc, EVENT_CONNECT);
@@ -2628,15 +3298,15 @@ static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int dur
break;
case MISDN_CALLING_ACKNOWLEDGE:
ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
- if (strlen(bc->dad) < sizeof(bc->dad) - 1) {
- strncat(bc->dad, buf, sizeof(bc->dad) - strlen(bc->dad) - 1);
+ if (strlen(bc->dialed.number) < sizeof(bc->dialed.number) - 1) {
+ strncat(bc->dialed.number, buf, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
}
- ast_copy_string(p->ast->exten, bc->dad, sizeof(p->ast->exten));
+ ast_copy_string(p->ast->exten, bc->dialed.number, sizeof(p->ast->exten));
misdn_lib_send_event(bc, EVENT_INFORMATION);
break;
default:
/* Do not send Digits in CONNECTED State, when
- * the other side is too mISDN. */
+ * the other side is also mISDN. */
if (p->other_ch) {
return 0;
}
@@ -2687,7 +3357,7 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
switch (cond) {
case AST_CONTROL_BUSY:
- chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc->pid);
ast_setstate(ast, AST_STATE_BUSY);
p->bc->out_cause = AST_CAUSE_USER_BUSY;
@@ -2699,20 +3369,20 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
}
return -1;
case AST_CONTROL_RING:
- chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc->pid);
return -1;
case AST_CONTROL_RINGING:
- chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc->pid);
switch (p->state) {
case MISDN_ALERTING:
- chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc->pid);
break;
case MISDN_CONNECTED:
- chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc->pid);
return -1;
default:
p->state = MISDN_ALERTING;
- chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc->pid);
misdn_lib_send_event( p->bc, EVENT_ALERTING);
if (p->other_ch && p->other_ch->bc) {
@@ -2727,7 +3397,7 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
}
}
- chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc->pid);
ast_setstate(ast, AST_STATE_RING);
if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio) {
@@ -2738,28 +3408,28 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
}
break;
case AST_CONTROL_ANSWER:
- chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc->pid);
start_bc_tones(p);
break;
case AST_CONTROL_TAKEOFFHOOK:
- chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc->pid);
return -1;
case AST_CONTROL_OFFHOOK:
- chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc->pid);
return -1;
case AST_CONTROL_FLASH:
- chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc->pid);
break;
case AST_CONTROL_PROGRESS:
- chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc->pid);
misdn_lib_send_event( p->bc, EVENT_PROGRESS);
break;
case AST_CONTROL_PROCEEDING:
- chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc->pid);
misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
break;
case AST_CONTROL_CONGESTION:
- chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc->pid);
p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
start_bc_tones(p);
@@ -2770,7 +3440,7 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
}
break;
case -1 :
- chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc->pid);
stop_indicate(p);
@@ -2780,14 +3450,23 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
break;
case AST_CONTROL_HOLD:
ast_moh_start(ast, data, p->mohinterpret);
- chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc->pid);
break;
case AST_CONTROL_UNHOLD:
ast_moh_stop(ast);
- chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc->pid);
+ break;
+ case AST_CONTROL_CONNECTED_LINE:
+ chan_misdn_log(1, p->bc->port, "* IND :\tconnected line update pid:%d\n", p->bc->pid);
+ misdn_update_connected_line(ast, p->bc, p->originator);
+ break;
+ case AST_CONTROL_REDIRECTING:
+ chan_misdn_log(1, p->bc->port, "* IND :\tredirecting info update pid:%d\n", p->bc->pid);
+ misdn_copy_redirecting_from_ast(p->bc, ast);
break;
default:
- chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
+ chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid);
+ break;
}
return 0;
@@ -2814,8 +3493,10 @@ static int misdn_hangup(struct ast_channel *ast)
if (bc) {
const char *tmp;
+
ast_channel_lock(ast);
- if ((tmp = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER"))) {
+ tmp = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
+ if (tmp) {
ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
strcpy(bc->uu, tmp);
bc->uulen = strlen(bc->uu);
@@ -2875,11 +3556,17 @@ static int misdn_hangup(struct ast_channel *ast)
}
ast_channel_unlock(ast);
- chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n", p->bc ? p->bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(p));
+ chan_misdn_log(1, bc->port,
+ "* IND : HANGUP\tpid:%d context:%s dialed:%s caller:\"%s\" <%s> State:%s\n",
+ p->bc ? p->bc->pid : -1,
+ ast->context,
+ ast->exten,
+ ast->cid.cid_name ? ast->cid.cid_name : "",
+ ast->cid.cid_num ? ast->cid.cid_num : "",
+ misdn_get_ch_state(p));
chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
- chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
switch (p->state) {
case MISDN_INCOMING_SETUP:
@@ -3034,7 +3721,7 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame
ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
}
} else {
- ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
+ ast_log(LOG_NOTICE, "Fax detected but no fax extension, context:%s exten:%s\n", context, ast->exten);
}
} else {
ast_debug(1, "Already in a fax extension, not redirecting\n");
@@ -3081,7 +3768,8 @@ static struct ast_frame *misdn_read(struct ast_channel *ast)
FD_ZERO(&rrfs);
FD_SET(tmp->pipe[0], &rrfs);
- if (!(t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv))) {
+ t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv);
+ if (!t) {
chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
len = 160;
}
@@ -3249,15 +3937,11 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
return 0;
}
-
-
-
-static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
- struct ast_channel *c1, int flags,
- struct ast_frame **fo,
- struct ast_channel **rc,
- int timeoutms)
-
+static enum ast_bridge_result misdn_bridge(struct ast_channel *c0,
+ struct ast_channel *c1, int flags,
+ struct ast_frame **fo,
+ struct ast_channel **rc,
+ int timeoutms)
{
struct chan_list *ch1, *ch2;
struct ast_channel *carr[2], *who;
@@ -3293,7 +3977,11 @@ static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
- chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
+ chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between \"%s\" <%s> and \"%s\" <%s>\n",
+ ch1->bc->caller.name,
+ ch1->bc->caller.number,
+ ch2->bc->caller.name,
+ ch2->bc->caller.number);
if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) ) {
ch1->ignore_dtmf = 1;
@@ -3342,7 +4030,7 @@ static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
}
#endif
- ast_write(who == c0 ? c1 : c0, f);
+ ast_write((who == c0) ? c1 : c0, f);
}
chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
@@ -3437,7 +4125,8 @@ static struct chan_list *init_chan_list(int orig)
{
struct chan_list *cl;
- if (!(cl = ast_calloc(1, sizeof(*cl)))) {
+ cl = ast_calloc(1, sizeof(*cl));
+ if (!cl) {
chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
return NULL;
}
@@ -3455,38 +4144,54 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
{
struct ast_channel *tmp = NULL;
char group[BUFFERSIZE + 1] = "";
- char buf[128];
- char *buf2 = ast_strdupa(data), *ext = NULL, *port_str;
- char *tokb = NULL, *p = NULL;
- int channel = 0, port = 0;
+ char dial_str[128];
+ char *dest_cp;
+ char *p = NULL;
+ int channel = 0;
+ int port = 0;
struct misdn_bchannel *newbc = NULL;
int dec = 0;
+ struct chan_list *cl;
- struct chan_list *cl = init_chan_list(ORG_AST);
-
- snprintf(buf, sizeof(buf), "%s/%s", misdn_type, (char*)data);
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(intf); /* interface token */
+ AST_APP_ARG(ext); /* extension token */
+ AST_APP_ARG(opts); /* options token */
+ );
- port_str = strtok_r(buf2, "/", &tokb);
+ snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
- ext = strtok_r(NULL, "/", &tokb);
+ /*
+ * data is ---v
+ * Dial(mISDN/g:group_name[/extension[/options]])
+ * Dial(mISDN/port[:preselected_channel][/extension[/options]])
+ *
+ * The dial extension could be empty if you are using MISDN_KEYPAD
+ * to control ISDN provider features.
+ */
+ dest_cp = ast_strdupa(data);
+ AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
+ if (!args.ext) {
+ args.ext = "";
+ }
- if (port_str) {
- if (port_str[0] == 'g' && port_str[1] == ':' ) {
+ if (!ast_strlen_zero(args.intf)) {
+ if (args.intf[0] == 'g' && args.intf[1] == ':' ) {
/* We make a group call lets checkout which ports are in my group */
- port_str += 2;
- ast_copy_string(group, port_str, sizeof(group));
+ args.intf += 2;
+ ast_copy_string(group, args.intf, sizeof(group));
chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
- } else if ((p = strchr(port_str, ':'))) {
+ } else if ((p = strchr(args.intf, ':'))) {
/* we have a preselected channel */
- *p = 0;
- channel = atoi(++p);
- port = atoi(port_str);
+ *p++ = 0;
+ channel = atoi(p);
+ port = atoi(args.intf);
chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
} else {
- port = atoi(port_str);
+ port = atoi(args.intf);
}
} else {
- ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extensions.conf\n", ext);
+ ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
return NULL;
}
@@ -3579,7 +4284,8 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
chan_misdn_log(4, port, "portup:%d\n", port_up);
if (port_up > 0) {
- if ((newbc = misdn_lib_get_free_bc(port, 0, 0, dec))) {
+ newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
+ if (newbc) {
break;
}
}
@@ -3602,18 +4308,22 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
}
newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
-
if (!newbc) {
- ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
+ ast_log(LOG_WARNING, "Could not create channel on port:%d for Dial(%s)\n", port, dial_str);
return NULL;
}
}
/* create ast_channel and link all the objects together */
+ cl = init_chan_list(ORG_AST);
+ if (!cl) {
+ ast_log(LOG_WARNING, "Could not create Asterisk channel for Dial(%s)\n", dial_str);
+ return NULL;
+ }
cl->bc = newbc;
- tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
+ tmp = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, format, port, channel);
if (!tmp) {
ast_log(LOG_ERROR, "Could not create Asterisk object\n");
return NULL;
@@ -3625,7 +4335,7 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
cl_queue_chan(&cl_te, cl);
/* fill in the config into the objects */
- read_config(cl, ORG_AST);
+ read_config(cl);
/* important */
cl->need_hangup = 0;
@@ -3736,7 +4446,7 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char
tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
if (tmp) {
- chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
+ chan_misdn_log(2, 0, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid);
tmp->nativeformats = prefformat;
@@ -3791,7 +4501,11 @@ static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bc
}
}
- chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
+ chan_misdn_log(6, bc->port,
+ "$$$ find_chan_by_bc: No channel found for dialed:%s caller:\"%s\" <%s>\n",
+ bc->dialed.number,
+ bc->caller.name,
+ bc->caller.number);
return NULL;
}
@@ -3805,7 +4519,7 @@ static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
}
}
- chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
+ chan_misdn_log(6, 0, "$$$ find_chan_by_pid: No channel found for pid:%d\n", pid);
return NULL;
}
@@ -3818,7 +4532,11 @@ static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchann
return NULL;
}
- chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
+ chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d dialed:%s caller:\"%s\" <%s>\n",
+ bc->channel,
+ bc->dialed.number,
+ bc->caller.name,
+ bc->caller.number);
for (; help; help = help->next) {
chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n", help->state == MISDN_HOLDED, help->hold_info.channel);
if ((help->state == MISDN_HOLDED) &&
@@ -3826,7 +4544,11 @@ static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchann
return help;
}
}
- chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
+ chan_misdn_log(6, bc->port,
+ "$$$ find_holded: No channel found for dialed:%s caller:\"%s\" <%s>\n",
+ bc->dialed.number,
+ bc->caller.name,
+ bc->caller.number);
return NULL;
}
@@ -3947,12 +4669,14 @@ static void hangup_chan(struct chan_list *ch)
}
/** Isdn asks us to release channel, pendant to misdn_hangup **/
-static void release_chan(struct misdn_bchannel *bc) {
+static void release_chan(struct misdn_bchannel *bc)
+{
struct ast_channel *ast = NULL;
struct chan_list *ch;
ast_mutex_lock(&release_lock);
- if (!(ch = find_chan_by_bc(cl_te, bc))) {
+ ch = find_chan_by_bc(cl_te, bc);
+ if (!ch) {
chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
ast_mutex_unlock(&release_lock);
return;
@@ -3965,7 +4689,7 @@ static void release_chan(struct misdn_bchannel *bc) {
chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
/* releasing jitterbuffer */
- if (ch->jb ) {
+ if (ch->jb) {
misdn_jb_destroy(ch->jb);
ch->jb = NULL;
} else {
@@ -3993,7 +4717,14 @@ static void release_chan(struct misdn_bchannel *bc) {
close(ch->pipe[1]);
if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
- chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n", bc ? bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(ch));
+ chan_misdn_log(1, bc->port,
+ "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s> state: %s\n",
+ bc->pid,
+ ast->context,
+ ast->exten,
+ ast->cid.cid_name ? ast->cid.cid_name : "",
+ ast->cid.cid_num ? ast->cid.cid_num : "",
+ misdn_get_ch_state(ch));
chan_misdn_log(3, bc->port, " --> * State Down\n");
MISDN_ASTERISK_TECH_PVT(ast) = NULL;
@@ -4053,9 +4784,14 @@ static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch,
ch->state = MISDN_INCOMING_SETUP;
}
- chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, ast->cid.cid_num);
+ chan_misdn_log(1, bc->port,
+ "* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
+ ast->context,
+ ast->exten,
+ ast->cid.cid_name ? ast->cid.cid_name : "",
+ ast->cid.cid_num ? ast->cid.cid_num : "");
- strncpy(ast->exten, "s", 2);
+ strcpy(ast->exten, "s");
if (pbx_start_chan(ch) < 0) {
ast = NULL;
@@ -4183,6 +4919,7 @@ void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_
void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
{
char tmp[32];
+
chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
snprintf(tmp, sizeof(tmp), "%d", bc->pid);
pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
@@ -4237,7 +4974,8 @@ int add_out_calls(int port)
return 0;
}
-static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
+static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
+{
if (pbx_start_chan(ch) < 0) {
hangup_chan(ch);
chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
@@ -4250,10 +4988,11 @@ static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct as
}
}
-static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
+static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
+{
ch->state = MISDN_WAITING4DIGS;
misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
- if (bc->nt && !bc->dad[0]) {
+ if (bc->nt && !bc->dialed.number[0]) {
dialtone_indicate(ch);
}
}
@@ -4273,7 +5012,14 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
debuglevel = 5;
}
- chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch ? misdn_get_ch_state(ch) : "none");
+ chan_misdn_log(debuglevel, bc->port,
+ "I IND :%s caller:\"%s\" <%s> dialed:%s pid:%d state:%s\n",
+ manager_isdn_get_info(event),
+ bc->caller.name,
+ bc->caller.number,
+ bc->dialed.number,
+ bc->pid,
+ ch ? misdn_get_ch_state(ch) : "none");
if (debuglevel == 1) {
misdn_lib_log_ies(bc);
chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
@@ -4407,25 +5153,23 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
}
- strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
- ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
+ strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
+ ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
/* Check for Pickup Request first */
if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
if (ast_pickup_call(ch->ast)) {
hangup_chan(ch);
} else {
- struct ast_channel *chan = ch->ast;
ch->state = MISDN_CALLING_ACKNOWLEDGE;
- ast_setstate(chan, AST_STATE_DOWN);
hangup_chan(ch);
ch->ast = NULL;
break;
}
}
- if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
- if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
+ if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
+ if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc->port);
strcpy(ch->ast->exten, "i");
@@ -4459,7 +5203,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
break;
}
- if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+ if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
ch->state = MISDN_DIALING;
start_pbx(ch, bc, ch->ast);
}
@@ -4482,8 +5226,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
if (ch->state != MISDN_CONNECTED ) {
if (digits) {
- strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
- ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
+ strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
+ ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
ast_cdr_update(ch->ast);
}
@@ -4494,10 +5238,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
case EVENT_SETUP:
{
struct chan_list *ch = find_chan_by_bc(cl_te, bc);
- int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
+ int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dialed.number);
struct ast_channel *chan;
int exceed;
- int pres, screen;
int ai;
int im;
@@ -4537,10 +5280,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ch->bc = bc;
ch->l3id = bc->l3_id;
ch->addr = bc->addr;
- ch->originator = ORG_MISDN;
-
- chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
+ chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, AST_FORMAT_ALAW, bc->port, bc->channel);
if (!chan) {
misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
@@ -4555,49 +5296,44 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
}
- read_config(ch, ORG_MISDN);
+ read_config(ch);
export_ch(chan, bc, ch);
ch->ast->rings = 1;
ast_setstate(ch->ast, AST_STATE_RINGING);
- switch (bc->pres) {
- case 1:
- pres = AST_PRES_RESTRICTED;
- chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
- break;
- case 2:
- pres = AST_PRES_UNAVAILABLE;
- chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
- break;
- default:
- pres = AST_PRES_ALLOWED;
- chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
- break;
- }
+ /* Update asterisk channel caller information */
+ chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
+ chan_misdn_log(2, bc->port, " --> PLAN: %s(%d)\n", misdn_to_str_plan(bc->caller.number_plan), bc->caller.number_plan);
+ chan->cid.cid_ton = misdn_to_ast_ton(bc->caller.number_type)
+ | misdn_to_ast_plan(bc->caller.number_plan);
- switch (bc->screen) {
- default:
- case 0:
- screen = AST_PRES_USER_NUMBER_UNSCREENED;
- chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
- break;
- case 1:
- screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
- chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
- break;
- case 2:
- screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
- chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
- break;
- case 3:
- screen = AST_PRES_NETWORK_NUMBER;
- chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
- break;
- }
+ chan_misdn_log(2, bc->port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
+ chan_misdn_log(2, bc->port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
+ chan->cid.cid_pres = misdn_to_ast_pres(bc->caller.presentation)
+ | misdn_to_ast_screen(bc->caller.screening);
+
+ ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number);
+
+ if (!ast_strlen_zero(bc->redirecting.from.number)) {
+ struct ast_party_redirecting redirecting;
- chan->cid.cid_pres = pres | screen;
+ /* Add configured prefix to redirecting.from.number */
+ misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type, bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
+
+ /* Update asterisk channel redirecting information */
+ ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
+ redirecting.from.number = bc->redirecting.from.number;
+ redirecting.from.number_type =
+ misdn_to_ast_ton(bc->redirecting.from.number_type)
+ | misdn_to_ast_plan(bc->redirecting.from.number_plan);
+ redirecting.from.number_presentation =
+ misdn_to_ast_pres(bc->redirecting.from.presentation)
+ | misdn_to_ast_screen(bc->redirecting.from.screening);
+ redirecting.reason = misdn_to_ast_reason(bc->redirecting.reason);
+ ast_channel_set_redirecting(chan, &redirecting);
+ }
pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
chan->transfercapability = bc->capability;
@@ -4627,7 +5363,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
break;
}
}
- } /* end for */
+ }
if (i == ARRAY_LEN(allowed_bearers_array)) {
/* We did not find the bearer capability */
chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
@@ -4652,7 +5388,6 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
hangup_chan(ch);
} else {
ch->state = MISDN_CALLING_ACKNOWLEDGE;
- ast_setstate(chan, AST_STATE_DOWN);
hangup_chan(ch);
ch->ast = NULL;
break;
@@ -4669,16 +5404,16 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
break;
}
- /* check if we should jump into s when we have no dad */
+ /* check if we should jump into s when we have no dialed.number */
misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
- if (im && ast_strlen_zero(bc->dad)) {
+ if (im && ast_strlen_zero(bc->dialed.number)) {
do_immediate_setup(bc, ch, chan);
break;
}
chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
- if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
- if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
+ if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
+ if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc->port);
strcpy(ch->ast->exten, "i");
misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
@@ -4722,7 +5457,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
* the number is empty, we wait for the ISDN timeout
* instead of our own timer.
*/
- if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
+ if (ch->overlap_dial && bc->nt && !bc->dialed.number[0] ) {
wait_for_digits(ch, bc, chan);
break;
}
@@ -4747,7 +5482,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
/* If the extension does not exist and we're not TE_PTMP we wait for more digits
* without interdigit timeout.
* */
- if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+ if (!ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
wait_for_digits(ch, bc, chan);
break;
}
@@ -4755,29 +5490,30 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
/*
* If the extension exists let's just jump into it.
* */
- if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+ if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
misdn_lib_send_event(bc, bc->need_more_infos ? EVENT_SETUP_ACKNOWLEDGE : EVENT_PROCEEDING);
ch->state = MISDN_DIALING;
start_pbx(ch, bc, chan);
break;
}
- }
break;
+ }
case EVENT_SETUP_ACKNOWLEDGE:
ch->state = MISDN_CALLING_ACKNOWLEDGE;
- if (bc->channel)
+ if (bc->channel) {
update_name(ch->ast,bc->port,bc->channel);
+ }
if (!ast_strlen_zero(bc->infos_pending)) {
/* TX Pending Infos */
- strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
+ strncat(bc->dialed.number, bc->infos_pending, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
if (!ch->ast) {
break;
}
- ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
+ ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
@@ -4842,29 +5578,31 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
}
break;
case EVENT_CONNECT:
- {
- struct ast_channel *bridged;
+ {
+ struct ast_party_connected_line connected;
- /*we answer when we've got our very new L3 ID from the NT stack */
- misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
+ /* we answer when we've got our very new L3 ID from the NT stack */
+ misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
- if (!ch->ast) {
- break;
- }
+ if (!ch->ast) {
+ break;
+ }
- bridged = ast_bridged_channel(ch->ast);
- stop_indicate(ch);
+ stop_indicate(ch);
- if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
- struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
+ /* Add configured prefix to connected.number */
+ misdn_add_number_prefix(bc->port, bc->connected.number_type, bc->connected.number, sizeof(bc->connected.number));
+
+ /* Update the connected line information on the other channel */
+ ast_party_connected_line_init(&connected);
+ connected.id.number = bc->connected.number;
+ connected.id.number_type = misdn_to_ast_ton(bc->connected.number_type)
+ | misdn_to_ast_plan(bc->connected.number_plan);
+ connected.id.number_presentation = misdn_to_ast_pres(bc->connected.presentation)
+ | misdn_to_ast_screen(bc->connected.screening);
+ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
+ ast_channel_queue_connected_line_update(ch->ast, &connected);
- chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
- if (bridged_ch) {
- bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
- ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
- }
- }
- }
ch->l3id = bc->l3_id;
ch->addr = bc->addr;
@@ -4874,6 +5612,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
break;
+ }
case EVENT_CONNECT_ACKNOWLEDGE:
ch->l3id = bc->l3_id;
ch->addr = bc->addr;
@@ -4947,8 +5686,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
stop_bc_tones(ch);
hangup_chan(ch);
- if (ch)
+ if (ch) {
ch->state = MISDN_CLEANING;
+ }
release_chan(bc);
break;
@@ -5003,16 +5743,16 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
} else {
bc->tone_cnt = 0;
}
- }
break;
-
+ }
case EVENT_BCHAN_DATA:
if (ch->bc->AOCD_need_export) {
export_aoc_vars(ch->originator, ch->ast, ch->bc);
}
if (!misdn_cap_is_speech(ch->bc->capability)) {
struct ast_frame frame;
- /*In Data Modes we queue frames*/
+
+ /* In Data Modes we queue frames */
frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
frame.subclass = AST_FORMAT_ALAW;
frame.datalen = bc->bframe_len;
@@ -5023,8 +5763,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
frame.src = NULL;
frame.data.ptr = bc->bframe;
- if (ch->ast)
+ if (ch->ast) {
ast_queue_frame(ch->ast, &frame);
+ }
} else {
fd_set wrfs;
struct timeval tv = { 0, 0 };
@@ -5099,6 +5840,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
break;
default:
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
+ break;
}
break;
@@ -5137,8 +5879,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
}
- }
break;
+ }
case EVENT_HOLD:
{
int hold_allowed;
@@ -5171,8 +5913,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
}
- }
break;
+ }
case EVENT_FACILITY:
print_facility(&(bc->fac_in), bc);
@@ -5189,7 +5931,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
/*ch->state = MISDN_FACILITY_DEFLECTED;*/
if (ch_br->bc) {
- if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
+ if (ast_exists_extension(bridged, ch->context, (char *) bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->caller.number)) {
ch_br->state = MISDN_DIALING;
if (pbx_start_chan(ch_br) < 0) {
chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
@@ -5461,6 +6203,7 @@ static int misdn_facility_exec(struct ast_channel *chan, void *data)
{
struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
char *parse;
+
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(facility_type);
AST_APP_ARG(arg)[99];
@@ -5473,7 +6216,7 @@ static int misdn_facility_exec(struct ast_channel *chan, void *data)
return -1;
}
- if (ast_strlen_zero((char *)data)) {
+ if (ast_strlen_zero((char *) data)) {
ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
return -1;
}
@@ -5492,7 +6235,9 @@ static int misdn_facility_exec(struct ast_channel *chan, void *data)
}
if (strlen(args.arg[0]) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
- ast_log(LOG_WARNING, "Facility: Number argument too long (up to %d digits are allowed). Ignoring.\n", (int)sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
+ ast_log(LOG_WARNING,
+ "Facility: Number argument too long (up to %d digits are allowed). Ignoring.\n",
+ (int) sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
return 0;
}
ch->bc->fac_out.Function = Fac_CD;
@@ -5516,11 +6261,11 @@ static int misdn_check_l2l1(struct ast_channel *chan, void *data)
int port_up;
AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(grouppar);
- AST_APP_ARG(timeout);
+ AST_APP_ARG(grouppar);
+ AST_APP_ARG(timeout);
);
- if (ast_strlen_zero((char *)data)) {
+ if (ast_strlen_zero((char *) data)) {
ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
return -1;
}
@@ -5543,7 +6288,7 @@ static int misdn_check_l2l1(struct ast_channel *chan, void *data)
ast_copy_string(group, port_str, sizeof(group));
chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
- for ( port = misdn_cfg_get_next_port(port);
+ for (port = misdn_cfg_get_next_port(port);
port > 0;
port = misdn_cfg_get_next_port(port)) {
char cfg_group[BUFFERSIZE + 1];
@@ -5554,7 +6299,6 @@ static int misdn_check_l2l1(struct ast_channel *chan, void *data)
if (!strcasecmp(cfg_group, group)) {
port_up = misdn_lib_port_up(port, 1);
-
if (!port_up) {
chan_misdn_log(2, 0, " --> port '%d'\n", port);
misdn_lib_get_port_up(port);
@@ -5752,12 +6496,15 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
/* CRICH: callingpres!!! */
if (strstr(tok, "allowed")) {
- ch->bc->pres = 0;
+ ch->bc->presentation = 0;
+ ch->bc->set_presentation = 1;
} else if (strstr(tok, "restricted")) {
- ch->bc->pres = 1;
+ ch->bc->presentation = 1;
+ ch->bc->set_presentation = 1;
} else if (strstr(tok, "not_screened")) {
chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
- ch->bc->pres = 1;
+ ch->bc->presentation = 1;
+ ch->bc->set_presentation = 1;
}
break;
case 'i' :
@@ -5975,16 +6722,10 @@ int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
return read;
}
-
-
-
/*******************************************************/
/*************** JITTERBUFFER END *********************/
/*******************************************************/
-
-
-
static void chan_misdn_log(int level, int port, char *tmpl, ...)
{
va_list ap;
@@ -6005,7 +6746,6 @@ static void chan_misdn_log(int level, int port, char *tmpl, ...)
if (level == -1) {
ast_log(LOG_WARNING, "%s", buf);
-
} else if (misdn_debug_only[port] ?
(level == 1 && misdn_debug[port]) || (level == misdn_debug[port])
: level <= misdn_debug[port]) {
@@ -6021,7 +6761,8 @@ static void chan_misdn_log(int level, int port, char *tmpl, ...)
FILE *fp = fopen(global_tracefile, "a+");
- if ((p = strchr(tmp, '\n'))) {
+ p = strchr(tmp, '\n');
+ if (p) {
*p = ':';
}
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index 82a37cc36..dd1578cb8 100644
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -303,13 +303,13 @@ static int phone_call(struct ast_channel *ast, char *dest, int timeout)
snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min);
}
/* the standard format of ast->callerid is: "name" <number>, but not always complete */
- if (ast_strlen_zero(ast->cid.cid_name))
+ if (ast_strlen_zero(ast->connected.id.name))
strcpy(cid.name, DEFAULT_CALLER_ID);
else
- ast_copy_string(cid.name, ast->cid.cid_name, sizeof(cid.name));
+ ast_copy_string(cid.name, ast->connected.id.name, sizeof(cid.name));
- if (ast->cid.cid_num)
- ast_copy_string(cid.number, ast->cid.cid_num, sizeof(cid.number));
+ if (ast->connected.id.number)
+ ast_copy_string(cid.number, ast->connected.id.number, sizeof(cid.number));
p = ast->tech_pvt;
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 4fb164f9c..10883c5f3 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -942,6 +942,54 @@ static const struct cfsip_options {
{ SIP_OPT_TARGET_DIALOG,NOT_SUPPORTED, "tdialog" },
};
+/*! \brief Diversion header reasons
+ *
+ * The core defines a bunch of constants used to define
+ * redirecting reasons. This provides a translation table
+ * between those and the strings which may be present in
+ * a SIP Diversion header
+ */
+static const struct sip_reasons {
+ enum AST_REDIRECTING_REASON code;
+ char * const text;
+} sip_reason_table[] = {
+ { AST_REDIRECTING_REASON_UNKNOWN, "unknown" },
+ { AST_REDIRECTING_REASON_USER_BUSY, "user-busy" },
+ { AST_REDIRECTING_REASON_NO_ANSWER, "no-answer" },
+ { AST_REDIRECTING_REASON_UNAVAILABLE, "unavailable" },
+ { AST_REDIRECTING_REASON_UNCONDITIONAL, "unconditional" },
+ { AST_REDIRECTING_REASON_TIME_OF_DAY, "time-of-day" },
+ { AST_REDIRECTING_REASON_DO_NOT_DISTURB, "do-not-disturb" },
+ { AST_REDIRECTING_REASON_DEFLECTION, "deflection" },
+ { AST_REDIRECTING_REASON_FOLLOW_ME, "follow-me" },
+ { AST_REDIRECTING_REASON_OUT_OF_ORDER, "out-of-service" },
+ { AST_REDIRECTING_REASON_AWAY, "away" },
+ { AST_REDIRECTING_REASON_CALL_FWD_DTE, "unknown"}
+};
+
+static enum AST_REDIRECTING_REASON sip_reason_str_to_code(const char *text)
+{
+ enum AST_REDIRECTING_REASON ast = AST_REDIRECTING_REASON_UNKNOWN;
+ int i;
+
+ for (i = 0; i < ARRAY_LEN(sip_reason_table); ++i) {
+ if (!strcasecmp(text, sip_reason_table[i].text)) {
+ ast = sip_reason_table[i].code;
+ break;
+ }
+ }
+
+ return ast;
+}
+
+static const char *sip_reason_code_to_str(enum AST_REDIRECTING_REASON code)
+{
+ if (code >= 0 && code < ARRAY_LEN(sip_reason_table)) {
+ return sip_reason_table[code].text;
+ }
+
+ return "unknown";
+}
/*! \brief SIP Methods we support
\todo This string should be set dynamically. We only support REFER and SUBSCRIBE if we have
@@ -1354,7 +1402,10 @@ struct sip_auth {
#define SIP_PROG_INBAND_NO (1 << 25)
#define SIP_PROG_INBAND_YES (2 << 25)
-#define SIP_SENDRPID (1 << 29) /*!< DP: Remote Party-ID Support */
+#define SIP_SENDRPID (3 << 29) /*!< DP: Remote Party-ID Support */
+#define SIP_SENDRPID_NO (0 << 29)
+#define SIP_SENDRPID_PAI (1 << 29) /*!< Use "P-Asserted-Identity" for rpid */
+#define SIP_SENDRPID_RPID (2 << 29) /*!< Use "Remote-Party-ID" for rpid */
#define SIP_G726_NONSTANDARD (1 << 31) /*!< DP: Use non-standard packing for G726-32 data */
/*! \brief Flags to copy from peer/user to dialog */
@@ -1373,6 +1424,9 @@ struct sip_auth {
/* Space for addition of other realtime flags in the future */
#define SIP_PAGE2_STATECHANGEQUEUE (1 << 9) /*!< D: Unsent state pending change exists */
+#define SIP_PAGE2_CONNECTLINEUPDATE_PEND (1 << 10)
+#define SIP_PAGE2_RPID_IMMEDIATE (1 << 11)
+
#define SIP_PAGE2_PREFERRED_CODEC (1 << 13) /*!< GDP: Only respond with single most preferred joint codec */
#define SIP_PAGE2_VIDEOSUPPORT (1 << 14) /*!< DP: Video supported if offered? */
#define SIP_PAGE2_TEXTSUPPORT (1 << 15) /*!< GDP: Global text enable */
@@ -1403,7 +1457,8 @@ struct sip_auth {
(SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_IGNORESDPVERSION | \
SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | \
SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_TEXTSUPPORT | SIP_PAGE2_FAX_DETECT | \
- SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_PREFERRED_CODEC)
+ SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_PREFERRED_CODEC | \
+ SIP_PAGE2_RPID_IMMEDIATE)
/*@}*/
@@ -1611,8 +1666,6 @@ struct sip_pvt {
AST_STRING_FIELD(fullcontact); /*!< The Contact: that the UA registers with us */
/* we only store the part in <brackets> in this field. */
AST_STRING_FIELD(our_contact); /*!< Our contact header */
- AST_STRING_FIELD(rpid); /*!< Our RPID header */
- AST_STRING_FIELD(rpid_from); /*!< Our RPID From header */
AST_STRING_FIELD(url); /*!< URL to be sent with next message to peer */
AST_STRING_FIELD(parkinglot); /*!< Parkinglot */
AST_STRING_FIELD(engine); /*!< RTP engine to use */
@@ -2237,7 +2290,7 @@ static int transmit_response_using_temp(ast_string_field callid, struct sockaddr
static int transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req);
static int transmit_response_reliable(struct sip_pvt *p, const char *msg, const struct sip_request *req);
static int transmit_response_with_date(struct sip_pvt *p, const char *msg, const struct sip_request *req);
-static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp);
+static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp, int rpid);
static int transmit_response_with_unsupported(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported);
static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale);
static int transmit_response_with_allow(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
@@ -2258,7 +2311,7 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmitty
static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
static void copy_request(struct sip_request *dst, const struct sip_request *src);
static void receive_message(struct sip_pvt *p, struct sip_request *req);
-static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req);
+static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward);
static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *event, int cache_only);
/*--- Dialog management */
@@ -2506,11 +2559,14 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req);
static int set_address_from_contact(struct sip_pvt *pvt);
static void check_via(struct sip_pvt *p, struct sip_request *req);
static char *get_calleridname(const char *input, char *output, size_t outputsize);
-static int get_rpid_num(const char *input, char *output, int maxlen);
-static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq);
+static int get_rpid(struct sip_pvt *p, struct sip_request *oreq);
+static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason);
static int get_destination(struct sip_pvt *p, struct sip_request *oreq);
static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewline);
static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout);
+static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
+static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen);
+static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, int set_call_forward);
/*-- TCP connection handling ---*/
static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session);
@@ -2537,6 +2593,7 @@ static int add_header_contentLength(struct sip_request *req, int len);
static int add_line(struct sip_request *req, const char *line);
static int add_text(struct sip_request *req, const char *text);
static int add_digit(struct sip_request *req, char digit, unsigned int duration, int mode);
+static int add_rpid(struct sip_request *req, struct sip_pvt *p);
static int add_vidupdate(struct sip_request *req);
static void add_route(struct sip_request *req, struct sip_route *route);
static int copy_header(struct sip_request *req, const struct sip_request *orig, const char *field);
@@ -2545,7 +2602,6 @@ static int copy_via_headers(struct sip_pvt *p, struct sip_request *req, const st
static void set_destination(struct sip_pvt *p, char *uri);
static void append_date(struct sip_request *req);
static void build_contact(struct sip_pvt *p);
-static void build_rpid(struct sip_pvt *p);
/*------Request handling functions */
static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *recount, int *nounlock);
@@ -4808,6 +4864,8 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
ast_string_field_set(dialog, tohost, peer->tohost);
ast_string_field_set(dialog, fullcontact, peer->fullcontact);
ast_string_field_set(dialog, context, peer->context);
+ ast_string_field_set(dialog, cid_num, peer->cid_num);
+ ast_string_field_set(dialog, cid_name, peer->cid_name);
ast_string_field_set(dialog, parkinglot, peer->parkinglot);
ast_string_field_set(dialog, engine, peer->engine);
ref_proxy(dialog, obproxy_get(dialog, peer));
@@ -5072,11 +5130,13 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
p->t38.jointcapability = p->t38.capability;
ast_debug(2, "Our T38 capability (%d), joint T38 capability (%d)\n", p->t38.capability, p->t38.jointcapability);
+ sip_pvt_lock(p);
xmitres = transmit_invite(p, SIP_INVITE, 1, 2);
+ sip_pvt_unlock(p);
if (xmitres == XMIT_ERROR)
return -1;
p->invitestate = INV_CALLING;
-
+
/* Initialize auto-congest time */
AST_SCHED_REPLACE_UNREF(p->initid, sched, p->timer_b, auto_congest, p,
dialog_unref(_data, "dialog ptr dec when SCHED_REPLACE del op succeeded"),
@@ -5810,7 +5870,7 @@ static int sip_answer(struct ast_channel *ast)
change_t38_state(p, T38_ENABLED);
}
ast_rtp_instance_new_source(p->rtp);
- res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE);
+ res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE, TRUE);
ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
}
sip_pvt_unlock(p);
@@ -5846,8 +5906,8 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
!ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
ast_rtp_instance_new_source(p->rtp);
p->invitestate = INV_EARLY_MEDIA;
- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
} else if (p->t38.state == T38_ENABLED && !p->t38.direct) {
change_t38_state(p, T38_DISABLED);
transmit_reinvite_with_sdp(p, FALSE, FALSE);
@@ -5868,8 +5928,8 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
!ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
p->invitestate = INV_EARLY_MEDIA;
- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
}
p->lastrtptx = time(NULL);
res = ast_rtp_instance_write(p->vrtp, frame);
@@ -5889,8 +5949,8 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
!ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
p->invitestate = INV_EARLY_MEDIA;
- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
}
p->lastrtptx = time(NULL);
res = ast_rtp_instance_write(p->trtp, frame);
@@ -6109,8 +6169,8 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
!ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
p->invitestate = INV_EARLY_MEDIA;
- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
break;
}
res = -1;
@@ -6168,6 +6228,12 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
case AST_CONTROL_SRCUPDATE:
ast_rtp_instance_new_source(p->rtp);
break;
+ case AST_CONTROL_CONNECTED_LINE:
+ update_connectedline(p, data, datalen);
+ break;
+ case AST_CONTROL_REDIRECTING:
+ update_redirecting(p, data, datalen);
+ break;
case -1:
res = -1;
break;
@@ -8709,9 +8775,6 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in
if (!ast_strlen_zero(global_useragent))
add_header(req, "User-Agent", global_useragent);
- if (!ast_strlen_zero(p->rpid))
- add_header(req, "Remote-Party-ID", p->rpid);
-
if (!ast_strlen_zero(p->url)) {
add_header(req, "Access-URL", p->url);
ast_string_field_set(p, url, NULL);
@@ -8749,6 +8812,14 @@ static int __transmit_response(struct sip_pvt *p, const char *msg, const struct
return -1;
}
respprep(&resp, p, msg, req);
+
+ if (ast_test_flag(&p->flags[0], SIP_SENDRPID)
+ && ast_test_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND)
+ && (!strncmp(msg, "180", 3) || !strncmp(msg, "183", 3))) {
+ ast_clear_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND);
+ add_rpid(&resp, p);
+ }
+
add_header_contentLength(&resp, 0);
/* If we are cancelling an incoming invite for some reason, add information
about the reason why we are doing this in clear text */
@@ -8968,6 +9039,89 @@ static int add_digit(struct sip_request *req, char digit, unsigned int duration,
return 0;
}
+/*!
+ * \pre if p->owner exists, it must be locked
+ * \brief Add Remote-Party-ID header to SIP message
+ */
+static int add_rpid(struct sip_request *req, struct sip_pvt *p)
+{
+ struct ast_str *tmp = ast_str_alloca(256);
+ char *lid_num = NULL;
+ char *lid_name = NULL;
+ int lid_pres;
+ const char *fromdomain;
+ const char *privacy = NULL;
+ const char *screen = NULL;
+ const char *anonymous_string = "\"Anonymous\" <anonymous@anonymous.invalid>";
+
+ if (!ast_test_flag(&p->flags[0], SIP_SENDRPID)) {
+ return 0;
+ }
+
+ if (p->owner && p->owner->connected.id.number)
+ lid_num = p->owner->connected.id.number;
+ if (p->owner && p->owner->connected.id.name)
+ lid_name = p->owner->connected.id.name;
+ lid_pres = (p->owner) ? p->owner->connected.id.number_presentation : AST_PRES_NUMBER_NOT_AVAILABLE;
+
+ if (ast_strlen_zero(lid_num))
+ return 0;
+ if (ast_strlen_zero(lid_name))
+ lid_name = lid_num;
+ fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr));
+
+ if (ast_test_flag(&p->flags[0], SIP_SENDRPID_PAI)) {
+ if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) {
+ ast_str_set(&tmp, -1, "%s", anonymous_string);
+ } else {
+ ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>", lid_name, lid_num, fromdomain);
+ }
+ add_header(req, "P-Asserted-Identity", ast_str_buffer(tmp));
+ } else {
+ ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>;party=%s", lid_name, lid_num, fromdomain, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "calling" : "called");
+
+ switch (lid_pres) {
+ case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
+ case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
+ privacy = "off";
+ screen = "no";
+ break;
+ case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
+ case AST_PRES_ALLOWED_NETWORK_NUMBER:
+ privacy = "off";
+ screen = "yes";
+ break;
+ case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
+ case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
+ privacy = "full";
+ screen = "no";
+ break;
+ case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
+ case AST_PRES_PROHIB_NETWORK_NUMBER:
+ privacy = "full";
+ screen = "yes";
+ break;
+ case AST_PRES_NUMBER_NOT_AVAILABLE:
+ break;
+ default:
+ if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) {
+ privacy = "full";
+ }
+ else
+ privacy = "off";
+ screen = "no";
+ break;
+ }
+
+ if (!ast_strlen_zero(privacy) && !ast_strlen_zero(screen)) {
+ ast_str_append(&tmp, -1, ";privacy=%s;screen=%s", privacy, screen);
+ }
+
+ add_header(req, "Remote-Party-ID", ast_str_buffer(tmp));
+ }
+ return 0;
+}
+
/*! \brief add XML encoded media control with update
\note XML: The only way to turn 0 bits of information into a few hundred. (markster) */
static int add_vidupdate(struct sip_request *req)
@@ -9581,7 +9735,7 @@ static void copy_request(struct sip_request *dst, const struct sip_request *src)
/*! \brief Used for 200 OK and 183 early media
\return Will return XMIT_ERROR for network errors.
*/
-static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp)
+static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp, int rpid)
{
struct sip_request resp;
int seqno;
@@ -9590,6 +9744,9 @@ static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const
return -1;
}
respprep(&resp, p, msg, req);
+ if (rpid == TRUE) {
+ add_rpid(&resp, p);
+ }
if (p->rtp) {
if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
ast_debug(1, "Setting framing from config on incoming call\n");
@@ -9739,85 +9896,6 @@ static void build_contact(struct sip_pvt *p)
}
}
-/*! \brief Build the Remote Party-ID & From using callingpres options */
-static void build_rpid(struct sip_pvt *p)
-{
- int send_pres_tags = TRUE;
- const char *privacy=NULL;
- const char *screen=NULL;
- char buf[256];
- const char *clid = default_callerid;
- const char *clin = NULL;
- const char *fromdomain;
-
- if (!ast_strlen_zero(p->rpid) || !ast_strlen_zero(p->rpid_from))
- return;
-
- if (p->owner && p->owner->cid.cid_num)
- clid = p->owner->cid.cid_num;
- if (p->owner && p->owner->cid.cid_name)
- clin = p->owner->cid.cid_name;
- if (ast_strlen_zero(clin))
- clin = clid;
-
- switch (p->callingpres) {
- case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
- privacy = "off";
- screen = "no";
- break;
- case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
- privacy = "off";
- screen = "yes";
- break;
- case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
- privacy = "off";
- screen = "no";
- break;
- case AST_PRES_ALLOWED_NETWORK_NUMBER:
- privacy = "off";
- screen = "yes";
- break;
- case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
- privacy = "full";
- screen = "no";
- break;
- case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
- privacy = "full";
- screen = "yes";
- break;
- case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
- privacy = "full";
- screen = "no";
- break;
- case AST_PRES_PROHIB_NETWORK_NUMBER:
- privacy = "full";
- screen = "yes";
- break;
- case AST_PRES_NUMBER_NOT_AVAILABLE:
- send_pres_tags = FALSE;
- break;
- default:
- ast_log(LOG_WARNING, "Unsupported callingpres (%d)\n", p->callingpres);
- if ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)
- privacy = "full";
- else
- privacy = "off";
- screen = "no";
- break;
- }
-
- fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr));
-
- snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain);
- if (send_pres_tags)
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ";privacy=%s;screen=%s", privacy, screen);
- ast_string_field_set(p, rpid, buf);
-
- ast_string_field_build(p, rpid_from, "\"%s\" <sip:%s@%s>;tag=%s", clin,
- S_OR(p->fromuser, clid),
- fromdomain, p->tag);
-}
-
/*! \brief Initiate new SIP request to peer/user */
static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod)
{
@@ -9853,15 +9931,9 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text);
- if (p->owner) {
- l = p->owner->cid.cid_num;
- n = p->owner->cid.cid_name;
- }
- /* if we are not sending RPID and user wants his callerid restricted */
- if (!ast_test_flag(&p->flags[0], SIP_SENDRPID) &&
- ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)) {
- l = CALLERID_UNKNOWN;
- n = l;
+ if (p->owner && (p->owner->connected.id.number_presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
+ l = p->owner->connected.id.number;
+ n = p->owner->connected.id.name;
}
if (ast_strlen_zero(l))
l = default_callerid;
@@ -9950,12 +10022,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
/* SLD: FIXME?: do Route: here too? I think not cos this is the first request.
* OTOH, then we won't have anything in p->route anyway */
- /* Build Remote Party-ID and From */
- if (ast_test_flag(&p->flags[0], SIP_SENDRPID) && (sipmethod == SIP_INVITE)) {
- build_rpid(p);
- add_header(req, "From", p->rpid_from);
- } else
- add_header(req, "From", from);
+ add_header(req, "From", from);
add_header(req, "To", to);
ast_string_field_set(p, exten, l);
build_contact(p);
@@ -9964,8 +10031,44 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
add_header(req, "CSeq", tmp_n);
if (!ast_strlen_zero(global_useragent))
add_header(req, "User-Agent", global_useragent);
- if (!ast_strlen_zero(p->rpid))
- add_header(req, "Remote-Party-ID", p->rpid);
+}
+
+/*! \brief Add "Diversion" header to outgoing message
+ *
+ * We need to add a Diversion header if the owner channel of
+ * this dialog has redirecting information associated with it.
+ *
+ * \param req The request/response to which we will add the header
+ * \param pvt The sip_pvt which represents the call-leg
+ * \param apr Redirecting data used to make the diversion header
+ */
+static void add_diversion_header(struct sip_request *req, struct sip_pvt *pvt)
+{
+ const char *diverting_number;
+ const char *diverting_name;
+ const char *reason;
+ char header_text[256];
+
+ if (!pvt->owner) {
+ return;
+ }
+
+ diverting_number = pvt->owner->cid.cid_rdnis;
+ diverting_name = pvt->owner->redirecting.from.name;
+ reason = sip_reason_code_to_str(pvt->owner->redirecting.reason);
+
+ if (ast_strlen_zero(diverting_number)) {
+ return;
+ }
+
+ /* We at least have a number to place in the Diversion header, which is enough */
+ if (ast_strlen_zero(diverting_name)) {
+ snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_number, ast_inet_ntoa(pvt->ourip.sin_addr), reason);
+ } else {
+ snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s", diverting_name, diverting_number, ast_inet_ntoa(pvt->ourip.sin_addr), reason);
+ }
+
+ add_header(req, "Diversion", header_text);
}
/*! \brief Build REFER/INVITE/OPTIONS/SUBSCRIBE message and transmit it
@@ -10086,6 +10189,11 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
ast_channel_unlock(chan);
}
+ if ((sipmethod == SIP_INVITE || sipmethod == SIP_UPDATE) && ast_test_flag(&p->flags[0], SIP_SENDRPID))
+ add_rpid(&req, p);
+ if (sipmethod == SIP_INVITE) {
+ add_diversion_header(&req, p);
+ }
if (sdp) {
if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) {
ast_udptl_offered_from_local(p->udptl, 1);
@@ -10568,6 +10676,80 @@ static char mandescr_sipnotify[] =
" *Variable: <name>=<value> At least one variable pair must be specified.\n"
" ActionID: <id> Action ID for this transaction. Will be returned.\n";
+/*! \brief Send a provisional response indicating that a call was redirected
+ */
+static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen)
+{
+ struct sip_request resp;
+
+ if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ return;
+ }
+
+ if (!ast_strlen_zero(p->owner->redirecting.to.number)) {
+ ast_string_field_set(p, exten, p->owner->redirecting.to.number);
+ build_contact(p);
+ }
+ respprep(&resp, p, "181 Call is being forwarded", &p->initreq);
+ add_diversion_header(&resp, p);
+ send_response(p, &resp, XMIT_UNRELIABLE, 0);
+}
+
+/*! \brief Notify peer that the connected line has changed */
+static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen)
+{
+
+ if (!ast_test_flag(&p->flags[0], SIP_SENDRPID))
+ return;
+ if (ast_strlen_zero(p->owner->connected.id.number))
+ return;
+
+ append_history(p, "ConnectedLine", "%s party is now %s <%s>", ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "Calling" : "Called", p->owner->connected.id.name, p->owner->connected.id.number);
+
+ if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ struct sip_request req;
+
+ if (p->invitestate == INV_CONFIRMED || p->invitestate == INV_TERMINATED) {
+ reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ? SIP_UPDATE : SIP_INVITE, 0, 1);
+
+ add_header(&req, "Allow", ALLOWED_METHODS);
+ add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
+ add_rpid(&req, p);
+ add_sdp(&req, p, FALSE, TRUE, FALSE);
+
+ initialize_initreq(p, &req);
+ p->lastinvite = p->ocseq;
+ ast_set_flag(&p->flags[0], SIP_OUTGOING);
+ send_request(p, &req, XMIT_CRITICAL, p->ocseq);
+ } else {
+ reqprep(&req, p, SIP_UPDATE, 0, 1);
+ add_rpid(&req, p);
+ add_header_contentLength(&req, 0);
+ send_request(p, &req, XMIT_CRITICAL, p->ocseq);
+ }
+ } else {
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_RPID_IMMEDIATE)) {
+ struct sip_request resp;
+
+ if ((p->owner->_state == AST_STATE_RING) && !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT)) {
+ respprep(&resp, p, "180 Ringing", &p->initreq);
+ add_rpid(&resp, p);
+ send_response(p, &resp, XMIT_UNRELIABLE, 0);
+ ast_set_flag(&p->flags[0], SIP_RINGING);
+ } else if (p->owner->_state == AST_STATE_RINGING) {
+ respprep(&resp, p, "183 Session Progress", &p->initreq);
+ add_rpid(&resp, p);
+ send_response(p, &resp, XMIT_UNRELIABLE, 0);
+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+ } else {
+ ast_log(LOG_DEBUG, "Unable able to send update to '%s' in state '%s'\n", p->owner->name, ast_state2str(p->owner->_state));
+ }
+ } else {
+ ast_set_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND);
+ }
+ }
+}
+
static const struct _map_x_s regstatestrings[] = {
{ REG_STATE_FAILED, "Failed" },
{ REG_STATE_UNREGISTERED, "Unregistered"},
@@ -10595,7 +10777,7 @@ static const char *regstate2str(enum sipregistrystate regstate)
static int sip_reregister(const void *data)
{
/* if we are here, we know that we need to reregister. */
- struct sip_registry *r= (struct sip_registry *) data;
+ struct sip_registry *r = (struct sip_registry *) data;
/* if we couldn't get a reference to the registry object, punt */
if (!r)
@@ -12260,23 +12442,199 @@ static void sip_set_redirstr(struct sip_pvt *p, char *reason) {
}
}
+/*! \brief Parse the parts of the P-Asserted-Identity header
+ * on an incoming packet. Returns 1 if a valid header is found
+ * and it is different from the current caller id.
+ */
+static int get_pai(struct sip_pvt *p, struct sip_request *req)
+{
+ char pai[256];
+ char privacy[64];
+ char *cid_num = "";
+ char *cid_name = "";
+ int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+ char *start = NULL, *end = NULL;
+
+ ast_copy_string(pai, get_header(req, "P-Asserted-Identity"), sizeof(pai));
+
+ if (ast_strlen_zero(pai)) {
+ return 0;
+ }
+
+ start = pai;
+ if (*start == '"') {
+ *start++ = '\0';
+ end = strchr(start, '"');
+ if (!end)
+ return 0;
+ *end++ = '\0';
+ cid_name = start;
+ start = ast_skip_blanks(end);
+ }
+
+ if (*start != '<')
+ return 0;
+ *start++ = '\0';
+ end = strchr(start, '@');
+ if (!end)
+ return 0;
+ *end++ = '\0';
+ if (!strncasecmp(start, "anonymous@anonymous.invalid", 27)) {
+ callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+ /*XXX Assume no change in cid_num. Perhaps it should be
+ * blanked?
+ */
+ cid_num = (char *)p->cid_num;
+ } else if (!strncasecmp(start, "sip:", 4)) {
+ cid_num = start + 4;
+ if (ast_is_shrinkable_phonenumber(cid_num))
+ ast_shrink_phone_number(cid_num);
+ start = end;
+
+ end = strchr(start, '>');
+ if (!end)
+ return 0;
+ *end = '\0';
+ } else {
+ return 0;
+ }
+
+ ast_copy_string(privacy, get_header(req, "Privacy"), sizeof(privacy));
+ if (!ast_strlen_zero(privacy) && strncmp(privacy, "id", 2)) {
+ callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+ }
+
+ /* Only return true if the supplied caller id is different */
+ if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres)
+ return 0;
+
+ ast_string_field_set(p, cid_num, cid_num);
+ ast_string_field_set(p, cid_name, cid_name);
+ p->callingpres = callingpres;
+
+ if (p->owner) {
+ ast_set_callerid(p->owner, cid_num, cid_name, NULL);
+ p->owner->cid.cid_pres = callingpres;
+ }
+
+ return 1;
+}
+
+/*! \brief Get name, number and presentation from remote party id header,
+ * returns true if a valid header was found and it was different from the
+ * current caller id.
+ */
+static int get_rpid(struct sip_pvt *p, struct sip_request *oreq)
+{
+ char tmp[256];
+ struct sip_request *req;
+ char *cid_num = "";
+ char *cid_name = "";
+ int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+ char *privacy = "";
+ char *screen = "";
+ char *start, *end;
+
+ if (!ast_test_flag(&p->flags[0], SIP_TRUSTRPID))
+ return 0;
+ req = oreq;
+ if (!req)
+ req = &p->initreq;
+ ast_copy_string(tmp, get_header(req, "Remote-Party-ID"), sizeof(tmp));
+ if (ast_strlen_zero(tmp)) {
+ return get_pai(p, req);
+ }
+
+ start = tmp;
+ if (*start == '"') {
+ *start++ = '\0';
+ end = strchr(start, '"');
+ if (!end)
+ return 0;
+ *end++ = '\0';
+ cid_name = start;
+ start = ast_skip_blanks(end);
+ }
+
+ if (*start != '<')
+ return 0;
+ *start++ = '\0';
+ end = strchr(start, '@');
+ if (!end)
+ return 0;
+ *end++ = '\0';
+ if (strncasecmp(start, "sip:", 4))
+ return 0;
+ cid_num = start + 4;
+ if (ast_is_shrinkable_phonenumber(cid_num))
+ ast_shrink_phone_number(cid_num);
+ start = end;
+
+ end = strchr(start, '>');
+ if (!end)
+ return 0;
+ *end++ = '\0';
+ if (*end) {
+ start = end;
+ if (*start != ';')
+ return 0;
+ *start++ = '\0';
+ while (!ast_strlen_zero(start)) {
+ end = strchr(start, ';');
+ if (end)
+ *end++ = '\0';
+ if (!strncasecmp(start, "privacy=", 8))
+ privacy = start + 8;
+ else if (!strncasecmp(start, "screen=", 7))
+ screen = start + 7;
+ start = end;
+ }
+
+ if (!strcasecmp(privacy, "full")) {
+ if (!strcasecmp(screen, "yes"))
+ callingpres = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
+ else if (!strcasecmp(screen, "no"))
+ callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+ } else {
+ if (!strcasecmp(screen, "yes"))
+ callingpres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
+ else if (!strcasecmp(screen, "no"))
+ callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+ }
+ }
+
+ /* Only return true if the supplied caller id is different */
+ if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres)
+ return 0;
+
+ ast_string_field_set(p, cid_num, cid_num);
+ ast_string_field_set(p, cid_name, cid_name);
+ p->callingpres = callingpres;
+
+ if (p->owner) {
+ ast_set_callerid(p->owner, cid_num, cid_name, NULL);
+ p->owner->cid.cid_pres = callingpres;
+ }
+
+ return 1;
+}
+
/*! \brief Get referring dnis */
-static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq)
+static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason)
{
- char tmp[256], *exten, *rexten, *rdomain;
- char *params, *reason = NULL;
+ char tmp[256], *exten, *rexten, *rdomain, *rname = NULL;
+ char *params, *reason_param = NULL;
struct sip_request *req;
-
+
req = oreq ? oreq : &p->initreq;
ast_copy_string(tmp, get_header(req, "Diversion"), sizeof(tmp));
if (ast_strlen_zero(tmp))
- return 0;
+ return -1;
- /*! \todo This function does not take user-parameters into consideration.
- First look for @, then start looking for ; to find uri-parameters.
- */
- params = strchr(tmp, ';');
+ if ((params = strchr(tmp, '>'))) {
+ params = strchr(params, ';');
+ }
exten = get_in_brackets(tmp);
if (!strncasecmp(exten, "sip:", 4)) {
@@ -12295,16 +12653,16 @@ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq)
while (*params == ';' || *params == ' ')
params++;
/* Check if we have a reason parameter */
- if ((reason = strcasestr(params, "reason="))) {
- reason+=7;
+ if ((reason_param = strcasestr(params, "reason="))) {
+ reason_param+=7;
/* Remove enclosing double-quotes */
- if (*reason == '"')
- ast_strip_quoted(reason, "\"", "\"");
- if (!ast_strlen_zero(reason)) {
- sip_set_redirstr(p, reason);
+ if (*reason_param == '"')
+ ast_strip_quoted(reason_param, "\"", "\"");
+ if (!ast_strlen_zero(reason_param)) {
+ sip_set_redirstr(p, reason_param);
if (p->owner) {
pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause);
- pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason);
+ pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason_param);
}
}
}
@@ -12312,13 +12670,32 @@ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq)
rdomain = exten;
rexten = strsep(&rdomain, "@"); /* trim anything after @ */
- if (p->owner)
+ if (p->owner)
pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain);
if (sip_debug_test_pvt(p))
- ast_verbose("RDNIS for this call is is %s (reason %s)\n", exten, reason ? reason : "");
+ ast_verbose("RDNIS for this call is %s (reason %s)\n", exten, reason ? reason_param : "");
+
+ /*ast_string_field_set(p, rdnis, rexten);*/
+
+ if (*tmp == '\"') {
+ char *end_quote;
+ rname = tmp + 1;
+ end_quote = strchr(rname, '\"');
+ *end_quote = '\0';
+ }
- ast_string_field_set(p, rdnis, rexten);
+ if (number) {
+ *number = ast_strdup(rexten);
+ }
+
+ if (name && rname) {
+ *name = ast_strdup(rname);
+ }
+
+ if (reason && !ast_strlen_zero(reason_param)) {
+ *reason = sip_reason_str_to_code(reason_param);
+ }
return 0;
}
@@ -12931,58 +13308,12 @@ static char *get_calleridname(const char *input, char *output, size_t outputsize
return output;
}
-/*! \brief Get caller id number from Remote-Party-ID header field
- * Returns true if number should be restricted (privacy setting found)
- * output is set to NULL if no number found
- */
-static int get_rpid_num(const char *input, char *output, int maxlen)
-{
- char *start;
- char *end;
-
- start = strchr(input, ':');
- if (!start) {
- output[0] = '\0';
- return 0;
- }
- start++;
-
- /* we found "number" */
- ast_copy_string(output, start, maxlen);
- output[maxlen-1] = '\0';
-
- end = strchr(output, '@');
- if (end)
- *end = '\0';
- else
- output[0] = '\0';
- if (strstr(input, "privacy=full") || strstr(input, "privacy=uri"))
- return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-
- return 0;
-}
-
-
-/*! \brief helper function for check_{user|peer}_ok() */
-static void replace_cid(struct sip_pvt *p, const char *rpid_num, const char *calleridname)
-{
- /* replace callerid if rpid found, and not restricted */
- if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) {
- char *tmp = ast_strdupa(rpid_num); /* XXX the copy can be done later */
- if (!ast_strlen_zero(calleridname))
- ast_string_field_set(p, cid_name, calleridname);
- if (ast_is_shrinkable_phonenumber(tmp))
- ast_shrink_phone_number(tmp);
- ast_string_field_set(p, cid_num, tmp);
- }
-}
/*! \brief Validate device authentication */
static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
struct sip_request *req, int sipmethod, struct sockaddr_in *sin,
struct sip_peer **authpeer,
- enum xmittype reliable,
- char *rpid_num, char *calleridname, char *uri2)
+ enum xmittype reliable, char *calleridname, char *uri2)
{
enum check_auth_result res;
int debug=sip_debug_test_addr(sin);
@@ -13030,7 +13361,6 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
if (p->sipoptions)
peer->sipoptions = p->sipoptions;
- replace_cid(p, rpid_num, calleridname);
do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE));
ast_string_field_set(p, peersecret, peer->secret);
@@ -13083,14 +13413,18 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
/* XXX this takes the name from the caller... can we override ? */
ast_string_field_set(p, authname, peer->username);
}
- if (!ast_strlen_zero(peer->cid_num)) {
- char *tmp = ast_strdupa(peer->cid_num);
- if (ast_is_shrinkable_phonenumber(tmp))
- ast_shrink_phone_number(tmp);
- ast_string_field_set(p, cid_num, tmp);
+ if (!get_rpid(p, req)) {
+ if (!ast_strlen_zero(peer->cid_num)) {
+ char *tmp = ast_strdupa(peer->cid_num);
+ if (ast_is_shrinkable_phonenumber(tmp))
+ ast_shrink_phone_number(tmp);
+ ast_string_field_set(p, cid_num, tmp);
+ }
+ if (!ast_strlen_zero(peer->cid_name))
+ ast_string_field_set(p, cid_name, peer->cid_name);
+ if (peer->callingpres)
+ p->callingpres = peer->callingpres;
}
- if (!ast_strlen_zero(peer->cid_name))
- ast_string_field_set(p, cid_name, peer->cid_name);
ast_string_field_set(p, fullcontact, peer->fullcontact);
if (!ast_strlen_zero(peer->context))
ast_string_field_set(p, context, peer->context);
@@ -13140,8 +13474,6 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
char *dummy; /* dummy return value for parse_uri */
char *domain; /* dummy return value for parse_uri */
char *of, *of2;
- char rpid_num[50];
- const char *rpid;
enum check_auth_result res;
char calleridname[50];
char *uri2 = ast_strdupa(uri);
@@ -13157,11 +13489,6 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
if (calleridname[0])
ast_string_field_set(p, cid_name, calleridname);
- rpid = get_header(req, "Remote-Party-ID");
- memset(rpid_num, 0, sizeof(rpid_num));
- if (!ast_strlen_zero(rpid))
- p->callingpres = get_rpid_num(rpid, rpid_num, sizeof(rpid_num));
-
of = get_in_brackets(from);
if (ast_strlen_zero(p->exten)) {
char *t = uri2;
@@ -13235,13 +13562,13 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
}
res = check_peer_ok(p, of, req, sipmethod, sin,
- authpeer, reliable, rpid_num, calleridname, uri2);
+ authpeer, reliable, calleridname, uri2);
if (res != AUTH_DONT_KNOW)
return res;
/* Finally, apply the guest policy */
if (sip_cfg.allowguest) {
- replace_cid(p, rpid_num, calleridname);
+ get_rpid(p, req);
if (!dialog_initialize_rtp(p)) {
res = AUTH_SUCCESSFUL;
} else {
@@ -16483,29 +16810,150 @@ static struct ast_custom_function sipchaninfo_function = {
.read = function_sipchaninfo_read,
};
+static int read_to_parts(struct sip_pvt *p, struct sip_request *req, char **name, char **number)
+{
+
+ char to_header[256];
+ char *to_name = NULL;
+ char *to_number = NULL;
+ char *separator;
+
+ ast_copy_string(to_header, get_header(req, "To"), sizeof(to_header));
+
+ /* Let's get that number first! */
+ to_number = get_in_brackets(to_header);
+
+ if (!strncasecmp(to_number, "sip:", 4)) {
+ to_number += 4;
+ } else if (!strncasecmp(to_number, "sips:", 5)) {
+ to_number += 5;
+ } else {
+ ast_log(LOG_WARNING, "Not a SIP URI? (%s)!\n", to_number);
+ return -1;
+ }
+
+ /* Remove the host and such since we just want the number */
+ if ((separator = strchr(to_number, '@'))) {
+ *separator = '\0';
+ }
+
+ /* We have the number. Let's get the name now. */
+
+ if (*to_header == '\"') {
+ to_name = to_header + 1;
+ if (!(separator = (char *)find_closing_quote(to_name, NULL))) {
+ ast_log(LOG_NOTICE, "No closing quote in name section of To: header (%s)\n", to_header);
+ return -1;
+ }
+ *separator = '\0';
+ }
+
+ if (number) {
+ *number = ast_strdup(to_number);
+ }
+ if (name && !ast_strlen_zero(to_name)) {
+ *name = ast_strdup(to_name);
+ }
+
+ return 0;
+}
+
+/*! \brief update redirecting information for a channel based on headers
+ *
+ */
+static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, int set_call_forward)
+{
+ char *redirecting_from_name = NULL;
+ char *redirecting_from_number = NULL;
+ char *redirecting_to_name = NULL;
+ char *redirecting_to_number = NULL;
+ int reason = AST_REDIRECTING_REASON_UNCONDITIONAL;
+ int is_response = req->method == SIP_RESPONSE;
+ int res = 0;
+
+ res = get_rdnis(p, req, &redirecting_from_name, &redirecting_from_number, &reason);
+ if (res == -1) {
+ if (is_response) {
+ read_to_parts(p, req, &redirecting_from_name, &redirecting_from_number);
+ } else {
+ return;
+ }
+ }
+
+ /* At this point, all redirecting "from" info should be filled in appropriately
+ * on to the "to" info
+ */
+
+ if (is_response) {
+ parse_moved_contact(p, req, &redirecting_to_name, &redirecting_to_number, set_call_forward);
+ } else {
+ read_to_parts(p, req, &redirecting_to_name, &redirecting_to_number);
+ }
+
+ if (!ast_strlen_zero(redirecting_from_number)) {
+ if (redirecting->from.number) {
+ ast_free(redirecting->from.number);
+ }
+ ast_debug(3, "Got redirecting from number %s\n", redirecting_from_number);
+ redirecting->from.number = redirecting_from_number;
+ }
+ if (!ast_strlen_zero(redirecting_from_name)) {
+ if (redirecting->from.name) {
+ ast_free(redirecting->from.name);
+ }
+ ast_debug(3, "Got redirecting from name %s\n", redirecting_from_name);
+ redirecting->from.name = redirecting_from_name;
+ }
+ if (!ast_strlen_zero(redirecting_to_number)) {
+ if (redirecting->to.number) {
+ ast_free(redirecting->to.number);
+ }
+ ast_debug(3, "Got redirecting to number %s\n", redirecting_to_number);
+ redirecting->to.number = redirecting_to_number;
+ }
+ if (!ast_strlen_zero(redirecting_to_name)) {
+ if (redirecting->to.name) {
+ ast_free(redirecting->to.name);
+ }
+ ast_debug(3, "Got redirecting to name %s\n", redirecting_from_number);
+ redirecting->to.name = redirecting_to_name;
+ }
+ redirecting->reason = reason;
+}
+
/*! \brief Parse 302 Moved temporalily response
\todo XXX Doesn't redirect over TLS on sips: uri's.
If we get a redirect to a SIPS: uri, this needs to be going back to the
dialplan (this is a request for a secure signalling path).
Note that transport=tls is deprecated, but we need to support it on incoming requests.
*/
-static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
+static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward)
{
- char tmp[SIPBUFSIZE];
- char *s, *e, *t, *trans;
+ char contact[SIPBUFSIZE];
+ char *contact_name = NULL;
+ char *contact_number = NULL;
+ char *separator, *trans;
char *domain;
enum sip_transport transport = SIP_TRANSPORT_UDP;
- ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp));
- if ((t = strchr(tmp, ',')))
- *t = '\0';
+ ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
+ if ((separator = strchr(contact, ',')))
+ *separator = '\0';
- s = get_in_brackets(tmp);
- if ((trans = strcasestr(s, ";transport="))) do {
+ /* ooh, a name */
+ if (*contact == '"') {
+ contact_name = contact + 1;
+ if ((separator = strchr(contact_name, '"'))) {
+ *separator++ = '\0';
+ }
+ }
+
+ contact_number = get_in_brackets(contact);
+ if ((trans = strcasestr(contact_number, ";transport="))) {
trans += 11;
- if ((e = strchr(trans, ';')))
- *e = '\0';
+ if ((separator = strchr(trans, ';')))
+ *separator = '\0';
if (!strncasecmp(trans, "tcp", 3))
transport = SIP_TRANSPORT_TCP;
@@ -16513,12 +16961,12 @@ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
transport = SIP_TRANSPORT_TLS;
else {
if (strncasecmp(trans, "udp", 3))
- ast_debug(1, "received contact with an invalid transport, '%s'\n", s);
+ ast_debug(1, "received contact with an invalid transport, '%s'\n", contact_number);
/* This will assume UDP for all unknown transports */
transport = SIP_TRANSPORT_UDP;
}
- } while(0);
- s = remove_uri_parameters(s);
+ }
+ contact_number = remove_uri_parameters(contact_number);
if (p->socket.tcptls_session) {
ao2_ref(p->socket.tcptls_session, -1);
@@ -16528,51 +16976,70 @@ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
p->socket.fd = -1;
p->socket.type = transport;
- if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
+ if (set_call_forward && ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
char *host = NULL;
- if (!strncasecmp(s, "sip:", 4))
- s += 4;
- else if (!strncasecmp(s, "sips:", 5))
- s += 5;
- e = strchr(s, '/');
- if (e)
- *e = '\0';
- if ((host = strchr(s, '@'))) {
+ if (!strncasecmp(contact_number, "sip:", 4))
+ contact_number += 4;
+ else if (!strncasecmp(contact_number, "sips:", 5))
+ contact_number += 5;
+ separator = strchr(contact_number, '/');
+ if (separator)
+ *separator = '\0';
+ if ((host = strchr(contact_number, '@'))) {
*host++ = '\0';
- ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", s, get_transport(transport), host);
+ ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", contact_number, get_transport(transport), host);
if (p->owner)
- ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", s, get_transport(transport), host);
+ ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", contact_number, get_transport(transport), host);
} else {
- ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), s);
+ ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), contact_number);
if (p->owner)
- ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s);
+ ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), contact_number);
}
} else {
- e = strchr(tmp, '@');
- if (e) {
- *e++ = '\0';
- domain = e;
+ separator = strchr(contact, '@');
+ if (separator) {
+ *separator++ = '\0';
+ domain = separator;
} else {
/* No username part */
- domain = tmp;
- }
- e = strchr(tmp, '/'); /* WHEN do we hae a forward slash in the URI? */
- if (e)
- *e = '\0';
-
- if (!strncasecmp(s, "sip:", 4))
- s += 4;
- else if (!strncasecmp(s, "sips:", 5))
- s += 5;
- e = strchr(s, ';'); /* And username ; parameters? */
- if (e)
- *e = '\0';
- ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain);
- if (p->owner) {
- pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain);
- ast_string_field_set(p->owner, call_forward, s);
+ domain = contact;
+ }
+ separator = strchr(contact, '/'); /* WHEN do we hae a forward slash in the URI? */
+ if (separator)
+ *separator = '\0';
+
+ if (!strncasecmp(contact_number, "sip:", 4))
+ contact_number += 4;
+ else if (!strncasecmp(contact_number, "sips:", 5))
+ contact_number += 5;
+ separator = strchr(contact_number, ';'); /* And username ; parameters? */
+ if (separator)
+ *separator = '\0';
+ if (set_call_forward) {
+ ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", contact_number, domain);
+ if (p->owner) {
+ pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain);
+ ast_string_field_set(p->owner, call_forward, contact_number);
+ }
}
}
+
+ /* We've gotten the number for the contact, now get the name */
+
+ if (*contact == '\"') {
+ contact_name = contact + 1;
+ if (!(separator = (char *)find_closing_quote(contact_name, NULL))) {
+ ast_log(LOG_NOTICE, "No closing quote on name in Contact header? %s\n", contact);
+ }
+ *separator = '\0';
+ }
+
+ if (name && !ast_strlen_zero(contact_name)) {
+ *name = ast_strdup(contact_name);
+ }
+ if (number) {
+ *number = ast_strdup(contact_number);
+ }
}
/*! \brief Check pending actions on SIP call */
@@ -16635,6 +17102,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
int reinvite = (p->owner && p->owner->_state == AST_STATE_UP);
char *p_hdrval;
int rtn;
+ struct ast_party_connected_line connected;
if (reinvite)
ast_debug(4, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid);
@@ -16653,7 +17121,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
/* RFC3261 says we must treat every 1xx response (but not 100)
that we don't recognize as if it was 183.
*/
- if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 182 && resp != 183)
+ if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 181 && resp != 182 && resp != 183)
resp = 183;
/* Any response between 100 and 199 is PROCEEDING */
@@ -16681,6 +17149,14 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p))
ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
if (!req->ignore && p->owner) {
+ if (get_rpid(p, req)) {
+ ast_party_connected_line_init(&connected);
+ connected.id.number = (char *) p->cid_num;
+ connected.id.name = (char *) p->cid_name;
+ connected.id.number_presentation = p->callingpres;
+ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
+ ast_channel_queue_connected_line_update(p->owner, &connected);
+ }
ast_queue_control(p->owner, AST_CONTROL_RINGING);
if (p->owner->_state != AST_STATE_UP) {
ast_setstate(p->owner, AST_STATE_RINGING);
@@ -16698,10 +17174,32 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
check_pendings(p);
break;
+ case 181: /* Call Is Being Forwarded */
+ if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p))
+ ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
+ if (!req->ignore && p->owner) {
+ struct ast_party_redirecting redirecting = {{0,},};
+ change_redirecting_information(p, req, &redirecting, FALSE);
+ ast_channel_queue_redirecting_update(p->owner, &redirecting);
+ }
+ check_pendings(p);
+ break;
+
case 183: /* Session progress */
if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p))
ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
/* Ignore 183 Session progress without SDP */
+ if (!req->ignore && p->owner) {
+ if (get_rpid(p, req)) {
+ /* Queue a connected line update */
+ ast_party_connected_line_init(&connected);
+ connected.id.number = (char *) p->cid_num;
+ connected.id.name = (char *) p->cid_name;
+ connected.id.number_presentation = p->callingpres;
+ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
+ ast_channel_queue_connected_line_update(p->owner, &connected);
+ }
+ }
if (find_sdp(req)) {
if (p->invitestate != INV_CANCELLED)
p->invitestate = INV_EARLY_MEDIA;
@@ -16723,7 +17221,17 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
if (!reinvite)
/* This 200 OK's SDP is not acceptable, so we need to ack, then hangup */
/* For re-invites, we try to recover */
- ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
+ ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
+ }
+
+ if (!req->ignore && p->owner && get_rpid(p, req)) {
+ /* Queue a connected line update */
+ ast_party_connected_line_init(&connected);
+ connected.id.number = (char *) p->cid_num;
+ connected.id.name = (char *) p->cid_name;
+ connected.id.number_presentation = p->callingpres;
+ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
+ ast_channel_queue_connected_line_update(p->owner, &connected);
}
/* Parse contact header for continued conversation */
@@ -16747,6 +17255,9 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
if (!req->ignore && p->owner) {
if (!reinvite) {
+ struct ast_party_connected_line connected;
+ ast_party_connected_line_collect_caller(&connected, &p->owner->cid);
+ ast_channel_queue_connected_line_update(p->owner, &connected);
ast_queue_control(p->owner, AST_CONTROL_ANSWER);
if (sip_cfg.callevents)
manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate",
@@ -17402,6 +17913,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
case 183: /* 183 Session Progress */
case 180: /* 180 Ringing */
case 182: /* 182 Queued */
+ case 181: /* 181 Call Is Being Forwarded */
if (sipmethod == SIP_INVITE)
handle_response_invite(p, resp, rest, req, seqno);
break;
@@ -17569,7 +18081,11 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
case 301: /* Moved permanently */
case 302: /* Moved temporarily */
case 305: /* Use Proxy */
- parse_moved_contact(p, req);
+ {
+ struct ast_party_redirecting redirecting = {{0,},};
+ change_redirecting_information(p, req, &redirecting, TRUE);
+ ast_channel_set_redirecting(p->owner, &redirecting);
+ }
/* Fall through */
case 486: /* Busy here */
case 600: /* Busy everywhere */
@@ -18265,7 +18781,7 @@ static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, in
/* We should answer something here. If we are here, the
call we are replacing exists, so an accepted
can't harm */
- transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE);
+ transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE, FALSE);
/* Do something more clever here */
ast_channel_unlock(c);
sip_pvt_unlock(p->refer->refer_call);
@@ -18299,7 +18815,7 @@ static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, in
Targetcall is not touched by the masq */
/* Answer the incoming call and set channel to UP state */
- transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE);
+ transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE, FALSE);
ast_setstate(c, AST_STATE_UP);
@@ -18699,10 +19215,11 @@ static int sip_t38_abort(const void *data)
return 0;
}
-/*! \brief Handle incoming INVITE request
-\note If the INVITE has a Replaces header, it is part of an
+/*!
+ * \brief Handle incoming INVITE request
+ * \note If the INVITE has a Replaces header, it is part of an
* attended transfer. If so, we do not go through the dial
- * plan but tries to find the active call and masquerade
+ * plan but try to find the active call and masquerade
* into it
*/
static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, char *e, int *nounlock)
@@ -18973,6 +19490,16 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
parse_ok_contact(p, req);
} else { /* Re-invite on existing call */
ast_clear_flag(&p->flags[0], SIP_OUTGOING); /* This is now an inbound dialog */
+ if (get_rpid(p, req)) {
+ struct ast_party_connected_line connected;
+
+ ast_party_connected_line_init(&connected);
+ connected.id.number = (char *) p->cid_num;
+ connected.id.name = (char *) p->cid_name;
+ connected.id.number_presentation = p->callingpres;
+ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
+ ast_channel_queue_connected_line_update(p->owner, &connected);
+ }
/* Handle SDP here if we already have an owner */
if (find_sdp(req)) {
if (process_sdp(p, req, SDP_T38_INITIATE)) {
@@ -18995,6 +19522,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
if (!p->lastinvite && !req->ignore && !p->owner) {
/* This is a new invite */
/* Handle authentication if this is our first invite */
+ struct ast_party_redirecting redirecting = {{0,},};
res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin);
if (res == AUTH_CHALLENGE_SENT) {
p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */
@@ -19052,7 +19580,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
return 0;
}
gotdest = get_destination(p, NULL); /* Get destination right away */
- get_rdnis(p, NULL); /* Get redirect information */
+ change_redirecting_information(p, req, &redirecting, FALSE); /*Will return immediately if no Diversion header is present */
extract_uri(p, req); /* Get the Contact URI */
build_contact(p); /* Build our contact header */
@@ -19096,9 +19624,11 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
if (c) {
/* Pre-lock the call */
ast_channel_lock(c);
+ ast_channel_set_redirecting(c, &redirecting);
}
}
} else {
+ struct ast_party_redirecting redirecting = {{0,},};
if (sipdebug) {
if (!req->ignore)
ast_debug(2, "Got a SIP re-invite for call %s\n", p->callid);
@@ -19108,6 +19638,10 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
if (!req->ignore)
reinvite = 1;
c = p->owner;
+ change_redirecting_information(p, req, &redirecting, FALSE); /*Will return immediately if no Diversion header is present */
+ if (c) {
+ ast_channel_set_redirecting(c, &redirecting);
+ }
}
/* Session-Timers */
@@ -19318,7 +19852,6 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
c->hangupcause = AST_CAUSE_CALL_REJECTED;
} else {
sip_pvt_unlock(p);
- ast_setstate(c, AST_STATE_DOWN);
c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
}
p->invitestate = INV_COMPLETED;
@@ -19348,7 +19881,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
} else if (p->t38.state == T38_DISABLED) {
/* If this is not a re-invite or something to ignore - it's critical */
ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
- transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE:TRUE);
+ transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE : TRUE, FALSE);
}
p->invitestate = INV_TERMINATED;
@@ -19466,6 +19999,8 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *
else
ast_clear_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER);
} else {
+ struct ast_party_connected_line connected_caller;
+
/* Transfer succeeded! */
const char *xfersound = pbx_builtin_getvar_helper(target.chan1, "ATTENDED_TRANSFER_COMPLETE_SOUND");
@@ -19480,6 +20015,45 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *
ast_debug(1, "SIP attended transfer: Unlocking channel %s\n", targetcall_pvt->owner->name);
ast_channel_unlock(targetcall_pvt->owner);
}
+
+ if (target.chan2) {
+ if (current->chan2) {
+ /* Tell each of the other channels to whom they are now connected */
+ ast_channel_lock(current->chan2);
+ ast_connected_line_copy_from_caller(&connected_caller, &current->chan2->cid);
+ ast_channel_unlock(current->chan2);
+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
+ ast_channel_update_connected_line(target.chan2, &connected_caller);
+ ast_channel_lock(target.chan2);
+ ast_connected_line_copy_from_caller(&connected_caller, &target.chan2->cid);
+ ast_channel_unlock(target.chan2);
+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
+ ast_channel_update_connected_line(current->chan2, &connected_caller);
+ ast_party_connected_line_free(&connected_caller);
+ }
+ } else {
+ /* Notify the first other party that they are connected to someone else assuming that target.chan1
+ has progressed far enough through the dialplan to have it's called party information set. */
+ if (current->chan2) {
+ ast_channel_lock(target.chan1);
+ ast_party_connected_line_copy(&connected_caller, &target.chan1->connected);
+ ast_channel_unlock(target.chan1);
+ connected_caller = target.chan1->connected;
+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
+ ast_channel_update_connected_line(current->chan2, &connected_caller);
+ ast_party_connected_line_free(&connected_caller);
+ }
+
+ /* We can't indicate to the called channel directly so we force the masquerade to complete
+ and queue and update to be read and passed-through */
+ ast_channel_lock(target.chan1);
+ ast_do_masquerade(target.chan1);
+ ast_channel_unlock(target.chan1);
+
+ ast_party_connected_line_collect_caller(&connected_caller, &target.chan1->cid);
+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
+ ast_channel_queue_connected_line_update(target.chan1, &connected_caller);
+ }
}
if (targetcall_pvt)
ao2_t_ref(targetcall_pvt, -1, "drop targetcall_pvt");
@@ -20553,10 +21127,10 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct so
*/
int ret = 0;
- if (p->ocseq < seqno && seqno != p->lastnoninvite) {
+ if (p->ocseq < seqno && p->lastinvite != seqno && p->lastnoninvite != seqno) {
ast_debug(1, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq);
ret = -1;
- } else if (p->ocseq != seqno && seqno != p->lastnoninvite) {
+ } else if (p->ocseq != seqno && p->lastinvite != seqno && p->lastnoninvite != seqno) {
/* ignore means "don't do anything with it" but still have to
* respond appropriately.
* But in this case this is a response already, so we really
@@ -22130,7 +22704,16 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
ast_set2_flag(&flags[0], ast_true(v->value), SIP_TRUSTRPID);
} else if (!strcasecmp(v->name, "sendrpid")) {
ast_set_flag(&mask[0], SIP_SENDRPID);
- ast_set2_flag(&flags[0], ast_true(v->value), SIP_SENDRPID);
+ if (!strcasecmp(v->value, "pai")) {
+ ast_set_flag(&flags[0], SIP_SENDRPID_PAI);
+ } else if (!strcasecmp(v->value, "rpid")) {
+ ast_set_flag(&flags[0], SIP_SENDRPID_RPID);
+ } else if (ast_true(v->value)) {
+ ast_set_flag(&flags[0], SIP_SENDRPID_RPID);
+ }
+ } else if (!strcasecmp(v->name, "rpid_immediate")) {
+ ast_set_flag(&mask[1], SIP_PAGE2_RPID_IMMEDIATE);
+ ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RPID_IMMEDIATE);
} else if (!strcasecmp(v->name, "g726nonstandard")) {
ast_set_flag(&mask[0], SIP_G726_NONSTANDARD);
ast_set2_flag(&flags[0], ast_true(v->value), SIP_G726_NONSTANDARD);
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index f4104a89e..588680e3c 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -2516,6 +2516,43 @@ static int skinny_extensionstate_cb(char *context, char *exten, int state, void
return 0;
}
+static void update_connectedline(struct skinny_subchannel *sub, const void *data, size_t datalen)
+{
+ struct ast_channel *c = sub->owner;
+ struct skinny_line *l = sub->parent;
+ struct skinny_device *d = l->device;
+
+ if (ast_strlen_zero(c->cid.cid_num) || ast_strlen_zero(c->connected.id.number))
+ return;
+
+ if (sub->owner->_state == AST_STATE_UP) {
+ transmit_callstate(d, l->instance, SKINNY_CONNECTED, sub->callid);
+ transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
+ if (sub->outgoing)
+ transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+ else
+ transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
+ } else {
+ if (sub->outgoing) {
+ transmit_callstate(d, l->instance, SKINNY_RINGIN, sub->callid);
+ transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
+ transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+ } else {
+ if (!sub->ringing) {
+ transmit_callstate(d, l->instance, SKINNY_RINGOUT, sub->callid);
+ transmit_displaypromptstatus(d, "Ring-Out", 0, l->instance, sub->callid);
+ sub->ringing = 1;
+ } else {
+ transmit_callstate(d, l->instance, SKINNY_PROGRESS, sub->callid);
+ transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
+ sub->progress = 1;
+ }
+
+ transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
+ }
+ }
+}
+
static void mwi_event_cb(const struct ast_event *event, void *userdata)
{
struct skinny_line *l = userdata;
@@ -3610,6 +3647,8 @@ static void *skinny_newcall(void *data)
l->hidecallerid ? "" : l->cid_num,
l->hidecallerid ? "" : l->cid_name,
c->cid.cid_ani ? NULL : l->cid_num);
+ c->connected.id.number = ast_strdup(c->exten);
+ c->connected.id.name = NULL;
ast_setstate(c, AST_STATE_RING);
if (!sub->rtp) {
start_rtp(sub);
@@ -3773,7 +3812,7 @@ static int skinny_call(struct ast_channel *ast, char *dest, int timeout)
transmit_callstateonly(d, sub, SKINNY_RINGIN);
transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+ transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
transmit_ringer_mode(d, SKINNY_RING_INSIDE);
@@ -3900,7 +3939,7 @@ static int skinny_answer(struct ast_channel *ast)
/* order matters here...
for some reason, transmit_callinfo must be before transmit_callstate,
or you won't get keypad messages in some situations. */
- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
+ transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
transmit_callstateonly(d, sub, SKINNY_CONNECTED);
transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
@@ -4095,6 +4134,10 @@ static char *control2str(int ind) {
return "Unhold";
case AST_CONTROL_SRCUPDATE:
return "Media Source Update";
+ case AST_CONTROL_CONNECTED_LINE:
+ return "Connected Line";
+ case AST_CONTROL_REDIRECTING:
+ return "Redirecting";
case -1:
return "Stop tone";
default:
@@ -4202,7 +4245,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
transmit_callstateonly(d, sub, SKINNY_RINGOUT);
transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
+ transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
sub->ringing = 1;
if (!d->earlyrtp) {
break;
@@ -4243,7 +4286,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
}
transmit_callstateonly(d, sub, SKINNY_PROGRESS);
transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
+ transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
sub->progress = 1;
if (!d->earlyrtp) {
break;
@@ -4264,6 +4307,9 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
case AST_CONTROL_SRCUPDATE:
ast_rtp_instance_new_source(sub->rtp);
break;
+ case AST_CONTROL_CONNECTED_LINE:
+ update_connectedline(sub, data, datalen);
+ break;
default:
ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
return -1; /* Tell asterisk to provide inband signalling */
diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c
index 1cd94e02f..e4588b368 100644
--- a/channels/chan_unistim.c
+++ b/channels/chan_unistim.c
@@ -3671,16 +3671,16 @@ static int unistim_call(struct ast_channel *ast, char *dest, int timeout)
Sendicon(TEXT_LINE0, FAV_ICON_NONE, session);
if (sub->owner) {
- if (sub->owner->cid.cid_num) {
- send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->cid.cid_num);
- change_callerid(session, 0, sub->owner->cid.cid_num);
+ if (sub->owner->connected.id.number) {
+ send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->connected.id.number);
+ change_callerid(session, 0, sub->owner->connected.id.number);
} else {
send_text(TEXT_LINE1, TEXT_NORMAL, session, DEFAULTCALLERID);
change_callerid(session, 0, DEFAULTCALLERID);
}
- if (sub->owner->cid.cid_name) {
- send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->cid.cid_name);
- change_callerid(session, 1, sub->owner->cid.cid_name);
+ if (sub->owner->connected.id.name) {
+ send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.name);
+ change_callerid(session, 1, sub->owner->connected.id.name);
} else {
send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERNAME);
change_callerid(session, 1, DEFAULTCALLERNAME);
diff --git a/channels/misdn/chan_misdn_config.h b/channels/misdn/chan_misdn_config.h
index c00db864b..d64b8c860 100644
--- a/channels/misdn/chan_misdn_config.h
+++ b/channels/misdn/chan_misdn_config.h
@@ -46,10 +46,16 @@ enum misdn_cfg_elements {
MISDN_CFG_DIALPLAN, /* int */
MISDN_CFG_LOCALDIALPLAN, /* int */
MISDN_CFG_CPNDIALPLAN, /* int */
- MISDN_CFG_NATPREFIX, /* char[] */
- MISDN_CFG_INTERNATPREFIX, /* char[] */
+ MISDN_CFG_TON_PREFIX_UNKNOWN, /* char[] */
+ MISDN_CFG_TON_PREFIX_INTERNATIONAL, /* char[] */
+ MISDN_CFG_TON_PREFIX_NATIONAL, /* char[] */
+ MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC,/* char[] */
+ MISDN_CFG_TON_PREFIX_SUBSCRIBER, /* char[] */
+ MISDN_CFG_TON_PREFIX_ABBREVIATED, /* char[] */
MISDN_CFG_PRES, /* int */
MISDN_CFG_SCREEN, /* int */
+ MISDN_CFG_DISPLAY_CONNECTED, /* int */
+ MISDN_CFG_DISPLAY_SETUP, /* int */
MISDN_CFG_ALWAYS_IMMEDIATE, /* int (bool) */
MISDN_CFG_NODIALTONE, /* int (bool) */
MISDN_CFG_IMMEDIATE, /* int (bool) */
diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c
index 071f756eb..d8cf6171a 100644
--- a/channels/misdn/isdn_lib.c
+++ b/channels/misdn/isdn_lib.c
@@ -171,19 +171,24 @@ struct misdn_stack *get_stack_by_bc(struct misdn_bchannel *bc)
void get_show_stack_details(int port, char *buf)
{
- struct misdn_stack *stack=get_misdn_stack();
+ struct misdn_stack *stack = get_misdn_stack();
- for ( ; stack; stack=stack->next) {
- if (stack->port == port) break;
+ for (; stack; stack = stack->next) {
+ if (stack->port == port) {
+ break;
+ }
}
if (stack) {
- sprintf(buf, "* Port %d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d",
- stack->port, stack->nt ? "NT" : "TE", stack->ptp ? "PTP" : "PMP",
- stack->l2link ? "UP" : "DOWN", stack->l1link ? "UP" : "DOWN",
+ sprintf(buf, "* Port %2d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d",
+ stack->port,
+ stack->nt ? "NT" : "TE",
+ stack->ptp ? "PTP" : "PMP",
+ stack->l2link ? "UP " : "DOWN",
+ stack->l1link ? "UP " : "DOWN",
stack->blocked);
} else {
- buf[0]=0;
+ buf[0] = 0;
}
}
@@ -644,6 +649,29 @@ static void bc_next_state_change(struct misdn_bchannel *bc, enum bchannel_state
static void empty_bc(struct misdn_bchannel *bc)
{
+ bc->caller.presentation = 0; /* allowed */
+ bc->caller.number_plan = NUMPLAN_ISDN;
+ bc->caller.number_type = NUMTYPE_UNKNOWN;
+ bc->caller.name[0] = 0;
+ bc->caller.number[0] = 0;
+ bc->caller.subaddress[0] = 0;
+
+ bc->connected.presentation = 0; /* allowed */
+ bc->connected.number_plan = NUMPLAN_ISDN;
+ bc->connected.number_type = NUMTYPE_UNKNOWN;
+ bc->connected.name[0] = 0;
+ bc->connected.number[0] = 0;
+ bc->connected.subaddress[0] = 0;
+
+ bc->redirecting.from.presentation = 0; /* allowed */
+ bc->redirecting.from.number_plan = NUMPLAN_ISDN;
+ bc->redirecting.from.number_type = NUMTYPE_UNKNOWN;
+ bc->redirecting.from.name[0] = 0;
+ bc->redirecting.from.number[0] = 0;
+ bc->redirecting.from.subaddress[0] = 0;
+
+ bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
+
bc->dummy=0;
bc->bframe_len=0;
@@ -678,12 +706,6 @@ static void empty_bc(struct misdn_bchannel *bc)
bc->generate_tone=0;
bc->tone_cnt=0;
- bc->dnumplan=NUMPLAN_UNKNOWN;
- bc->onumplan=NUMPLAN_UNKNOWN;
- bc->rnumplan=NUMPLAN_UNKNOWN;
- bc->cpnnumplan=NUMPLAN_UNKNOWN;
-
-
bc->active = 0;
bc->early_bconnect = 1;
@@ -701,7 +723,12 @@ static void empty_bc(struct misdn_bchannel *bc)
bc->cause = AST_CAUSE_NORMAL_CLEARING;
bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
- bc->pres = 0; /* allowed */
+
+ bc->display_connected = 0; /* none */
+ bc->display_setup = 0; /* none */
+
+ bc->presentation = 0; /* allowed */
+ bc->set_presentation = 0;
bc->evq=EVENT_NOTHING;
@@ -719,15 +746,14 @@ static void empty_bc(struct misdn_bchannel *bc)
bc->hdlc=0;
+ bc->dialed.number_plan = NUMPLAN_ISDN;
+ bc->dialed.number_type = NUMTYPE_UNKNOWN;
+ bc->dialed.number[0] = 0;
+ bc->dialed.subaddress[0] = 0;
bc->info_dad[0] = 0;
bc->display[0] = 0;
bc->infos_pending[0] = 0;
- bc->cad[0] = 0;
- bc->oad[0] = 0;
- bc->dad[0] = 0;
- bc->rad[0] = 0;
- bc->orig_dad[0] = 0;
bc->uu[0]=0;
bc->uulen=0;
@@ -929,7 +955,7 @@ static int create_process(int midev, struct misdn_bchannel *bc)
if (stack->procids[proc_id] == 0) {
break;
}
- } /* end for */
+ }
if (proc_id == MAXPROCS) {
cb_log(0, stack->port, "Couldn't Create New ProcId.\n");
return -1;
@@ -1560,7 +1586,14 @@ static int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_
setup_bc(bc);
if ( *bc->crypt_key ) {
- cb_log(4, stack->port, "ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s\n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
+ cb_log(4, stack->port,
+ "ENABLING BLOWFISH channel:%d caller%d:\"%s\" <%s> dialed%d:%s\n",
+ bc->channel,
+ bc->caller.number_type,
+ bc->caller.name,
+ bc->caller.number,
+ bc->dialed.number_type,
+ bc->dialed.number);
manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
}
@@ -1582,7 +1615,14 @@ static int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_
case EVENT_CONNECT:
if ( *bc->crypt_key ) {
- cb_log(4, stack->port, "ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s\n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
+ cb_log(4, stack->port,
+ "ENABLING BLOWFISH channel:%d caller%d:\"%s\" <%s> dialed%d:%s\n",
+ bc->channel,
+ bc->caller.number_type,
+ bc->caller.name,
+ bc->caller.number,
+ bc->dialed.number_type,
+ bc->dialed.number);
manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
}
case EVENT_ALERTING:
@@ -2454,7 +2494,14 @@ static int handle_bchan(msg_t *msg)
{
unsigned int *cont = (unsigned int *) &frm->data.p;
- cb_log(4, stack->port, "PH_CONTROL: channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
+ cb_log(4, stack->port,
+ "PH_CONTROL: channel:%d caller%d:\"%s\" <%s> dialed%d:%s \n",
+ bc->channel,
+ bc->caller.number_type,
+ bc->caller.name,
+ bc->caller.number,
+ bc->dialed.number_type,
+ bc->dialed.number);
if ((*cont & ~DTMF_TONE_MASK) == DTMF_TONE_VAL) {
int dtmf = *cont & DTMF_TONE_MASK;
@@ -3268,10 +3315,6 @@ struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel, int inout, i
return NULL;
}
-
-
-
-/* ******************************************************************* */
/*!
* \internal
* \brief Convert the facility function enum value into a string.
@@ -3286,14 +3329,8 @@ static const char *fac2str(enum FacFunction facility)
} arr[] = {
/* *INDENT-OFF* */
{ Fac_None, "Fac_None" },
- { Fac_GetSupportedServices, "Fac_GetSupportedServices" },
- { Fac_Listen, "Fac_Listen" },
- { Fac_Suspend, "Fac_Suspend" },
- { Fac_Resume, "Fac_Resume" },
{ Fac_CFActivate, "Fac_CFActivate" },
{ Fac_CFDeactivate, "Fac_CFDeactivate" },
- { Fac_CFInterrogateParameters, "Fac_CFInterrogateParameters" },
- { Fac_CFInterrogateNumbers, "Fac_CFInterrogateNumbers" },
{ Fac_CD, "Fac_CD" },
{ Fac_AOCDCurrency, "Fac_AOCDCurrency" },
{ Fac_AOCDChargingUnit, "Fac_AOCDChargingUnit" },
@@ -3306,10 +3343,10 @@ static const char *fac2str(enum FacFunction facility)
if (arr[index].facility == facility) {
return arr[index].name;
}
- } /* end for */
+ }
return "unknown";
-} /* end fac2str() */
+}
void misdn_lib_log_ies(struct misdn_bchannel *bc)
{
@@ -3321,20 +3358,50 @@ void misdn_lib_log_ies(struct misdn_bchannel *bc)
if (!stack) return;
- cb_log(2, stack->port, " --> channel:%d mode:%s cause:%d ocause:%d rad:%s cad:%s\n", bc->channel, stack->nt?"NT":"TE", bc->cause, bc->out_cause, bc->rad, bc->cad);
+ cb_log(2, stack->port,
+ " --> channel:%d mode:%s cause:%d ocause:%d\n",
+ bc->channel,
+ stack->nt ? "NT" : "TE",
+ bc->cause,
+ bc->out_cause);
+
+ cb_log(2, stack->port,
+ " --> info_dad:%s dialed numtype:%d plan:%d\n",
+ bc->info_dad,
+ bc->dialed.number_type,
+ bc->dialed.number_plan);
+
+ cb_log(2, stack->port,
+ " --> caller:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
+ bc->caller.name,
+ bc->caller.number,
+ bc->caller.number_type,
+ bc->caller.number_plan,
+ bc->caller.presentation,
+ bc->caller.screening);
+
+ cb_log(2, stack->port,
+ " --> redirecting:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d reason:%d\n",
+ bc->redirecting.from.name,
+ bc->redirecting.from.number,
+ bc->redirecting.from.number_type,
+ bc->redirecting.from.number_plan,
+ bc->redirecting.from.presentation,
+ bc->redirecting.from.screening,
+ bc->redirecting.reason);
cb_log(2, stack->port,
- " --> info_dad:%s onumplan:%c dnumplan:%c rnumplan:%c cpnnumplan:%c\n",
- bc->info_dad,
- bc->onumplan>=0?'0'+bc->onumplan:' ',
- bc->dnumplan>=0?'0'+bc->dnumplan:' ',
- bc->rnumplan>=0?'0'+bc->rnumplan:' ',
- bc->cpnnumplan>=0?'0'+bc->cpnnumplan:' '
- );
+ " --> connected:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
+ bc->connected.name,
+ bc->connected.number,
+ bc->connected.number_type,
+ bc->connected.number_plan,
+ bc->connected.presentation,
+ bc->connected.screening);
cb_log(3, stack->port, " --> caps:%s pi:%x keypad:%s sending_complete:%d\n", bearer2str(bc->capability),bc->progress_indicator, bc->keypad, bc->sending_complete);
- cb_log(4, stack->port, " --> screen:%d --> pres:%d\n",
- bc->screen, bc->pres);
+
+ cb_log(4, stack->port, " --> set_pres:%d pres:%d\n", bc->set_presentation, bc->presentation);
cb_log(4, stack->port, " --> addr:%x l3id:%x b_stid:%x layer_id:%x\n", bc->addr, bc->l3_id, bc->b_stid, bc->layer_id);
@@ -3373,7 +3440,12 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
stack = get_stack_by_bc(bc);
if (!stack) {
- cb_log(0,bc->port,"SENDEVENT: no Stack for event:%s oad:%s dad:%s \n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad);
+ cb_log(0,bc->port,
+ "SENDEVENT: no Stack for event:%s caller:\"%s\" <%s> dialed:%s \n",
+ isdn_get_info(msgs_g, event, 0),
+ bc->caller.name,
+ bc->caller.number,
+ bc->dialed.number);
RETURN(-1,OUT);
}
@@ -3390,7 +3462,13 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
RETURN(0,OUT);
}
- cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s pid:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, bc->pid);
+ cb_log(1, stack->port,
+ "I SEND:%s caller:\"%s\" <%s> dialed:%s pid:%d\n",
+ isdn_get_info(msgs_g, event, 0),
+ bc->caller.name,
+ bc->caller.number,
+ bc->dialed.number,
+ bc->pid);
cb_log(4, stack->port, " --> bc_state:%s\n",bc_state2str(bc->bc_state));
misdn_lib_log_ies(bc);
@@ -3431,7 +3509,14 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
if (misdn_cap_is_speech(bc->capability)) {
if ((event==EVENT_CONNECT)||(event==EVENT_RETRIEVE_ACKNOWLEDGE)) {
if ( *bc->crypt_key ) {
- cb_log(4, stack->port, " --> ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
+ cb_log(4, stack->port,
+ " --> ENABLING BLOWFISH channel:%d caller%d:\"%s\" <%s> dialed%d:%s\n",
+ bc->channel,
+ bc->caller.number_type,
+ bc->caller.name,
+ bc->caller.number,
+ bc->dialed.number_type,
+ bc->dialed.number);
manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
}
@@ -3571,8 +3656,19 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
/* Later we should think about sending bchannel data directly to misdn. */
msg = isdn_msg_build_event(msgs_g, bc, event, stack->nt);
- msg_queue_tail(&stack->downqueue, msg);
- sem_post(&glob_mgr->new_msg);
+ if (!msg) {
+ /*
+ * The message was not built.
+ *
+ * NOTE: The only time that the message will fail to build
+ * is because the requested FACILITY message is not supported.
+ * A failed malloc() results in exit() being called.
+ */
+ RETURN(-1, OUT);
+ } else {
+ msg_queue_tail(&stack->downqueue, msg);
+ sem_post(&glob_mgr->new_msg);
+ }
OUT:
misdn_send_unlock(bc);
diff --git a/channels/misdn/isdn_lib.h b/channels/misdn/isdn_lib.h
index 638df8a74..ff098c18b 100644
--- a/channels/misdn/isdn_lib.h
+++ b/channels/misdn/isdn_lib.h
@@ -96,15 +96,23 @@ enum misdn_err_e {
ENOCHAN=1
};
-
enum mISDN_NUMBER_PLAN {
- NUMPLAN_UNINITIALIZED=-1,
- NUMPLAN_INTERNATIONAL=0x1,
- NUMPLAN_NATIONAL=0x2,
- NUMPLAN_SUBSCRIBER=0x4,
- NUMPLAN_UNKNOWN=0x0
+ NUMPLAN_UNKNOWN = 0x0,
+ NUMPLAN_ISDN = 0x1, /* ISDN/Telephony numbering plan E.164 */
+ NUMPLAN_DATA = 0x3, /* Data numbering plan X.121 */
+ NUMPLAN_TELEX = 0x4, /* Telex numbering plan F.69 */
+ NUMPLAN_NATIONAL = 0x8,
+ NUMPLAN_PRIVATE = 0x9
};
+enum mISDN_NUMBER_TYPE {
+ NUMTYPE_UNKNOWN = 0x0,
+ NUMTYPE_INTERNATIONAL = 0x1,
+ NUMTYPE_NATIONAL = 0x2,
+ NUMTYPE_NETWORK_SPECIFIC = 0x3,
+ NUMTYPE_SUBSCRIBER = 0x4,
+ NUMTYPE_ABBREVIATED = 0x5
+};
enum event_response_e {
RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE,
@@ -189,6 +197,19 @@ enum { /* progress indicators */
INFO_PI_INTERWORKING_NO_RELEASE_POST_ANSWER =0x13
};
+/*!
+ * \brief Q.931 encoded redirecting reason
+ */
+enum mISDN_REDIRECTING_REASON {
+ mISDN_REDIRECTING_REASON_UNKNOWN = 0x0,
+ mISDN_REDIRECTING_REASON_CALL_FWD_BUSY = 0x1, /* Call forwarding busy or called DTE busy */
+ mISDN_REDIRECTING_REASON_NO_REPLY = 0x2, /* Call forwarding no reply */
+ mISDN_REDIRECTING_REASON_DEFLECTION = 0x4, /* Call deflection */
+ mISDN_REDIRECTING_REASON_OUT_OF_ORDER = 0x9, /* Called DTE out of order */
+ mISDN_REDIRECTING_REASON_CALL_FWD_DTE = 0xA, /* Call forwarding by the called DTE */
+ mISDN_REDIRECTING_REASON_CALL_FWD = 0xF /* Call forwarding unconditional or systematic call redirection */
+};
+
enum { /*CODECS*/
INFO_CODEC_ULAW=2,
INFO_CODEC_ALAW=3
@@ -202,12 +223,81 @@ enum layer_e {
UNKNOWN
};
+/* Maximum phone number (address) length plus null terminator */
+#define MISDN_MAX_NUMBER_LEN (31 + 1)
+
+/* Maximum name length plus null terminator (From ECMA-164) */
+#define MISDN_MAX_NAME_LEN (50 + 1)
+
+/* Maximum subaddress length plus null terminator */
+#define MISDN_MAX_SUBADDRESS_LEN (23 + 1)
+
+/* Maximum keypad facility content length plus null terminator */
+#define MISDN_MAX_KEYPAD_LEN (31 + 1)
+
+/*! \brief Connected-Line/Calling/Redirecting ID info struct */
+struct misdn_party_id {
+ /*! \brief Number presentation restriction code
+ * 0=Allowed, 1=Restricted, 2=Unavailable
+ */
+ int presentation;
+
+ /*! \brief Number screening code
+ * 0=Unscreened, 1=Passed Screen, 2=Failed Screen, 3=Network Number
+ */
+ int screening;
+
+ /*! \brief Type-of-number in ISDN terms for the number */
+ enum mISDN_NUMBER_TYPE number_type;
+
+ /*! \brief Type-of-number numbering plan. */
+ enum mISDN_NUMBER_PLAN number_plan;
+
+ /*! \brief Subscriber Name
+ * \note The name is currently obtained from Asterisk for
+ * potential use in display ie's since basic ISDN does
+ * not support names directly.
+ */
+ char name[MISDN_MAX_NAME_LEN];
+
+ /*! \brief Phone number (Address) */
+ char number[MISDN_MAX_NUMBER_LEN];
+
+ /*! \brief Subaddress number */
+ char subaddress[MISDN_MAX_SUBADDRESS_LEN];
+};
+
+/*! \brief Redirecting information struct */
+struct misdn_party_redirecting {
+ /*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) */
+ struct misdn_party_id from;
+
+ /*! \brief Reason a call is being redirected (Q.931 field value) */
+ enum mISDN_REDIRECTING_REASON reason;
+};
+/*! \brief B channel control structure */
struct misdn_bchannel {
/*! \brief B channel send locking structure */
struct send_lock *send_lock;
+ /*! \brief Originating/Caller ID information struct
+ * \note The number_type element is set to "localdialplan" in /etc/asterisk/misdn.conf for outgoing calls
+ * \note The number element can be set to "callerid" in /etc/asterisk/misdn.conf for outgoing calls
+ */
+ struct misdn_party_id caller;
+
+ /*! \brief Connected-Party/Connected-Line ID information struct
+ * \note The number_type element is set to "cpndialplan" in /etc/asterisk/misdn.conf for outgoing calls
+ */
+ struct misdn_party_id connected;
+
+ /*! \brief Redirecting information struct (Where a call diversion or transfer was invoked)
+ * \note The redirecting subaddress is not defined in Q.931 so it is not used.
+ */
+ struct misdn_party_redirecting redirecting;
+
/*! \brief TRUE if this is a dummy BC record */
int dummy;
@@ -326,26 +416,6 @@ struct misdn_bchannel {
/*! \brief TRUE if we will not use the jitter buffer system */
int nojitter;
- /*! \brief Type-of-number in ISDN terms for the dialed/called number
- * \note This value is set to "dialplan" in /etc/asterisk/misdn.conf for outgoing calls
- */
- enum mISDN_NUMBER_PLAN dnumplan;
-
- /*! \brief Type-of-number in ISDN terms for the redirecting number which a call diversion or transfer was invoked.
- * \note Collected from the incoming SETUP message but not used.
- */
- enum mISDN_NUMBER_PLAN rnumplan;
-
- /*! \brief Type-of-number in ISDN terms for the originating/calling number (Caller-ID)
- * \note This value is set to "localdialplan" in /etc/asterisk/misdn.conf for outgoing calls
- */
- enum mISDN_NUMBER_PLAN onumplan;
-
- /*! \brief Type-of-number in ISDN terms for the connected party number
- * \note This value is set to "cpndialplan" in /etc/asterisk/misdn.conf for outgoing calls
- */
- enum mISDN_NUMBER_PLAN cpnnumplan;
-
/*! \brief Progress Indicator IE coding standard field.
* \note Collected from the incoming messages but not used.
*/
@@ -421,16 +491,38 @@ struct misdn_bchannel {
*/
int stack_holder;
- /*! \brief Caller ID presentation restriction code
+ /*!
+ * \brief Put a display ie in the CONNECT message
+ * \details
+ * Put a display ie in the CONNECT message containing the following
+ * information if it is available (nt port only):
+ * 0 - Do not put the connected line information in the display ie.
+ * 1 - Put the available connected line name in the display ie.
+ * 2 - Put the available connected line number in the display ie.
+ * 3 - Put the available connected line name and number in the display ie.
+ */
+ int display_connected;
+
+ /*!
+ * \brief Put a display ie in the SETUP message
+ * \details
+ * Put a display ie in the SETUP message containing the following
+ * information if it is available (nt port only):
+ * 0 - Do not put the caller information in the display ie.
+ * 1 - Put the available caller name in the display ie.
+ * 2 - Put the available caller number in the display ie.
+ * 3 - Put the available caller name and number in the display ie.
+ */
+ int display_setup;
+
+ /*! \brief User set presentation restriction code
* 0=Allowed, 1=Restricted, 2=Unavailable
* \note It is settable by the misdn_set_opt() application.
*/
- int pres;
+ int presentation;
- /*! \brief Caller ID screening code
- * 0=Unscreened, 1=Passed Screen, 2=Failed Screen, 3=Network Number
- */
- int screen;
+ /*! \brief TRUE if the user set the presentation restriction code */
+ int set_presentation;
/*! \brief SETUP message bearer capability field code value */
int capability;
@@ -462,6 +554,23 @@ struct misdn_bchannel {
int hdlc;
/* V110 */
+ /*! \brief Dialed/Called information struct */
+ struct {
+ /*! \brief Type-of-number in ISDN terms for the dialed/called number
+ * \note This value is set to "dialplan" in /etc/asterisk/misdn.conf for outgoing calls
+ */
+ enum mISDN_NUMBER_TYPE number_type;
+
+ /*! \brief Type-of-number numbering plan. */
+ enum mISDN_NUMBER_PLAN number_plan;
+
+ /*! \brief Dialed/Called Phone Number (Address) */
+ char number[MISDN_MAX_NUMBER_LEN];
+
+ /*! \brief Dialed/Called Subaddress number */
+ char subaddress[MISDN_MAX_SUBADDRESS_LEN];
+ } dialed;
+
/*! \brief Display message that can be displayed by the user phone.
* \note Maximum displayable length is 34 or 82 octets.
* It is also settable by the misdn_set_opt() application.
@@ -469,39 +578,20 @@ struct misdn_bchannel {
char display[84];
/*! \brief Not used. Contents are setup but not used. */
- char msn[32];
-
- /*! \brief Originating/Calling Phone Number (Address)
- * \note This value can be set to "callerid" in /etc/asterisk/misdn.conf for outgoing calls
- */
- char oad[32];
-
- /*! \brief Redirecting Phone Number (Address) where a call diversion or transfer was invoked */
- char rad[32];
-
- /*! \brief Dialed/Called Phone Number (Address) */
- char dad[32];
-
- /*! \brief Connected Party/Line Phone Number (Address) */
- char cad[32];
-
- /*! \brief Original Dialed/Called Phone Number (Address) before national/international dialing prefix added.
- * \note Not used. Contents are setup but not used.
- */
- char orig_dad[32];
+ char msn[MISDN_MAX_NUMBER_LEN];
/*! \brief Q.931 Keypad Facility IE contents
* \note Contents exported and imported to Asterisk variable MISDN_KEYPAD
*/
- char keypad[32];
+ char keypad[MISDN_MAX_KEYPAD_LEN];
/*! \brief Current overlap dialing digits to/from INFORMATION messages */
- char info_dad[64];
+ char info_dad[MISDN_MAX_NUMBER_LEN];
/*! \brief Collected digits to go into info_dad[] while waiting for a SETUP_ACKNOWLEDGE to come in. */
- char infos_pending[64];
+ char infos_pending[MISDN_MAX_NUMBER_LEN];
-/* unsigned char info_keypad[32]; */
+/* unsigned char info_keypad[MISDN_MAX_KEYPAD_LEN]; */
/* unsigned char clisub[24]; */
/* unsigned char cldsub[24]; */
diff --git a/channels/misdn/isdn_lib_intern.h b/channels/misdn/isdn_lib_intern.h
index a4ddc7a49..3347fe335 100644
--- a/channels/misdn/isdn_lib_intern.h
+++ b/channels/misdn/isdn_lib_intern.h
@@ -41,7 +41,6 @@ struct send_lock {
struct isdn_msg {
unsigned long misdn_msg;
- enum layer_e layer;
enum event_e event;
void (*msg_parser)(struct isdn_msg *msgs, msg_t *msg, struct misdn_bchannel *bc, int nt);
diff --git a/channels/misdn/isdn_msg_parser.c b/channels/misdn/isdn_msg_parser.c
index 6c4272ea0..01c084ff7 100644
--- a/channels/misdn/isdn_msg_parser.c
+++ b/channels/misdn/isdn_msg_parser.c
@@ -25,6 +25,42 @@
#include "ie.c"
+/*!
+ * \internal
+ * \brief Build the name, number, name/number display message string
+ *
+ * \param display Display buffer to fill in
+ * \param display_length Length of the display buffer to fill in
+ * \param display_format Display format enumeration
+ * \param name Name string to use
+ * \param number Number string to use
+ *
+ * \return Nothing
+ */
+static void build_display_str(char *display, size_t display_length, int display_format, const char *name, const char *number)
+{
+ display[0] = 0;
+ switch (display_format) {
+ default:
+ case 0: /* none */
+ break;
+
+ case 1: /* name */
+ snprintf(display, display_length, "%s", name);
+ break;
+
+ case 2: /* number */
+ snprintf(display, display_length, "%s", number);
+ break;
+
+ case 3: /* both */
+ if (name[0] || number[0]) {
+ snprintf(display, display_length, "\"%s\" <%s>", name, number);
+ }
+ break;
+ }
+}
+
static void set_channel(struct misdn_bchannel *bc, int channel)
{
@@ -161,62 +197,74 @@ static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchann
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
SETUP_t *setup= (SETUP_t*)((unsigned long)msg->data+HEADER_LEN);
Q931_info_t *qi=(Q931_info_t*)((unsigned long)msg->data+HEADER_LEN);
+ int type;
+ int plan;
+ int present;
+ int screen;
+ int reason;
#ifdef DEBUG
printf("Parsing SETUP Msg\n");
#endif
- {
- int type,plan,present, screen;
- char id[32];
- dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, id, sizeof(id)-1, nt,bc);
-
- bc->onumplan=type;
- strcpy(bc->oad, id);
- switch (present) {
- case 0:
- bc->pres=0; /* screened */
- break;
- case 1:
- bc->pres=1; /* not screened */
- break;
- default:
- bc->pres=0;
- }
- switch (screen) {
- case 0:
- break;
- default:
- ;
- }
- }
- {
- int type, plan;
- char number[32];
- dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)setup, &type, &plan, number, sizeof(number)-1, nt,bc);
- strcpy(bc->dad, number);
- bc->dnumplan=type;
+
+ dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, bc->caller.number, sizeof(bc->caller.number) - 1, nt, bc);
+ bc->caller.number_type = type;
+ bc->caller.number_plan = plan;
+ switch (present) {
+ default:
+ case 0:
+ bc->caller.presentation = 0; /* presentation allowed */
+ break;
+ case 1:
+ bc->caller.presentation = 1; /* presentation restricted */
+ break;
+ case 2:
+ bc->caller.presentation = 2; /* Number not available */
+ break;
}
- {
- char keypad[32];
- dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)setup, keypad, sizeof(keypad)-1, nt,bc);
- strcpy(bc->keypad, keypad);
+ if (0 <= screen) {
+ bc->caller.screening = screen;
+ } else {
+ bc->caller.screening = 0; /* Unscreened */
}
- {
- dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &bc->sending_complete, nt,bc);
-
+ dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *) setup, &type, &plan, bc->dialed.number, sizeof(bc->dialed.number) - 1, nt, bc);
+ bc->dialed.number_type = type;
+ bc->dialed.number_plan = plan;
+
+ dec_ie_keypad(setup->KEYPAD, (Q931_info_t *) setup, bc->keypad, sizeof(bc->keypad) - 1, nt, bc);
+
+ dec_ie_complete(setup->COMPLETE, (Q931_info_t *) setup, &bc->sending_complete, nt, bc);
+
+ dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *) setup, &type, &plan, &present, &screen, &reason, bc->redirecting.from.number, sizeof(bc->redirecting.from.number) - 1, nt, bc);
+ bc->redirecting.from.number_type = type;
+ bc->redirecting.from.number_plan = plan;
+ switch (present) {
+ default:
+ case 0:
+ bc->redirecting.from.presentation = 0; /* presentation allowed */
+ break;
+ case 1:
+ bc->redirecting.from.presentation = 1; /* presentation restricted */
+ break;
+ case 2:
+ bc->redirecting.from.presentation = 2; /* Number not available */
+ break;
}
-
- {
- int type, plan, present, screen, reason;
- char id[32];
- dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *)setup, &type, &plan, &present, &screen, &reason, id, sizeof(id)-1, nt,bc);
-
- strcpy(bc->rad, id);
- bc->rnumplan=type;
+ if (0 <= screen) {
+ bc->redirecting.from.screening = screen;
+ } else {
+ bc->redirecting.from.screening = 0; /* Unscreened */
+ }
+ if (0 <= reason) {
+ bc->redirecting.reason = reason;
+ } else {
+ bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
}
+
{
int coding, capability, mode, rate, multi, user, async, urate, stopbits, dbits, parity;
+
dec_ie_bearer(setup->BEARER, (Q931_info_t *)setup, &coding, &capability, &mode, &rate, &multi, &user, &async, &urate, &stopbits, &dbits, &parity, nt,bc);
switch (capability) {
case -1: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
@@ -271,7 +319,7 @@ static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchann
}
-#define ANY_CHANNEL 0xff /* IE attribut for 'any channel' */
+#define ANY_CHANNEL 0xff /* IE attribute for 'any channel' */
static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -286,35 +334,43 @@ static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, in
enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
- {
- int type=bc->onumplan,plan=1,present=bc->pres,screen=bc->screen;
- enc_ie_calling_pn(&setup->CALLING_PN, msg, type, plan, present,
- screen, bc->oad, nt, bc);
- }
+ enc_ie_calling_pn(&setup->CALLING_PN, msg, bc->caller.number_type, bc->caller.number_plan,
+ bc->caller.presentation, bc->caller.screening, bc->caller.number, nt, bc);
- {
- if (bc->dad[0])
- enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dnumplan, 1, bc->dad, nt,bc);
+ if (bc->dialed.number[0]) {
+ enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dialed.number_type, bc->dialed.number_plan, bc->dialed.number, nt, bc);
}
- {
- if (bc->rad[0])
- enc_ie_redir_nr(&setup->REDIR_NR, msg, 1, 1, bc->pres, bc->screen, 0, bc->rad, nt,bc);
+ if (bc->redirecting.from.number[0]) {
+ enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type, bc->redirecting.from.number_plan,
+ bc->redirecting.from.presentation, bc->redirecting.from.screening, bc->redirecting.reason,
+ bc->redirecting.from.number, nt, bc);
}
- {
- if (bc->keypad[0])
- enc_ie_keypad(&setup->KEYPAD, msg, bc->keypad, nt,bc);
+ if (bc->keypad[0]) {
+ enc_ie_keypad(&setup->KEYPAD, msg, bc->keypad, nt,bc);
}
+
if (*bc->display) {
- enc_ie_display(&setup->DISPLAY, msg, bc->display, nt,bc);
+ enc_ie_display(&setup->DISPLAY, msg, bc->display, nt, bc);
+ } else if (nt && bc->caller.presentation == 0) {
+ char display[sizeof(bc->display)];
+
+ /* Presentation is allowed */
+ build_display_str(display, sizeof(display), bc->display_setup, bc->caller.name, bc->caller.number);
+ if (display[0]) {
+ enc_ie_display(&setup->DISPLAY, msg, display, nt, bc);
+ }
}
{
- int coding=0, capability, mode=0 /* 2 for packet ! */
- ,user, rate=0x10;
+ int coding = 0;
+ int capability;
+ int mode = 0; /* 2 for packet! */
+ int user;
+ int rate = 0x10;
switch (bc->law) {
case INFO_CODEC_ULAW: user=2;
@@ -340,8 +396,6 @@ static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, in
capability=bc->capability;
}
-
-
enc_ie_bearer(&setup->BEARER, msg, coding, capability, mode, rate, -1, user, nt,bc);
}
@@ -365,15 +419,36 @@ static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bcha
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
CONNECT_t *connect=(CONNECT_t*)((unsigned long)(msg->data+HEADER_LEN));
+ int type;
+ int plan;
+ int pres;
+ int screen;
- int plan,pres,screen;
-
- bc->ces = connect->ces;
bc->ces = connect->ces;
dec_ie_progress(connect->PROGRESS, (Q931_info_t *)connect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
- dec_ie_connected_pn(connect->CONNECT_PN,(Q931_info_t *)connect, &bc->cpnnumplan, &plan, &pres, &screen, bc->cad, 31, nt, bc);
+ dec_ie_connected_pn(connect->CONNECT_PN, (Q931_info_t *) connect, &type, &plan,
+ &pres, &screen, bc->connected.number, sizeof(bc->connected.number) - 1, nt, bc);
+ bc->connected.number_type = type;
+ bc->connected.number_plan = plan;
+ switch (pres) {
+ default:
+ case 0:
+ bc->connected.presentation = 0; /* presentation allowed */
+ break;
+ case 1:
+ bc->connected.presentation = 1; /* presentation restricted */
+ break;
+ case 2:
+ bc->connected.presentation = 2; /* Number not available */
+ break;
+ }
+ if (0 <= screen) {
+ bc->connected.screening = screen;
+ } else {
+ bc->connected.screening = 0; /* Unscreened */
+ }
/*
cb_log(1,bc->port,"CONNETED PN: %s cpn_dialplan:%d\n", connected_pn, type);
@@ -400,9 +475,17 @@ static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc,
enc_ie_date(&connect->DATE, msg, now, nt,bc);
}
- {
- int type=bc->cpnnumplan, plan=1, present=2, screen=0;
- enc_ie_connected_pn(&connect->CONNECT_PN, msg, type,plan, present, screen, bc->cad, nt , bc);
+ enc_ie_connected_pn(&connect->CONNECT_PN, msg, bc->connected.number_type, bc->connected.number_plan,
+ bc->connected.presentation, bc->connected.screening, bc->connected.number, nt, bc);
+
+ if (nt && bc->connected.presentation == 0) {
+ char display[sizeof(bc->display)];
+
+ /* Presentation is allowed */
+ build_display_str(display, sizeof(display), bc->display_connected, bc->connected.name, bc->connected.number);
+ if (display[0]) {
+ enc_ie_display(&connect->DISPLAY, msg, display, nt, bc);
+ }
}
#ifdef DEBUG
@@ -982,12 +1065,12 @@ static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bch
static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
{
- int len,
- HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
- unsigned char *ie_fac,
- fac_tmp[256];
- msg_t *msg =(msg_t*)create_l3msg(CC_FACILITY | REQUEST, MT_FACILITY, bc?bc->l3_id:-1, sizeof(FACILITY_t) ,nt);
- FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
+ int len;
+ int HEADER_LEN;
+ unsigned char *ie_fac;
+ unsigned char fac_tmp[256];
+ msg_t *msg;
+ FACILITY_t *facility;
Q931_info_t *qi;
#ifdef DEBUG
@@ -995,8 +1078,14 @@ static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc,
#endif
len = encodeFac(fac_tmp, &(bc->fac_out));
- if (len <= 0)
+ if (len <= 0) {
+ /* mISDN does not know how to build the requested facility structure */
return NULL;
+ }
+
+ msg = (msg_t *) create_l3msg(CC_FACILITY | REQUEST, MT_FACILITY, bc ? bc->l3_id : -1, sizeof(FACILITY_t), nt);
+ HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
+ facility = (FACILITY_t *) (msg->data + HEADER_LEN);
ie_fac = msg_put(msg, len);
if (bc->nt) {
@@ -1009,7 +1098,9 @@ static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc,
memcpy(ie_fac, fac_tmp, len);
if (*bc->display) {
+#ifdef DEBUG
printf("Sending %s as Display\n", bc->display);
+#endif
enc_ie_display(&facility->DISPLAY, msg, bc->display, nt,bc);
}
@@ -1062,15 +1153,11 @@ static void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
INFORMATION_t *information=(INFORMATION_t*)((unsigned long)(msg->data+HEADER_LEN));
- {
- int type, plan;
- char number[32];
- char keypad[32];
- dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *)information, &type, &plan, number, sizeof(number)-1, nt, bc);
- dec_ie_keypad(information->KEYPAD, (Q931_info_t *)information, keypad, sizeof(keypad)-1, nt, bc);
- strcpy(bc->info_dad, number);
- strcpy(bc->keypad,keypad);
- }
+ int type, plan;
+
+ dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *) information, &type, &plan, bc->info_dad, sizeof(bc->info_dad) - 1, nt, bc);
+ dec_ie_keypad(information->KEYPAD, (Q931_info_t *) information, bc->keypad, sizeof(bc->keypad) - 1, nt, bc);
+
#ifdef DEBUG
printf("Parsing INFORMATION Msg\n");
#endif
@@ -1084,13 +1171,13 @@ static msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *
information=(INFORMATION_t*)((msg->data+HEADER_LEN));
- {
- enc_ie_called_pn(&information->CALLED_PN, msg, 0, 1, bc->info_dad, nt,bc);
- }
+ enc_ie_called_pn(&information->CALLED_PN, msg, 0, 1, bc->info_dad, nt,bc);
{
if (*bc->display) {
+#ifdef DEBUG
printf("Sending %s as Display\n", bc->display);
+#endif
enc_ie_display(&information->DISPLAY, msg, bc->display, nt,bc);
}
}
@@ -1110,7 +1197,6 @@ static void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchan
dec_ie_cause(status->CAUSE, (Q931_info_t *)(status), &location, &cause, nt,bc);
if (cause>0) bc->cause=cause;
- ;
#ifdef DEBUG
printf("Parsing STATUS Msg\n");
@@ -1161,97 +1247,40 @@ static msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc,
/** Msg Array **/
struct isdn_msg msgs_g[] = {
- {CC_PROCEEDING,L3,EVENT_PROCEEDING,
- parse_proceeding,build_proceeding,
- "PROCEEDING"},
- {CC_ALERTING,L3,EVENT_ALERTING,
- parse_alerting,build_alerting,
- "ALERTING"},
- {CC_PROGRESS,L3,EVENT_PROGRESS,
- parse_progress,build_progress,
- "PROGRESS"},
- {CC_SETUP,L3,EVENT_SETUP,
- parse_setup,build_setup,
- "SETUP"},
- {CC_CONNECT,L3,EVENT_CONNECT,
- parse_connect,build_connect,
- "CONNECT"},
- {CC_SETUP_ACKNOWLEDGE,L3,EVENT_SETUP_ACKNOWLEDGE,
- parse_setup_acknowledge,build_setup_acknowledge,
- "SETUP_ACKNOWLEDGE"},
- {CC_CONNECT_ACKNOWLEDGE ,L3,EVENT_CONNECT_ACKNOWLEDGE ,
- parse_connect_acknowledge ,build_connect_acknowledge,
- "CONNECT_ACKNOWLEDGE "},
- {CC_USER_INFORMATION,L3,EVENT_USER_INFORMATION,
- parse_user_information,build_user_information,
- "USER_INFORMATION"},
- {CC_SUSPEND_REJECT,L3,EVENT_SUSPEND_REJECT,
- parse_suspend_reject,build_suspend_reject,
- "SUSPEND_REJECT"},
- {CC_RESUME_REJECT,L3,EVENT_RESUME_REJECT,
- parse_resume_reject,build_resume_reject,
- "RESUME_REJECT"},
- {CC_HOLD,L3,EVENT_HOLD,
- parse_hold,build_hold,
- "HOLD"},
- {CC_SUSPEND,L3,EVENT_SUSPEND,
- parse_suspend,build_suspend,
- "SUSPEND"},
- {CC_RESUME,L3,EVENT_RESUME,
- parse_resume,build_resume,
- "RESUME"},
- {CC_HOLD_ACKNOWLEDGE,L3,EVENT_HOLD_ACKNOWLEDGE,
- parse_hold_acknowledge,build_hold_acknowledge,
- "HOLD_ACKNOWLEDGE"},
- {CC_SUSPEND_ACKNOWLEDGE,L3,EVENT_SUSPEND_ACKNOWLEDGE,
- parse_suspend_acknowledge,build_suspend_acknowledge,
- "SUSPEND_ACKNOWLEDGE"},
- {CC_RESUME_ACKNOWLEDGE,L3,EVENT_RESUME_ACKNOWLEDGE,
- parse_resume_acknowledge,build_resume_acknowledge,
- "RESUME_ACKNOWLEDGE"},
- {CC_HOLD_REJECT,L3,EVENT_HOLD_REJECT,
- parse_hold_reject,build_hold_reject,
- "HOLD_REJECT"},
- {CC_RETRIEVE,L3,EVENT_RETRIEVE,
- parse_retrieve,build_retrieve,
- "RETRIEVE"},
- {CC_RETRIEVE_ACKNOWLEDGE,L3,EVENT_RETRIEVE_ACKNOWLEDGE,
- parse_retrieve_acknowledge,build_retrieve_acknowledge,
- "RETRIEVE_ACKNOWLEDGE"},
- {CC_RETRIEVE_REJECT,L3,EVENT_RETRIEVE_REJECT,
- parse_retrieve_reject,build_retrieve_reject,
- "RETRIEVE_REJECT"},
- {CC_DISCONNECT,L3,EVENT_DISCONNECT,
- parse_disconnect,build_disconnect,
- "DISCONNECT"},
- {CC_RESTART,L3,EVENT_RESTART,
- parse_restart,build_restart,
- "RESTART"},
- {CC_RELEASE,L3,EVENT_RELEASE,
- parse_release,build_release,
- "RELEASE"},
- {CC_RELEASE_COMPLETE,L3,EVENT_RELEASE_COMPLETE,
- parse_release_complete,build_release_complete,
- "RELEASE_COMPLETE"},
- {CC_FACILITY,L3,EVENT_FACILITY,
- parse_facility,build_facility,
- "FACILITY"},
- {CC_NOTIFY,L3,EVENT_NOTIFY,
- parse_notify,build_notify,
- "NOTIFY"},
- {CC_STATUS_ENQUIRY,L3,EVENT_STATUS_ENQUIRY,
- parse_status_enquiry,build_status_enquiry,
- "STATUS_ENQUIRY"},
- {CC_INFORMATION,L3,EVENT_INFORMATION,
- parse_information,build_information,
- "INFORMATION"},
- {CC_STATUS,L3,EVENT_STATUS,
- parse_status,build_status,
- "STATUS"},
- {CC_TIMEOUT,L3,EVENT_TIMEOUT,
- parse_timeout,build_timeout,
- "TIMEOUT"},
- {0,0,0,NULL,NULL,NULL}
+/* *INDENT-OFF* */
+ /* misdn_msg, event, msg_parser, msg_builder, info */
+ { CC_PROCEEDING, EVENT_PROCEEDING, parse_proceeding, build_proceeding, "PROCEEDING" },
+ { CC_ALERTING, EVENT_ALERTING, parse_alerting, build_alerting, "ALERTING" },
+ { CC_PROGRESS, EVENT_PROGRESS, parse_progress, build_progress, "PROGRESS" },
+ { CC_SETUP, EVENT_SETUP, parse_setup, build_setup, "SETUP" },
+ { CC_CONNECT, EVENT_CONNECT, parse_connect, build_connect, "CONNECT" },
+ { CC_SETUP_ACKNOWLEDGE, EVENT_SETUP_ACKNOWLEDGE, parse_setup_acknowledge, build_setup_acknowledge, "SETUP_ACKNOWLEDGE" },
+ { CC_CONNECT_ACKNOWLEDGE, EVENT_CONNECT_ACKNOWLEDGE, parse_connect_acknowledge, build_connect_acknowledge, "CONNECT_ACKNOWLEDGE " },
+ { CC_USER_INFORMATION, EVENT_USER_INFORMATION, parse_user_information, build_user_information, "USER_INFORMATION" },
+ { CC_SUSPEND_REJECT, EVENT_SUSPEND_REJECT, parse_suspend_reject, build_suspend_reject, "SUSPEND_REJECT" },
+ { CC_RESUME_REJECT, EVENT_RESUME_REJECT, parse_resume_reject, build_resume_reject, "RESUME_REJECT" },
+ { CC_HOLD, EVENT_HOLD, parse_hold, build_hold, "HOLD" },
+ { CC_SUSPEND, EVENT_SUSPEND, parse_suspend, build_suspend, "SUSPEND" },
+ { CC_RESUME, EVENT_RESUME, parse_resume, build_resume, "RESUME" },
+ { CC_HOLD_ACKNOWLEDGE, EVENT_HOLD_ACKNOWLEDGE, parse_hold_acknowledge, build_hold_acknowledge, "HOLD_ACKNOWLEDGE" },
+ { CC_SUSPEND_ACKNOWLEDGE, EVENT_SUSPEND_ACKNOWLEDGE, parse_suspend_acknowledge, build_suspend_acknowledge, "SUSPEND_ACKNOWLEDGE" },
+ { CC_RESUME_ACKNOWLEDGE, EVENT_RESUME_ACKNOWLEDGE, parse_resume_acknowledge, build_resume_acknowledge, "RESUME_ACKNOWLEDGE" },
+ { CC_HOLD_REJECT, EVENT_HOLD_REJECT, parse_hold_reject, build_hold_reject, "HOLD_REJECT" },
+ { CC_RETRIEVE, EVENT_RETRIEVE, parse_retrieve, build_retrieve, "RETRIEVE" },
+ { CC_RETRIEVE_ACKNOWLEDGE, EVENT_RETRIEVE_ACKNOWLEDGE, parse_retrieve_acknowledge, build_retrieve_acknowledge, "RETRIEVE_ACKNOWLEDGE" },
+ { CC_RETRIEVE_REJECT, EVENT_RETRIEVE_REJECT, parse_retrieve_reject, build_retrieve_reject, "RETRIEVE_REJECT" },
+ { CC_DISCONNECT, EVENT_DISCONNECT, parse_disconnect, build_disconnect, "DISCONNECT" },
+ { CC_RESTART, EVENT_RESTART, parse_restart, build_restart, "RESTART" },
+ { CC_RELEASE, EVENT_RELEASE, parse_release, build_release, "RELEASE" },
+ { CC_RELEASE_COMPLETE, EVENT_RELEASE_COMPLETE, parse_release_complete, build_release_complete, "RELEASE_COMPLETE" },
+ { CC_FACILITY, EVENT_FACILITY, parse_facility, build_facility, "FACILITY" },
+ { CC_NOTIFY, EVENT_NOTIFY, parse_notify, build_notify, "NOTIFY" },
+ { CC_STATUS_ENQUIRY, EVENT_STATUS_ENQUIRY, parse_status_enquiry, build_status_enquiry, "STATUS_ENQUIRY" },
+ { CC_INFORMATION, EVENT_INFORMATION, parse_information, build_information, "INFORMATION" },
+ { CC_STATUS, EVENT_STATUS, parse_status, build_status, "STATUS" },
+ { CC_TIMEOUT, EVENT_TIMEOUT, parse_timeout, build_timeout, "TIMEOUT" },
+ { 0, 0, NULL, NULL, NULL }
+/* *INDENT-ON* */
};
#define msgs_max (sizeof(msgs_g)/sizeof(struct isdn_msg))
diff --git a/channels/misdn_config.c b/channels/misdn_config.c
index f447c5c21..444b939f2 100644
--- a/channels/misdn_config.c
+++ b/channels/misdn_config.c
@@ -132,7 +132,7 @@ static const struct misdn_cfg_spec port_spec[] = {
{ "musicclass", MISDN_CFG_MUSICCLASS, MISDN_CTYPE_STR, "default", NONE,
"Sets the musiconhold class." },
{ "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE,
- "Sets the caller ID." },
+ "Set the outgoing caller id to the value." },
{ "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE,
"Set the method to use for channel selection:\n"
"\t standard - Use the first free channel starting from the lowest number.\n"
@@ -140,62 +140,71 @@ static const struct misdn_cfg_spec port_spec[] = {
"\t round_robin - Use the round robin algorithm to select a channel. Use this\n"
"\t if you want to balance your load." },
{ "dialplan", MISDN_CFG_DIALPLAN, MISDN_CTYPE_INT, "0", NONE,
- "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
- "\n"
+ "Dialplan means Type Of Number in ISDN Terms\n"
"\tThere are different types of the dialplan:\n"
"\n"
- "\tdialplan -> outgoing Number\n"
- "\tlocaldialplan -> callerid\n"
- "\tcpndialplan -> connected party number\n"
+ "\tdialplan -> for outgoing call's dialed number\n"
+ "\tlocaldialplan -> for outgoing call's callerid\n"
+ "\t (if -1 is set use the value from the asterisk channel)\n"
+ "\tcpndialplan -> for incoming call's connected party number sent to caller\n"
+ "\t (if -1 is set use the value from the asterisk channel)\n"
"\n"
"\tdialplan options:\n"
"\n"
"\t0 - unknown\n"
"\t1 - International\n"
"\t2 - National\n"
- "\t4 - Subscriber\n"
- "\n"
- "\tThis setting is used for outgoing calls." },
+ "\t4 - Subscriber" },
{ "localdialplan", MISDN_CFG_LOCALDIALPLAN, MISDN_CTYPE_INT, "0", NONE,
- "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
- "\n"
+ "Dialplan means Type Of Number in ISDN Terms\n"
"\tThere are different types of the dialplan:\n"
"\n"
- "\tdialplan -> outgoing Number\n"
- "\tlocaldialplan -> callerid\n"
- "\tcpndialplan -> connected party number\n"
+ "\tdialplan -> for outgoing call's dialed number\n"
+ "\tlocaldialplan -> for outgoing call's callerid\n"
+ "\t (if -1 is set use the value from the asterisk channel)\n"
+ "\tcpndialplan -> for incoming call's connected party number sent to caller\n"
+ "\t (if -1 is set use the value from the asterisk channel)\n"
"\n"
"\tdialplan options:\n"
"\n"
"\t0 - unknown\n"
"\t1 - International\n"
"\t2 - National\n"
- "\t4 - Subscriber\n"
- "\n"
- "\tThis setting is used for outgoing calls." },
+ "\t4 - Subscriber" },
{ "cpndialplan", MISDN_CFG_CPNDIALPLAN, MISDN_CTYPE_INT, "0", NONE,
- "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
- "\n"
+ "Dialplan means Type Of Number in ISDN Terms\n"
"\tThere are different types of the dialplan:\n"
"\n"
- "\tdialplan -> outgoing Number\n"
- "\tlocaldialplan -> callerid\n"
- "\tcpndialplan -> connected party number\n"
+ "\tdialplan -> for outgoing call's dialed number\n"
+ "\tlocaldialplan -> for outgoing call's callerid\n"
+ "\t (if -1 is set use the value from the asterisk channel)\n"
+ "\tcpndialplan -> for incoming call's connected party number sent to caller\n"
+ "\t (if -1 is set use the value from the asterisk channel)\n"
"\n"
"\tdialplan options:\n"
"\n"
"\t0 - unknown\n"
"\t1 - International\n"
"\t2 - National\n"
- "\t4 - Subscriber\n"
- "\n"
- "\tThis setting is used for outgoing calls." },
- { "nationalprefix", MISDN_CFG_NATPREFIX, MISDN_CTYPE_STR, "0", NONE,
- "Prefix for national, this is put before the\n"
- "\toad if an according dialplan is set by the other end." },
- { "internationalprefix", MISDN_CFG_INTERNATPREFIX, MISDN_CTYPE_STR, "00", NONE,
- "Prefix for international, this is put before the\n"
- "\toad if an according dialplan is set by the other end." },
+ "\t4 - Subscriber" },
+ { "unknownprefix", MISDN_CFG_TON_PREFIX_UNKNOWN, MISDN_CTYPE_STR, "", NONE,
+ "Prefix for unknown numbers, this is put before an incoming number\n"
+ "\tif its type-of-number is unknown." },
+ { "internationalprefix", MISDN_CFG_TON_PREFIX_INTERNATIONAL, MISDN_CTYPE_STR, "00", NONE,
+ "Prefix for international numbers, this is put before an incoming number\n"
+ "\tif its type-of-number is international." },
+ { "nationalprefix", MISDN_CFG_TON_PREFIX_NATIONAL, MISDN_CTYPE_STR, "0", NONE,
+ "Prefix for national numbers, this is put before an incoming number\n"
+ "\tif its type-of-number is national." },
+ { "netspecificprefix", MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC, MISDN_CTYPE_STR, "", NONE,
+ "Prefix for network-specific numbers, this is put before an incoming number\n"
+ "\tif its type-of-number is network-specific." },
+ { "subscriberprefix", MISDN_CFG_TON_PREFIX_SUBSCRIBER, MISDN_CTYPE_STR, "", NONE,
+ "Prefix for subscriber numbers, this is put before an incoming number\n"
+ "\tif its type-of-number is subscriber." },
+ { "abbreviatedprefix", MISDN_CFG_TON_PREFIX_ABBREVIATED, MISDN_CTYPE_STR, "", NONE,
+ "Prefix for abbreviated numbers, this is put before an incoming number\n"
+ "\tif its type-of-number is abbreviated." },
{ "presentation", MISDN_CFG_PRES, MISDN_CTYPE_INT, "-1", NONE,
"These (presentation and screen) are the exact isdn screening and presentation\n"
"\tindicators.\n"
@@ -212,6 +221,22 @@ static const struct misdn_cfg_spec port_spec[] = {
"\n"
"\tscreen=0, presentation=0 -> callerid presented\n"
"\tscreen=1, presentation=1 -> callerid restricted (the remote end doesn't see it!)" },
+ { "display_connected", MISDN_CFG_DISPLAY_CONNECTED, MISDN_CTYPE_INT, "0", NONE,
+ "Put a display ie in the CONNECT message containing the following\n"
+ "\tinformation if it is available (nt port only):\n"
+ "\n"
+ "\t0 - Do not put the connected line information in the display ie.\n"
+ "\t1 - Put the available connected line name in the display ie.\n"
+ "\t2 - Put the available connected line number in the display ie.\n"
+ "\t3 - Put the available connected line name and number in the display ie." },
+ { "display_setup", MISDN_CFG_DISPLAY_SETUP, MISDN_CTYPE_INT, "0", NONE,
+ "Put a display ie in the SETUP message containing the following\n"
+ "\tinformation if it is available (nt port only):\n"
+ "\n"
+ "\t0 - Do not put the caller information in the display ie.\n"
+ "\t1 - Put the available caller name in the display ie.\n"
+ "\t2 - Put the available caller number in the display ie.\n"
+ "\t3 - Put the available caller name and number in the display ie." },
{ "always_immediate", MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE,
"Enable this to get into the s dialplan-extension.\n"
"\tThere you can use DigitTimeout if you can't or don't want to use\n"
@@ -220,7 +245,7 @@ static const struct misdn_cfg_spec port_spec[] = {
{ "nodialtone", MISDN_CFG_NODIALTONE, MISDN_CTYPE_BOOL, "no", NONE,
"Enable this to prevent chan_misdn to generate the dialtone\n"
"\tThis makes only sense together with the always_immediate=yes option\n"
- "\tto generate your own dialtone with Playtones or so."},
+ "\tto generate your own dialtone with Playtones or so." },
{ "immediate", MISDN_CFG_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE,
"Enable this if you want callers which called exactly the base\n"
"\tnumber (so no extension is set) to jump into the s extension.\n"
@@ -257,17 +282,17 @@ static const struct misdn_cfg_spec port_spec[] = {
#endif
#ifdef WITH_BEROEC
{ "bnechocancel", MISDN_CFG_BNECHOCANCEL, MISDN_CTYPE_BOOLINT, "yes", 64,
- "echotail in ms (1-200)\n"},
+ "echotail in ms (1-200)" },
{ "bnec_antihowl", MISDN_CFG_BNEC_ANTIHOWL, MISDN_CTYPE_INT, "0", NONE,
- "Use antihowl\n"},
+ "Use antihowl" },
{ "bnec_nlp", MISDN_CFG_BNEC_NLP, MISDN_CTYPE_BOOL, "yes", NONE,
- "Nonlinear Processing (much faster adaption)"},
+ "Nonlinear Processing (much faster adaption)" },
{ "bnec_zerocoeff", MISDN_CFG_BNEC_ZEROCOEFF, MISDN_CTYPE_BOOL, "no", NONE,
- "ZeroCoeffeciens\n"},
+ "ZeroCoeffeciens" },
{ "bnec_tonedisabler", MISDN_CFG_BNEC_TD, MISDN_CTYPE_BOOL, "no", NONE,
- "Disable Tone\n"},
+ "Disable Tone" },
{ "bnec_adaption", MISDN_CFG_BNEC_ADAPT, MISDN_CTYPE_INT, "1", NONE,
- "Adaption mode (0=no,1=full,2=fast)\n"},
+ "Adaption mode (0=no,1=full,2=fast)" },
#endif
{ "need_more_infos", MISDN_CFG_NEED_MORE_INFOS, MISDN_CTYPE_BOOL, "0", NONE,
"Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),\n"
@@ -311,13 +336,13 @@ static const struct misdn_cfg_spec port_spec[] = {
{ "faxdetect_context", MISDN_CFG_FAXDETECT_CONTEXT, MISDN_CTYPE_STR, NO_DEFAULT, NONE,
"Context to jump into if we detect a fax. Don't set this if you want to stay in the current context." },
{ "l1watcher_timeout", MISDN_CFG_L1_TIMEOUT, MISDN_CTYPE_BOOLINT, "0", 4,
- "Watches the layer 1. If the layer 1 is down, it tries to\n"
- "\tget it up. The timeout is given in seconds. with 0 as value it\n"
- "\tdoes not watch the l1 at all\n"
+ "Monitors L1 of the port. If L1 is down it tries\n"
+ "\tto bring it up. The polling timeout is given in seconds.\n"
+ "\tSetting the value to 0 disables monitoring L1 of the port.\n"
"\n"
- "\tThis option is only read at loading time of chan_misdn, which\n"
- "\tmeans you need to unload and load chan_misdn to change the value,\n"
- "\tan Asterisk restart should do the trick." },
+ "\tThis option is only read at chan_misdn loading time.\n"
+ "\tYou need to unload and load chan_misdn to change the\n"
+ "\tvalue. An asterisk restart will also do the trick." },
{ "overlapdial", MISDN_CFG_OVERLAP_DIAL, MISDN_CTYPE_BOOLINT, "0", 4,
"Enables overlap dial for the given amount of seconds.\n"
"\tPossible values are positive integers or:\n"