aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
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"