46 #include "asterisk/stasis_channels.h"
49 #if !defined(LIBSS7_ABI_COMPATIBILITY)
50 #error "Upgrade your libss7"
51 #elif LIBSS7_ABI_COMPATIBILITY != 2
52 #error "Your installed libss7 is not compatible"
78 static void sig_ss7_unlock_private(
struct sig_ss7_chan *p)
92 static void sig_ss7_deadlock_avoidance_private(
struct sig_ss7_chan *p)
98 sig_ss7_unlock_private(p);
100 sig_ss7_lock_private(p);
104 void sig_ss7_set_alarm(
struct sig_ss7_chan *p,
int in_alarm)
112 static void sig_ss7_set_dialing(
struct sig_ss7_chan *p,
int is_dialing)
119 static void sig_ss7_set_digital(
struct sig_ss7_chan *p,
int is_digital)
126 static void sig_ss7_set_outgoing(
struct sig_ss7_chan *p,
int is_outgoing)
134 static void sig_ss7_set_inservice(
struct sig_ss7_chan *p,
int is_inservice)
142 static void sig_ss7_set_locallyblocked(
struct sig_ss7_chan *p,
int is_blocked,
int type)
155 static void sig_ss7_set_remotelyblocked(
struct sig_ss7_chan *p,
int is_blocked,
int type)
189 static void sig_ss7_set_caller_id(
struct sig_ss7_chan *p)
196 caller.id.name.str = p->cid_name;
198 caller.id.name.valid = 1;
200 caller.id.number.str = p->cid_num;
201 caller.id.number.plan = p->
cid_ton;
203 caller.id.number.valid = 1;
206 caller.id.subaddress.valid = 1;
212 caller.ani.number.str = p->cid_ani;
215 caller.ani.number.valid = 1;
230 static void sig_ss7_set_dnid(
struct sig_ss7_chan *p,
const char *dnid)
237 static int sig_ss7_play_tone(
struct sig_ss7_chan *p,
enum sig_ss7_tone tone)
249 static int sig_ss7_set_echocanceller(
struct sig_ss7_chan *p,
int enable)
257 static void sig_ss7_loopback(
struct sig_ss7_chan *p,
int enable)
275 assignedids, requestor);
288 p->do_hangup = SS7_HANGUP_FREE_CALL;
290 p->do_hangup = SS7_HANGUP_SEND_REL;
293 ast_channel_transfercapability_set(ast, transfercapability);
296 if (transfercapability & AST_TRANS_CAP_DIGITAL) {
297 sig_ss7_set_digital(p, 1);
303 static void sig_ss7_handle_link_exception(
struct sig_ss7_linkset *linkset,
int which)
326 static int sig_ss7_is_chan_available(
struct sig_ss7_chan *pvt)
347 static void sig_ss7_lock_owner(
struct sig_ss7_linkset *ss7,
int chanpos)
350 if (!ss7->
pvts[chanpos]->owner) {
354 if (!ast_channel_trylock(ss7->
pvts[chanpos]->owner)) {
360 sig_ss7_unlock_private(ss7->
pvts[chanpos]);
361 DEADLOCK_AVOIDANCE(&ss7->
lock);
362 sig_ss7_lock_private(ss7->
pvts[chanpos]);
380 sig_ss7_lock_owner(ss7, chanpos);
381 if (ss7->
pvts[chanpos]->owner) {
383 ast_channel_unlock(ss7->
pvts[chanpos]->owner);
399 static void sig_ss7_queue_control(
struct sig_ss7_linkset *ss7,
int chanpos,
int subclass)
409 sig_ss7_queue_frame(ss7, chanpos, &f);
425 static void ss7_queue_pvt_cause_data(
struct ast_channel *owner,
const char *cause,
int ast_cause)
428 int datalen =
sizeof(*cause_code) + strlen(cause);
431 memset(cause_code, 0, datalen);
450 int sig_ss7_find_cic(
struct sig_ss7_linkset *linkset,
int cic,
unsigned int dpc)
454 for (i = 0; i < linkset->numchans; i++) {
455 if (linkset->
pvts[i] && (linkset->
pvts[i]->
dpc == dpc && linkset->
pvts[i]->
cic == cic)) {
475 static int ss7_find_cic_gripe(
struct sig_ss7_linkset *linkset,
int cic,
unsigned int dpc,
const char *msg_name)
479 chanpos = sig_ss7_find_cic(linkset, cic, dpc);
481 ast_log(LOG_WARNING,
"Linkset %d: SS7 %s requested on unconfigured CIC/DPC %d/%d.\n",
482 linkset->
span, msg_name, cic, dpc);
488 static struct sig_ss7_chan *ss7_find_pvt(
struct ss7 *ss7,
int cic,
unsigned int dpc)
493 winner = sig_ss7_find_linkset(ss7);
494 if (winner && (chanpos = sig_ss7_find_cic(winner, cic, dpc)) > -1) {
495 return winner->
pvts[chanpos];
500 int sig_ss7_cb_hangup(
struct ss7 *ss7,
int cic,
unsigned int dpc,
int cause,
int do_hangup)
505 if (!(p = ss7_find_pvt(ss7, cic, dpc))) {
506 return SS7_CIC_NOT_EXISTS;
509 sig_ss7_lock_private(p);
511 ast_channel_hangupcause_set(p->owner, cause);
513 p->do_hangup = do_hangup;
518 sig_ss7_unlock_private(p);
523 void sig_ss7_cb_call_null(
struct ss7 *ss7,
struct isup_call *call,
int lock)
528 winner = sig_ss7_find_linkset(ss7);
532 for (i = 0; i < winner->numchans; i++) {
535 sig_ss7_lock_private(winner->
pvts[i]);
538 if (winner->
pvts[i]->owner) {
539 ast_channel_hangupcause_set(winner->
pvts[i]->owner, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
543 sig_ss7_unlock_private(winner->
pvts[i]);
545 ast_log(LOG_WARNING,
"libss7 asked set ss7 call to NULL on CIC %d DPC %d\n", winner->
pvts[i]->
cic, winner->
pvts[i]->
dpc);
550 void sig_ss7_cb_notinservice(
struct ss7 *ss7,
int cic,
unsigned int dpc)
554 if (!(p = ss7_find_pvt(ss7, cic, dpc))) {
558 sig_ss7_lock_private(p);
559 sig_ss7_set_inservice(p, 0);
560 sig_ss7_unlock_private(p);
574 static void ss7_check_range(
struct sig_ss7_linkset *linkset,
int startcic,
int endcic,
unsigned int dpc,
unsigned char *state)
578 for (cic = startcic; cic <= endcic; cic++) {
579 if (state[cic - startcic] && sig_ss7_find_cic(linkset, cic, dpc) == -1) {
580 state[cic - startcic] = 0;
585 static int ss7_match_range(
struct sig_ss7_chan *pvt,
int startcic,
int endcic,
unsigned int dpc)
587 if (pvt && pvt->
dpc == dpc && pvt->
cic >= startcic && pvt->
cic <= endcic) {
608 int sig_ss7_find_cic_range(
struct sig_ss7_linkset *linkset,
int startcic,
int endcic,
unsigned int dpc)
612 for (i = 0; i < linkset->numchans; i++) {
613 if (ss7_match_range(linkset->
pvts[i], startcic, endcic, dpc)) {
618 if (found == endcic - startcic + 1) {
625 static void ss7_handle_cqm(
struct sig_ss7_linkset *linkset, ss7_event *e)
627 unsigned char status[32];
633 memset(status, 0,
sizeof(status));
634 for (i = 0; i < linkset->numchans; i++) {
635 if (ss7_match_range(linkset->
pvts[i], e->cqm.startcic, e->cqm.endcic, e->cqm.opc)) {
636 p = linkset->
pvts[i];
637 sig_ss7_lock_private(p);
638 offset = p->
cic - e->cqm.startcic;
641 status[offset] |= (1 << 0) | (1 << 4);
644 status[offset] |= (1 << 1) | (1 << 5);
648 status[offset] |= (1 << 3);
650 status[offset] |= (1 << 2);
653 status[offset] |= 0x3 << 2;
655 sig_ss7_unlock_private(p);
660 isup_cqr(linkset->ss7, e->cqm.startcic, e->cqm.endcic, e->cqm.opc, status);
662 ast_log(LOG_WARNING,
"Could not find any equipped circuits within CQM CICs\n");
665 chanpos = sig_ss7_find_cic(linkset, e->cqm.startcic, e->cqm.opc);
667 isup_free_call(linkset->ss7, e->cqm.call);
670 p = linkset->
pvts[chanpos];
671 sig_ss7_lock_private(p);
674 p->
ss7call = isup_free_call_if_clear(linkset->ss7, e->cqm.call);
676 sig_ss7_unlock_private(p);
679 static inline void ss7_hangup_cics(
struct sig_ss7_linkset *linkset,
int startcic,
int endcic,
unsigned int dpc)
683 for (i = 0; i < linkset->numchans; i++) {
684 if (ss7_match_range(linkset->
pvts[i], startcic, endcic, dpc)) {
685 sig_ss7_lock_private(linkset->
pvts[i]);
686 sig_ss7_lock_owner(linkset, i);
687 if (linkset->
pvts[i]->owner) {
689 ast_channel_unlock(linkset->
pvts[i]->owner);
691 sig_ss7_unlock_private(linkset->
pvts[i]);
709 static inline void ss7_block_cics(
struct sig_ss7_linkset *linkset,
int startcic,
int endcic,
unsigned int dpc,
unsigned char state[],
int block,
int remotely,
int type)
713 for (i = 0; i < linkset->numchans; i++) {
714 if (ss7_match_range(linkset->
pvts[i], startcic, endcic, dpc)) {
715 sig_ss7_lock_private(linkset->
pvts[i]);
717 if (state[linkset->
pvts[i]->
cic - startcic]) {
720 sig_ss7_set_remotelyblocked(linkset->
pvts[i], block, type);
722 sig_ss7_set_locallyblocked(linkset->
pvts[i], block, type);
725 sig_ss7_lock_owner(linkset, i);
726 if (linkset->
pvts[i]->owner) {
729 ast_channel_hangupcause_set(linkset->
pvts[i]->owner, SS7_CAUSE_TRY_AGAIN);
731 ast_channel_unlock(linkset->
pvts[i]->owner);
736 sig_ss7_set_remotelyblocked(linkset->
pvts[i], block, type);
738 sig_ss7_set_locallyblocked(linkset->
pvts[i], block, type);
741 sig_ss7_unlock_private(linkset->
pvts[i]);
754 static void ss7_inservice(
struct sig_ss7_linkset *linkset,
int startcic,
int endcic,
unsigned int dpc)
758 for (i = 0; i < linkset->numchans; i++) {
759 if (ss7_match_range(linkset->
pvts[i], startcic, endcic, dpc)) {
760 sig_ss7_lock_private(linkset->
pvts[i]);
761 sig_ss7_set_inservice(linkset->
pvts[i], 1);
762 sig_ss7_unlock_private(linkset->
pvts[i]);
792 int i, startcic, endcic,
dpc;
795 if (linkset->numchans <= 0) {
799 startcic = linkset->
pvts[0]->
cic;
800 p = linkset->
pvts[0];
804 for (i = 0; i < linkset->numchans; i++) {
805 if (linkset->
pvts[i+1]
806 && linkset->
pvts[i+1]->
dpc == dpc
808 && linkset->
pvts[i]->
cic - startcic < (linkset->
type == SS7_ANSI ? 24 : 31)) {
811 endcic = linkset->
pvts[i]->
cic;
812 ast_verb(1,
"Resetting CICs %d to %d\n", startcic, endcic);
814 sig_ss7_lock_private(p);
815 if (!ss7_find_alloc_call(p)) {
816 ast_log(LOG_ERROR,
"Unable to allocate new ss7call\n");
817 }
else if (!(endcic - startcic)) {
818 isup_rsc(linkset->ss7, p->
ss7call);
820 isup_grs(linkset->ss7, p->
ss7call, endcic);
822 sig_ss7_unlock_private(p);
825 if (linkset->
pvts[i+1]) {
826 startcic = linkset->
pvts[i+1]->
cic;
828 p = linkset->
pvts[i+1];
850 isup_rsc(p->ss7->ss7, p->
ss7call);
853 isup_blo(p->ss7->ss7, p->
ss7call);
855 sig_ss7_set_locallyblocked(p, 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
874 if (!linkset->
pvts[which]) {
878 if (!ss7_find_alloc_call(linkset->
pvts[which])) {
882 sig_ss7_set_remotelyblocked(linkset->
pvts[which], 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
883 sig_ss7_set_inservice(linkset->
pvts[which], 0);
884 sig_ss7_loopback(linkset->
pvts[which], 0);
886 sig_ss7_lock_owner(linkset, which);
887 if (linkset->
pvts[which]->owner) {
888 ast_channel_hangupcause_set(linkset->
pvts[which]->owner, AST_CAUSE_NORMAL_CLEARING);
890 ast_channel_unlock(linkset->
pvts[which]->owner);
891 linkset->
pvts[which]->do_hangup = SS7_HANGUP_SEND_RSC;
893 ss7_do_rsc(linkset->
pvts[which]);
913 static void ss7_clear_channels(
struct sig_ss7_linkset *linkset,
int startcic,
int endcic,
int dpc,
int do_hangup)
917 for (i = 0; i < linkset->numchans; i++) {
918 if (ss7_match_range(linkset->
pvts[i], startcic, endcic, dpc)) {
919 sig_ss7_lock_private(linkset->
pvts[i]);
920 sig_ss7_set_inservice(linkset->
pvts[i], 0);
921 sig_ss7_lock_owner(linkset, i);
922 if (linkset->
pvts[i]->owner) {
923 ast_channel_hangupcause_set(linkset->
pvts[i]->owner,
924 AST_CAUSE_NORMAL_CLEARING);
926 ast_channel_unlock(linkset->
pvts[i]->owner);
927 linkset->
pvts[i]->do_hangup = (linkset->
pvts[i]->
cic != startcic) ?
928 do_hangup : SS7_HANGUP_DO_NOTHING;
929 }
else if (linkset->
pvts[i] && linkset->
pvts[i]->
cic != startcic) {
933 sig_ss7_unlock_private(linkset->
pvts[i]);
949 struct ss7 *ss7 = linkset->ss7;
957 if (!(linkset->
flags & LINKSET_FLAG_EXPLICITACM)) {
965 if (linkset->
type == SS7_ITU) {
971 isup_set_echocontrol(p->
ss7call, (linkset->
flags & LINKSET_FLAG_DEFAULTECHOCONTROL) ? 1 : 0);
978 ast_mutex_unlock(&linkset->
lock);
979 sig_ss7_unlock_private(p);
980 c = sig_ss7_new_ast_channel(p,
AST_STATE_RING, law, 0, p->exten, NULL, NULL);
982 ast_log(LOG_WARNING,
"Unable to start PBX on CIC %d\n", p->
cic);
983 ast_mutex_lock(&linkset->
lock);
984 sig_ss7_lock_private(p);
985 isup_rel(linkset->ss7, p->
ss7call, AST_CAUSE_SWITCH_CONGESTION);
993 sig_ss7_lock_private(p);
1008 if (!ast_strlen_zero(p->charge_number)) {
1011 p->charge_number[0] = 0;
1013 if (!ast_strlen_zero(p->gen_add_number)) {
1016 p->gen_add_number[0] = 0;
1018 if (!ast_strlen_zero(p->jip_number)) {
1021 p->jip_number[0] = 0;
1023 if (!ast_strlen_zero(p->gen_dig_number)) {
1026 p->gen_dig_number[0] = 0;
1029 snprintf(tmp,
sizeof(tmp),
"%d", p->gen_dig_type);
1032 p->gen_dig_type = 0;
1034 snprintf(tmp,
sizeof(tmp),
"%d", p->gen_dig_scheme);
1037 p->gen_dig_scheme = 0;
1039 if (!ast_strlen_zero(p->lspi_ident)) {
1042 p->lspi_ident[0] = 0;
1045 snprintf(tmp,
sizeof(tmp),
"%d", p->call_ref_ident);
1048 p->call_ref_ident = 0;
1050 snprintf(tmp,
sizeof(tmp),
"%d", p->call_ref_pc);
1055 snprintf(tmp,
sizeof(tmp),
"%d", p->calling_party_cat);
1058 p->calling_party_cat = 0;
1060 if (p->redirect_counter) {
1063 switch (p->redirect_info_ind) {
1065 strp =
"NO_REDIRECTION";
1068 strp =
"CALL_REROUTED_PRES_ALLOWED";
1071 strp =
"CALL_REROUTED_INFO_RESTRICTED";
1074 strp =
"CALL_DIVERTED_PRES_ALLOWED";
1077 strp =
"CALL_DIVERTED_INFO_RESTRICTED";
1080 strp =
"CALL_REROUTED_PRES_RESTRICTED";
1083 strp =
"CALL_DIVERTED_PRES_RESTRICTED";
1089 strp =
"NO_REDIRECTION";
1094 p->redirect_info_ind = 0;
1098 if (p->redirect_info_counter) {
1099 redirecting.count = p->redirect_info_counter;
1100 if (p->redirect_info_counter != p->redirect_counter) {
1101 if (p->redirect_info_counter < p->redirect_counter) {
1102 redirecting.count = p->redirect_counter;
1104 ast_log(LOG_WARNING,
"Redirect counters differ: %u while info says %u - using %u\n",
1105 p->redirect_counter, p->redirect_info_counter, redirecting.count);
1108 p->redirect_info_counter = 0;
1109 p->redirect_counter = 0;
1112 if (p->redirect_counter) {
1113 redirecting.count = p->redirect_counter;
1115 p->redirect_counter = 0;
1118 switch (p->redirect_info_orig_reas) {
1119 case SS7_REDIRECTING_REASON_UNKNOWN:
1120 redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1122 case SS7_REDIRECTING_REASON_USER_BUSY:
1123 redirecting.orig_reason.code = AST_REDIRECTING_REASON_USER_BUSY;
1125 case SS7_REDIRECTING_REASON_NO_ANSWER:
1126 redirecting.orig_reason.code = AST_REDIRECTING_REASON_NO_ANSWER;
1128 case SS7_REDIRECTING_REASON_UNCONDITIONAL:
1129 redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNCONDITIONAL;
1132 redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1136 switch (p->redirect_info_reas) {
1137 case SS7_REDIRECTING_REASON_UNKNOWN:
1138 redirecting.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1140 case SS7_REDIRECTING_REASON_USER_BUSY:
1141 redirecting.reason.code = AST_REDIRECTING_REASON_USER_BUSY;
1142 if (!p->redirect_info_orig_reas && redirecting.count == 1) {
1143 redirecting.orig_reason.code = AST_REDIRECTING_REASON_USER_BUSY;
1146 case SS7_REDIRECTING_REASON_NO_ANSWER:
1147 redirecting.reason.code = AST_REDIRECTING_REASON_NO_ANSWER;
1148 if (!p->redirect_info_orig_reas && redirecting.count == 1) {
1149 redirecting.orig_reason.code = AST_REDIRECTING_REASON_NO_ANSWER;
1152 case SS7_REDIRECTING_REASON_UNCONDITIONAL:
1153 redirecting.reason.code = AST_REDIRECTING_REASON_UNCONDITIONAL;
1154 if (!p->redirect_info_orig_reas && redirecting.count == 1) {
1155 redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNCONDITIONAL;
1158 case SS7_REDIRECTING_REASON_DEFLECTION_DURING_ALERTING:
1159 case SS7_REDIRECTING_REASON_DEFLECTION_IMMEDIATE_RESPONSE:
1160 redirecting.reason.code = AST_REDIRECTING_REASON_DEFLECTION;
1162 case SS7_REDIRECTING_REASON_UNAVAILABLE:
1163 redirecting.reason.code = AST_REDIRECTING_REASON_UNAVAILABLE;
1166 redirecting.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1170 p->redirect_info_orig_reas = 0;
1171 p->redirect_info_reas = 0;
1173 if (!ast_strlen_zero(p->redirecting_num)) {
1174 redirecting.from.number.str =
ast_strdup(p->redirecting_num);
1175 redirecting.from.number.presentation = p->redirecting_presentation;
1176 redirecting.from.number.valid = 1;
1178 p->redirecting_num[0] = 0;
1181 if (!ast_strlen_zero(p->generic_name)) {
1182 redirecting.from.name.str =
ast_strdup(p->generic_name);
1183 redirecting.from.name.presentation = p->redirecting_presentation;
1184 redirecting.from.name.valid = 1;
1186 p->generic_name[0] = 0;
1189 if (!ast_strlen_zero(p->orig_called_num)) {
1190 redirecting.orig.number.str =
ast_strdup(p->orig_called_num);
1191 redirecting.orig.number.presentation = p->orig_called_presentation;
1192 redirecting.orig.number.valid = 1;
1194 p->orig_called_num[0] = 0;
1195 }
else if (redirecting.count == 1) {
1211 case ISUP_CUG_OUTGOING_ALLOWED:
1212 strp =
"OUTGOING_ALLOWED";
1214 case ISUP_CUG_OUTGOING_NOT_ALLOWED:
1215 strp =
"OUTGOING_NOT_ALLOWED";
1232 sig_ss7_unlock_private(p);
1233 ast_channel_unlock(c);
1236 ast_log(LOG_WARNING,
"Unable to start PBX on %s (CIC %d)\n", ast_channel_name(c), p->
cic);
1239 ast_verb(3,
"Accepting call to '%s' on CIC %d\n", p->exten, p->
cic);
1243 ast_mutex_lock(&linkset->
lock);
1244 sig_ss7_lock_private(p);
1248 static void ss7_apply_plan_to_number(
char *buf,
size_t size,
const struct sig_ss7_linkset *ss7,
const char *
number,
const unsigned nai)
1250 if (ast_strlen_zero(number)) {
1257 case SS7_NAI_INTERNATIONAL:
1260 case SS7_NAI_NATIONAL:
1263 case SS7_NAI_SUBSCRIBER:
1266 case SS7_NAI_UNKNOWN:
1269 case SS7_NAI_NETWORKROUTED:
1270 snprintf(buf, size,
"%s%s", ss7->networkroutedprefix, number);
1273 snprintf(buf, size,
"%s", number);
1278 static int ss7_pres_scr2cid_pres(
char presentation_ind,
char screening_ind)
1280 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
1297 static ast_callid func_ss7_linkset_callid(
struct sig_ss7_linkset *linkset,
int chanpos)
1299 ast_callid callid = 0;
1300 sig_ss7_lock_owner(linkset, chanpos);
1301 if (linkset->
pvts[chanpos]->owner) {
1302 callid = ast_channel_callid(linkset->
pvts[chanpos]->owner);
1303 ast_channel_unlock(linkset->
pvts[chanpos]->owner);
1327 ast_verb(3,
"SS7 exten: %s complete: %d\n", p->exten, p->
called_complete);
1330 && linkset->
type == SS7_ITU
1332 && !isup_start_digittimeout(linkset->ss7, p->
ss7call)) {
1339 sig_ss7_set_dnid(p, p->exten);
1342 if ((e->e == ISUP_EVENT_IAM)
1343 ? !(e->iam.cot_check_required || e->iam.cot_performed_on_previous_cic)
1344 : (!(e->sam.cot_check_required || e->sam.cot_performed_on_previous_cic) || e->sam.cot_check_passed)) {
1345 ss7_start_call(p, linkset);
1350 ast_debug(1,
"Call on CIC for unconfigured extension %s\n", p->exten);
1351 isup_rel(linkset->ss7, (e->e == ISUP_EVENT_IAM) ? e->iam.call : e->sam.call, AST_CAUSE_UNALLOCATED);
1355 void *ss7_linkset(
void *data)
1358 struct timeval *next = NULL, tv;
1360 struct ss7 *ss7 = linkset->ss7;
1361 ss7_event *e = NULL;
1364 unsigned char mb_state[255];
1367 #define SS7_MAX_POLL 60000
1369 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1372 ast_mutex_lock(&linkset->
lock);
1374 ast_mutex_unlock(&linkset->
lock);
1377 ast_mutex_lock(&linkset->
lock);
1378 if ((next = ss7_schedule_next(ss7))) {
1380 tv.tv_sec = next->tv_sec - tv.tv_sec;
1381 tv.tv_usec = next->tv_usec - tv.tv_usec;
1382 if (tv.tv_usec < 0) {
1383 tv.tv_usec += 1000000;
1386 if (tv.tv_sec < 0) {
1390 nextms = tv.tv_sec * 1000;
1391 nextms += tv.tv_usec / 1000;
1392 if (SS7_MAX_POLL < nextms) {
1393 nextms = SS7_MAX_POLL;
1396 nextms = SS7_MAX_POLL;
1399 for (i = 0; i < linkset->numsigchans; i++) {
1400 pollers[i].fd = linkset->fds[i];
1401 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
1402 pollers[i].revents = 0;
1404 ast_mutex_unlock(&linkset->
lock);
1406 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
1407 pthread_testcancel();
1408 res = poll(pollers, linkset->numsigchans, nextms);
1409 pthread_testcancel();
1410 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1412 ast_mutex_lock(&linkset->
lock);
1413 if ((res < 0) && (errno != EINTR)) {
1414 ast_log(LOG_ERROR,
"poll(%s)\n", strerror(errno));
1416 ss7_schedule_run(ss7);
1419 for (i = 0; i < linkset->numsigchans; i++) {
1420 if (pollers[i].revents & POLLPRI) {
1421 sig_ss7_handle_link_exception(linkset, i);
1423 if (pollers[i].revents & POLLIN) {
1424 res = ss7_read(ss7, pollers[i].fd);
1426 if (pollers[i].revents & POLLOUT) {
1427 res = ss7_write(ss7, pollers[i].fd);
1429 ast_debug(1,
"Error in write %s\n", strerror(errno));
1434 while ((e = ss7_check_event(ss7))) {
1435 ast_callid callid = 0;
1439 if (linkset->
debug) {
1440 ast_verbose(
"Linkset %d: Processing event: %s\n",
1441 linkset->
span, ss7_event2str(e->e));
1446 if (linkset->state != LINKSET_STATE_UP) {
1447 ast_verb(1,
"--- SS7 Up ---\n");
1448 ss7_reset_linkset(linkset);
1450 linkset->state = LINKSET_STATE_UP;
1452 case SS7_EVENT_DOWN:
1453 ast_verb(1,
"--- SS7 Down ---\n");
1454 linkset->state = LINKSET_STATE_DOWN;
1455 for (i = 0; i < linkset->numchans; i++) {
1456 p = linkset->
pvts[i];
1458 sig_ss7_set_inservice(p, 0);
1459 if (linkset->
flags & LINKSET_FLAG_INITIALHWBLO) {
1460 sig_ss7_set_remotelyblocked(p, 1, SS7_BLOCKED_HARDWARE);
1466 ast_verb(1,
"MTP2 link up (SLC %d)\n", e->gen.data);
1468 case MTP2_LINK_DOWN:
1469 ast_log(LOG_WARNING,
"MTP2 link down (SLC %d)\n", e->gen.data);
1471 case ISUP_EVENT_CPG:
1472 chanpos = ss7_find_cic_gripe(linkset, e->cpg.cic, e->cpg.opc,
"CPG");
1474 isup_free_call(ss7, e->cpg.call);
1477 p = linkset->
pvts[chanpos];
1478 sig_ss7_lock_private(p);
1479 callid = func_ss7_linkset_callid(linkset, chanpos);
1481 switch (e->cpg.event) {
1482 case CPG_EVENT_ALERTING:
1486 sig_ss7_lock_owner(linkset, chanpos);
1489 if (!ast_strlen_zero(e->cpg.connected_num)) {
1494 ast_connected.id.number.presentation =
1495 ss7_pres_scr2cid_pres(e->cpg.connected_presentation_ind,
1496 e->cpg.connected_screening_ind);
1497 ss7_apply_plan_to_number(connected_num,
sizeof(connected_num),
1498 linkset, e->cpg.connected_num, e->cpg.connected_nai);
1499 ast_connected.id.number.str =
ast_strdup(connected_num);
1500 ast_connected.id.number.valid = 1;
1504 ast_channel_unlock(p->owner);
1508 case CPG_EVENT_PROGRESS:
1509 case CPG_EVENT_INBANDINFO:
1511 ast_debug(1,
"Queuing frame PROGRESS on CIC %d\n", p->
cic);
1514 sig_ss7_set_dialing(p, 0);
1515 sig_ss7_open_media(p);
1519 ast_debug(1,
"Do not handle CPG with event type 0x%x\n", e->cpg.event);
1523 sig_ss7_unlock_private(p);
1525 case ISUP_EVENT_RSC:
1526 ast_verb(1,
"Resetting CIC %d\n", e->rsc.cic);
1527 chanpos = ss7_find_cic_gripe(linkset, e->rsc.cic, e->rsc.opc,
"RSC");
1529 isup_free_call(ss7, e->rsc.call);
1532 p = linkset->
pvts[chanpos];
1533 sig_ss7_lock_private(p);
1535 callid = func_ss7_linkset_callid(linkset, chanpos);
1536 sig_ss7_set_inservice(p, 1);
1537 sig_ss7_set_remotelyblocked(p, 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
1540 isup_blo(ss7, e->rsc.call);
1542 sig_ss7_set_locallyblocked(p, 0, SS7_BLOCKED_HARDWARE);
1545 isup_set_call_dpc(e->rsc.call, p->
dpc);
1546 sig_ss7_lock_owner(linkset, chanpos);
1548 p->do_hangup = SS7_HANGUP_SEND_RLC;
1549 if (!(e->rsc.got_sent_msg & ISUP_SENT_IAM)) {
1551 ast_channel_hangupcause_set(p->owner, AST_CAUSE_NORMAL_CLEARING);
1553 ast_channel_hangupcause_set(p->owner, SS7_CAUSE_TRY_AGAIN);
1556 ss7_queue_pvt_cause_data(p->owner,
"SS7 ISUP_EVENT_RSC", AST_CAUSE_INTERWORKING);
1559 ast_channel_unlock(p->owner);
1561 isup_rlc(ss7, e->rsc.call);
1562 p->
ss7call = isup_free_call_if_clear(ss7, e->rsc.call);
1565 sig_ss7_loopback(p, 0);
1567 sig_ss7_unlock_private(p);
1569 case ISUP_EVENT_GRS:
1570 if (!sig_ss7_find_cic_range(linkset, e->grs.startcic, e->grs.endcic,
1572 ast_log(LOG_WARNING,
"GRS on unconfigured range CIC %d - %d PC %d\n",
1573 e->grs.startcic, e->grs.endcic, e->grs.opc);
1574 chanpos = sig_ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
1576 isup_free_call(ss7, e->grs.call);
1579 p = linkset->
pvts[chanpos];
1580 sig_ss7_lock_private(p);
1581 p->
ss7call = isup_free_call_if_clear(ss7, e->grs.call);
1582 sig_ss7_unlock_private(p);
1587 for (i = e->grs.endcic - e->grs.startcic; 0 <= i; --i) {
1592 chanpos = sig_ss7_find_cic(linkset, e->grs.startcic + i, e->grs.opc);
1593 p = linkset->
pvts[chanpos];
1594 sig_ss7_lock_private(p);
1600 sig_ss7_set_locallyblocked(p, 0, SS7_BLOCKED_HARDWARE);
1603 sig_ss7_set_remotelyblocked(p, 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
1607 isup_gra(ss7, p->
ss7call, e->grs.endcic, mb_state);
1610 sig_ss7_lock_owner(linkset, chanpos);
1615 ast_channel_hangupcause_set(p->owner, SS7_CAUSE_TRY_AGAIN);
1617 ast_channel_hangupcause_set(p->owner, AST_CAUSE_NORMAL_CLEARING);
1619 p->do_hangup = SS7_HANGUP_FREE_CALL;
1620 ast_channel_unlock(p->owner);
1625 isup_free_call(ss7, p->
ss7call);
1628 sig_ss7_set_inservice(p, 1);
1629 sig_ss7_unlock_private(p);
1632 case ISUP_EVENT_CQM:
1633 ast_debug(1,
"Got Circuit group query message from CICs %d to %d\n",
1634 e->cqm.startcic, e->cqm.endcic);
1635 ss7_handle_cqm(linkset, e);
1637 case ISUP_EVENT_GRA:
1638 if (!sig_ss7_find_cic_range(linkset, e->gra.startcic,
1639 e->gra.endcic, e->gra.opc)) {
1640 ast_log(LOG_WARNING,
"GRA on unconfigured range CIC %d - %d PC %d\n",
1641 e->gra.startcic, e->gra.endcic, e->gra.opc);
1642 isup_free_call(ss7, e->gra.call);
1645 ast_verb(1,
"Got reset acknowledgement from CIC %d to %d DPC: %d\n",
1646 e->gra.startcic, e->gra.endcic, e->gra.opc);
1647 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc,
1648 e->gra.status, 1, 1, SS7_BLOCKED_MAINTENANCE);
1649 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
1651 chanpos = sig_ss7_find_cic(linkset, e->gra.startcic, e->gra.opc);
1653 isup_free_call(ss7, e->gra.call);
1657 p = linkset->
pvts[chanpos];
1658 sig_ss7_lock_private(p);
1661 p->
ss7call = isup_free_call_if_clear(ss7, e->gra.call);
1662 sig_ss7_unlock_private(p);
1664 case ISUP_EVENT_SAM:
1665 chanpos = ss7_find_cic_gripe(linkset, e->sam.cic, e->sam.opc,
"SAM");
1667 isup_free_call(ss7, e->sam.call);
1670 p = linkset->
pvts[chanpos];
1671 sig_ss7_lock_private(p);
1672 sig_ss7_lock_owner(linkset, chanpos);
1674 ast_log(LOG_WARNING,
"SAM on CIC %d PC %d already have call\n", e->sam.cic, e->sam.opc);
1675 ast_channel_unlock(p->owner);
1676 sig_ss7_unlock_private(p);
1680 if (!ast_strlen_zero(e->sam.called_party_num)) {
1682 strncat(p->exten, e->sam.called_party_num,
sizeof(p->exten) - strlen(p->exten) - 1);
1683 st = strchr(p->exten,
'#');
1688 ss7_match_extension(linkset, p, e);
1690 sig_ss7_unlock_private(p);
1692 case ISUP_EVENT_IAM:
1693 ast_debug(1,
"Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
1694 chanpos = ss7_find_cic_gripe(linkset, e->iam.cic, e->iam.opc,
"IAM");
1696 isup_free_call(ss7, e->iam.call);
1699 p = linkset->
pvts[chanpos];
1700 sig_ss7_lock_private(p);
1708 ast_log(LOG_NOTICE,
"Got IAM on remotely blocked CIC %d DPC %d remove blocking\n", e->iam.cic, e->iam.opc);
1709 sig_ss7_set_remotelyblocked(p, 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
1710 sig_ss7_set_inservice(p, 1);
1713 if (!sig_ss7_is_chan_available(p)) {
1715 isup_rel(ss7, e->iam.call, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
1717 isup_clear_callflags(ss7, e->iam.call, ISUP_GOT_IAM);
1718 p->
ss7call = isup_free_call_if_clear(ss7, e->iam.call);
1719 ast_log(LOG_WARNING,
"Got IAM on locally blocked CIC %d DPC %d, ignore\n", e->iam.cic, e->iam.opc);
1721 sig_ss7_unlock_private(p);
1731 if ((p->
use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
1732 ss7_apply_plan_to_number(p->cid_num,
sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.
calling_nai);
1733 p->
callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
1736 if (e->iam.presentation_ind) {
1737 p->
callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
1745 }
else if (!ast_strlen_zero(e->iam.called_party_num)) {
1747 ss7_apply_plan_to_number(p->exten,
sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.
called_nai);
1748 st = strchr(p->exten,
'#');
1757 p->cid_ani[0] =
'\0';
1758 if ((p->
use_callerid) && (!ast_strlen_zero(e->iam.generic_name))) {
1759 ast_copy_string(p->cid_name, e->iam.generic_name,
sizeof(p->cid_name));
1761 p->cid_name[0] =
'\0';
1766 ast_copy_string(p->charge_number, e->iam.charge_number,
sizeof(p->charge_number));
1767 ast_copy_string(p->gen_add_number, e->iam.gen_add_number,
sizeof(p->gen_add_number));
1768 p->gen_add_type = e->iam.gen_add_type;
1769 p->gen_add_nai = e->iam.gen_add_nai;
1770 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
1771 p->gen_add_num_plan = e->iam.gen_add_num_plan;
1772 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number,
sizeof(p->gen_dig_number));
1773 p->gen_dig_type = e->iam.gen_dig_type;
1774 p->gen_dig_scheme = e->iam.gen_dig_scheme;
1775 ast_copy_string(p->jip_number, e->iam.jip_number,
sizeof(p->jip_number));
1776 if (!ast_strlen_zero(e->iam.orig_called_num)) {
1777 ss7_apply_plan_to_number(p->orig_called_num,
sizeof(p->orig_called_num), linkset, e->iam.orig_called_num, e->iam.orig_called_nai);
1778 p->orig_called_presentation = ss7_pres_scr2cid_pres(e->iam.orig_called_pres_ind, e->iam.orig_called_screening_ind);
1780 if (!ast_strlen_zero(e->iam.redirecting_num)) {
1781 ss7_apply_plan_to_number(p->redirecting_num,
sizeof(p->redirecting_num), linkset, e->iam.redirecting_num, e->iam.redirecting_num_nai);
1782 p->redirecting_presentation = ss7_pres_scr2cid_pres(e->iam.redirecting_num_presentation_ind, e->iam.redirecting_num_screening_ind);
1784 ast_copy_string(p->generic_name, e->iam.generic_name,
sizeof(p->generic_name));
1785 p->calling_party_cat = e->iam.calling_party_cat;
1786 p->redirect_counter = e->iam.redirect_counter;
1787 p->redirect_info = e->iam.redirect_info;
1788 p->redirect_info_ind = e->iam.redirect_info_ind;
1789 p->redirect_info_orig_reas = e->iam.redirect_info_orig_reas;
1790 p->redirect_info_counter = e->iam.redirect_info_counter;
1791 if (p->redirect_info_counter && !p->redirect_counter) {
1792 p->redirect_counter = p->redirect_info_counter;
1794 p->redirect_info_reas = e->iam.redirect_info_reas;
1799 if (e->iam.cot_check_required) {
1800 sig_ss7_loopback(p, 1);
1803 p->echocontrol_ind = e->iam.echocontrol_ind;
1804 sig_ss7_set_caller_id(p);
1805 ss7_match_extension(linkset, p, e);
1806 sig_ss7_unlock_private(p);
1808 if (e->iam.cot_performed_on_previous_cic) {
1809 chanpos = sig_ss7_find_cic(linkset, (e->iam.cic - 1), e->iam.opc);
1812 ast_verb(1,
"COT request on previous nonexistent CIC %d in IAM PC %d\n", (e->iam.cic - 1), e->iam.opc);
1815 ast_verb(1,
"COT request on previous CIC %d in IAM PC %d\n", (e->iam.cic - 1), e->iam.opc);
1816 p = linkset->
pvts[chanpos];
1817 sig_ss7_lock_private(p);
1818 if (sig_ss7_is_chan_available(p)) {
1819 sig_ss7_set_inservice(p, 0);
1820 sig_ss7_loopback(p, 1);
1822 sig_ss7_unlock_private(p);
1825 case ISUP_EVENT_DIGITTIMEOUT:
1826 chanpos = ss7_find_cic_gripe(linkset, e->digittimeout.cic, e->digittimeout.opc,
"DIGITTIMEOUT");
1828 isup_free_call(ss7, e->digittimeout.call);
1831 p = linkset->
pvts[chanpos];
1832 sig_ss7_lock_private(p);
1833 ast_debug(1,
"Digittimeout on CIC: %d PC: %d\n", e->digittimeout.cic, e->digittimeout.opc);
1837 sig_ss7_set_dnid(p, p->exten);
1840 if (!(e->digittimeout.cot_check_required || e->digittimeout.cot_performed_on_previous_cic) || e->digittimeout.cot_check_passed) {
1841 ss7_start_call(p, linkset);
1844 ast_debug(1,
"Call on CIC for unconfigured extension %s\n", p->exten);
1845 isup_rel(linkset->ss7, e->digittimeout.call, AST_CAUSE_UNALLOCATED);
1847 sig_ss7_unlock_private(p);
1849 case ISUP_EVENT_COT:
1850 if (e->cot.cot_performed_on_previous_cic) {
1851 chanpos = sig_ss7_find_cic(linkset, (e->cot.cic - 1), e->cot.opc);
1854 p = linkset->
pvts[chanpos];
1855 sig_ss7_lock_private(p);
1856 sig_ss7_set_inservice(p, 1);
1857 sig_ss7_loopback(p, 0);
1858 sig_ss7_unlock_private(p);;
1859 ast_verb(1,
"Loop turned off on CIC: %d PC: %d\n", (e->cot.cic - 1), e->cot.opc);
1863 chanpos = ss7_find_cic_gripe(linkset, e->cot.cic, e->cot.opc,
"COT");
1865 isup_free_call(ss7, e->cot.call);
1868 p = linkset->
pvts[chanpos];
1870 sig_ss7_lock_private(p);
1874 sig_ss7_loopback(p, 0);
1875 ast_verb(1,
"Loop turned off on CIC: %d PC: %d\n", e->cot.cic, e->cot.opc);
1879 if ((e->cot.got_sent_msg & ISUP_GOT_IAM) && e->cot.passed && p->
called_complete) {
1880 ss7_start_call(p, linkset);
1884 sig_ss7_unlock_private(p);
1886 case ISUP_EVENT_CCR:
1887 ast_debug(1,
"Got CCR request on CIC %d\n", e->ccr.cic);
1888 chanpos = ss7_find_cic_gripe(linkset, e->ccr.cic, e->ccr.opc,
"CCR");
1890 isup_free_call(ss7, e->ccr.call);
1894 p = linkset->
pvts[chanpos];
1896 sig_ss7_lock_private(p);
1898 sig_ss7_loopback(p, 1);
1899 if (linkset->
type == SS7_ANSI) {
1900 isup_lpa(linkset->ss7, e->ccr.cic, p->
dpc);
1902 sig_ss7_unlock_private(p);
1904 case ISUP_EVENT_CVT:
1905 ast_debug(1,
"Got CVT request on CIC %d\n", e->cvt.cic);
1906 chanpos = ss7_find_cic_gripe(linkset, e->cvt.cic, e->cvt.opc,
"CVT");
1908 isup_free_call(ss7, e->cvt.call);
1912 p = linkset->
pvts[chanpos];
1914 sig_ss7_lock_private(p);
1916 sig_ss7_loopback(p, 1);
1918 p->
ss7call = isup_free_call_if_clear(ss7, e->cvt.call);
1920 isup_cvr(linkset->ss7, e->cvt.cic, p->
dpc);
1921 sig_ss7_unlock_private(p);
1923 case ISUP_EVENT_REL:
1924 chanpos = ss7_find_cic_gripe(linkset, e->rel.cic, e->rel.opc,
"REL");
1926 isup_free_call(ss7, e->rel.call);
1929 p = linkset->
pvts[chanpos];
1930 sig_ss7_lock_private(p);
1932 callid = func_ss7_linkset_callid(linkset, chanpos);
1933 sig_ss7_lock_owner(linkset, chanpos);
1935 snprintf(cause_str,
sizeof(cause_str),
"SS7 ISUP_EVENT_REL (%d)", e->rel.cause);
1936 ss7_queue_pvt_cause_data(p->owner, cause_str, e->rel.cause);
1938 ast_channel_hangupcause_set(p->owner, e->rel.cause);
1940 p->do_hangup = SS7_HANGUP_SEND_RLC;
1941 ast_channel_unlock(p->owner);
1943 ast_verb(1,
"REL on CIC %d DPC %d without owner!\n", p->
cic, p->
dpc);
1949 sig_ss7_loopback(p, 0);
1952 sig_ss7_unlock_private(p);
1954 case ISUP_EVENT_ACM:
1955 chanpos = ss7_find_cic_gripe(linkset, e->acm.cic, e->acm.opc,
"ACM");
1957 isup_free_call(ss7, e->acm.call);
1961 p = linkset->
pvts[chanpos];
1963 ast_debug(1,
"Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->
cic);
1965 if (e->acm.call_ref_ident > 0) {
1969 sig_ss7_lock_private(p);
1971 callid = func_ss7_linkset_callid(linkset, chanpos);
1976 sig_ss7_set_dialing(p, 0);
1978 if (e->acm.called_party_status_ind == 1) {
1982 sig_ss7_lock_owner(linkset, chanpos);
1985 ast_channel_unlock(p->owner);
1989 p->echocontrol_ind = e->acm.echocontrol_ind;
1990 sig_ss7_unlock_private(p);
1992 case ISUP_EVENT_CGB:
1993 chanpos = ss7_find_cic_gripe(linkset, e->cgb.startcic, e->cgb.opc,
"CGB");
1995 isup_free_call(ss7, e->cgb.call);
1998 p = linkset->
pvts[chanpos];
1999 ss7_check_range(linkset, e->cgb.startcic, e->cgb.endcic,
2000 e->cgb.opc, e->cgb.status);
2001 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic,
2002 e->cgb.opc, e->cgb.status, 1, 1,
2003 (e->cgb.type) ? SS7_BLOCKED_HARDWARE : SS7_BLOCKED_MAINTENANCE);
2005 sig_ss7_lock_private(p);
2008 isup_cgba(linkset->ss7, p->
ss7call, e->cgb.endcic, e->cgb.status);
2010 p->
ss7call = isup_free_call_if_clear(ss7, e->cgb.call);
2012 sig_ss7_unlock_private(p);
2014 case ISUP_EVENT_CGU:
2015 chanpos = ss7_find_cic_gripe(linkset, e->cgu.startcic, e->cgu.opc,
"CGU");
2017 isup_free_call(ss7, e->cgu.call);
2020 p = linkset->
pvts[chanpos];
2021 ss7_check_range(linkset, e->cgu.startcic, e->cgu.endcic,
2022 e->cgu.opc, e->cgu.status);
2023 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic,
2024 e->cgu.opc, e->cgu.status, 0, 1,
2025 e->cgu.
type ? SS7_BLOCKED_HARDWARE : SS7_BLOCKED_MAINTENANCE);
2027 sig_ss7_lock_private(p);
2030 isup_cgua(linkset->ss7, p->
ss7call, e->cgu.endcic, e->cgu.status);
2032 p->
ss7call = isup_free_call_if_clear(ss7, e->cgu.call);
2034 sig_ss7_unlock_private(p);
2036 case ISUP_EVENT_UCIC:
2037 chanpos = ss7_find_cic_gripe(linkset, e->ucic.cic, e->ucic.opc,
"UCIC");
2039 isup_free_call(ss7, e->ucic.call);
2042 p = linkset->
pvts[chanpos];
2043 ast_debug(1,
"Unequipped Circuit Id Code on CIC %d\n", e->ucic.cic);
2044 sig_ss7_lock_private(p);
2045 sig_ss7_lock_owner(linkset, chanpos);
2048 ast_channel_unlock(p->owner);
2050 sig_ss7_set_remotelyblocked(p, 1, SS7_BLOCKED_MAINTENANCE);
2051 sig_ss7_set_inservice(p, 0);
2053 isup_free_call(ss7, e->ucic.call);
2054 sig_ss7_unlock_private(p);
2056 case ISUP_EVENT_BLO:
2057 chanpos = ss7_find_cic_gripe(linkset, e->blo.cic, e->blo.opc,
"BLO");
2059 isup_free_call(ss7, e->blo.call);
2062 p = linkset->
pvts[chanpos];
2063 ast_debug(1,
"Blocking CIC %d\n", e->blo.cic);
2064 sig_ss7_lock_private(p);
2066 sig_ss7_set_remotelyblocked(p, 1, SS7_BLOCKED_MAINTENANCE);
2067 isup_bla(linkset->ss7, e->blo.call);
2068 sig_ss7_lock_owner(linkset, chanpos);
2070 p->
ss7call = isup_free_call_if_clear(ss7, e->blo.call);
2072 if (e->blo.got_sent_msg & ISUP_SENT_IAM) {
2074 ast_channel_hangupcause_set(p->owner, SS7_CAUSE_TRY_AGAIN);
2076 ast_channel_unlock(p->owner);
2078 sig_ss7_unlock_private(p);
2080 case ISUP_EVENT_BLA:
2081 chanpos = ss7_find_cic_gripe(linkset, e->bla.cic, e->bla.opc,
"BLA");
2083 isup_free_call(ss7, e->bla.call);
2086 ast_debug(1,
"Locally blocking CIC %d\n", e->bla.cic);
2087 p = linkset->
pvts[chanpos];
2088 sig_ss7_lock_private(p);
2090 sig_ss7_set_locallyblocked(p, 1, SS7_BLOCKED_MAINTENANCE);
2094 sig_ss7_unlock_private(p);
2096 case ISUP_EVENT_UBL:
2097 chanpos = ss7_find_cic_gripe(linkset, e->ubl.cic, e->ubl.opc,
"UBL");
2099 isup_free_call(ss7, e->ubl.call);
2102 p = linkset->
pvts[chanpos];
2103 ast_debug(1,
"Remotely unblocking CIC %d PC %d\n", e->ubl.cic, e->ubl.opc);
2104 sig_ss7_lock_private(p);
2106 sig_ss7_set_remotelyblocked(p, 0, SS7_BLOCKED_MAINTENANCE);
2107 isup_uba(linkset->ss7, e->ubl.call);
2111 sig_ss7_unlock_private(p);
2113 case ISUP_EVENT_UBA:
2114 chanpos = ss7_find_cic_gripe(linkset, e->uba.cic, e->uba.opc,
"UBA");
2116 isup_free_call(ss7, e->uba.call);
2119 p = linkset->
pvts[chanpos];
2120 ast_debug(1,
"Locally unblocking CIC %d PC %d\n", e->uba.cic, e->uba.opc);
2121 sig_ss7_lock_private(p);
2123 sig_ss7_set_locallyblocked(p, 0, SS7_BLOCKED_MAINTENANCE);
2127 sig_ss7_unlock_private(p);
2129 case ISUP_EVENT_CON:
2130 case ISUP_EVENT_ANM:
2131 if (e->e == ISUP_EVENT_CON) {
2132 chanpos = ss7_find_cic_gripe(linkset, e->con.cic, e->con.opc,
"CON");
2134 isup_free_call(ss7, e->con.call);
2138 chanpos = ss7_find_cic_gripe(linkset, e->anm.cic, e->anm.opc,
"ANM");
2140 isup_free_call(ss7, e->anm.call);
2145 p = linkset->
pvts[chanpos];
2146 sig_ss7_lock_private(p);
2147 p->
ss7call = (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call;
2148 callid = func_ss7_linkset_callid(linkset, chanpos);
2153 if (!ast_strlen_zero((e->e == ISUP_EVENT_ANM)
2154 ? e->anm.connected_num : e->con.connected_num)) {
2155 sig_ss7_lock_owner(linkset, chanpos);
2161 if (e->e == ISUP_EVENT_ANM) {
2162 ast_connected.id.number.presentation = ss7_pres_scr2cid_pres(
2163 e->anm.connected_presentation_ind,
2164 e->anm.connected_screening_ind);
2165 ss7_apply_plan_to_number(connected_num,
sizeof(connected_num),
2166 linkset, e->anm.connected_num, e->anm.connected_nai);
2167 ast_connected.id.number.str =
ast_strdup(connected_num);
2169 ast_connected.id.number.presentation = ss7_pres_scr2cid_pres(
2170 e->con.connected_presentation_ind,
2171 e->con.connected_screening_ind);
2172 ss7_apply_plan_to_number(connected_num,
sizeof(connected_num),
2173 linkset, e->con.connected_num, e->con.connected_nai);
2174 ast_connected.id.number.str =
ast_strdup(connected_num);
2176 ast_connected.id.number.valid = 1;
2180 ast_channel_unlock(p->owner);
2185 sig_ss7_set_dialing(p, 0);
2186 sig_ss7_open_media(p);
2187 if (((e->e == ISUP_EVENT_ANM) ? !e->anm.echocontrol_ind :
2188 !e->con.echocontrol_ind) || !(linkset->
flags & LINKSET_FLAG_USEECHOCONTROL)) {
2189 sig_ss7_set_echocanceller(p, 1);
2191 sig_ss7_unlock_private(p);
2193 case ISUP_EVENT_RLC:
2194 chanpos = ss7_find_cic_gripe(linkset, e->rlc.cic, e->rlc.opc,
"RLC");
2196 isup_free_call(ss7, e->rlc.call);
2200 p = linkset->
pvts[chanpos];
2201 sig_ss7_lock_private(p);
2203 callid = func_ss7_linkset_callid(linkset, chanpos);
2204 if (e->rlc.got_sent_msg & (ISUP_SENT_RSC | ISUP_SENT_REL)) {
2205 sig_ss7_loopback(p, 0);
2206 if (e->rlc.got_sent_msg & ISUP_SENT_RSC) {
2207 sig_ss7_set_inservice(p, 1);
2210 sig_ss7_lock_owner(linkset, chanpos);
2212 p->
ss7call = isup_free_call_if_clear(ss7, e->rlc.call);
2215 p->do_hangup = SS7_HANGUP_DO_NOTHING;
2217 ast_channel_unlock(p->owner);
2219 sig_ss7_unlock_private(p);
2221 case ISUP_EVENT_FAA:
2226 chanpos = ss7_find_cic_gripe(linkset, e->faa.cic, e->faa.opc,
"FAA");
2228 isup_free_call(ss7, e->faa.call);
2233 p = linkset->
pvts[chanpos];
2234 sig_ss7_lock_private(p);
2235 callid = func_ss7_linkset_callid(linkset, chanpos);
2236 ast_debug(1,
"FAA received on CIC %d\n", e->faa.cic);
2237 p->
ss7call = isup_free_call_if_clear(ss7, e->faa.call);
2238 sig_ss7_unlock_private(p);
2240 case ISUP_EVENT_CGBA:
2241 chanpos = ss7_find_cic_gripe(linkset, e->cgba.startcic, e->cgba.opc,
"CGBA");
2243 isup_free_call(ss7, e->cgba.call);
2247 ss7_block_cics(linkset, e->cgba.startcic, e->cgba.endcic,
2248 e->cgba.opc, e->cgba.status, 1, 0,
2249 e->cgba.
type ? SS7_BLOCKED_HARDWARE : SS7_BLOCKED_MAINTENANCE);
2251 p = linkset->
pvts[chanpos];
2252 sig_ss7_lock_private(p);
2258 sig_ss7_unlock_private(p);
2260 case ISUP_EVENT_CGUA:
2261 chanpos = ss7_find_cic_gripe(linkset, e->cgua.startcic, e->cgua.opc,
"CGUA");
2263 isup_free_call(ss7, e->cgua.call);
2267 ss7_block_cics(linkset, e->cgua.startcic, e->cgua.endcic,
2268 e->cgua.opc, e->cgua.status, 0, 0,
2269 e->cgba.
type ? SS7_BLOCKED_HARDWARE : SS7_BLOCKED_MAINTENANCE);
2271 p = linkset->
pvts[chanpos];
2272 sig_ss7_lock_private(p);
2278 sig_ss7_unlock_private(p);
2280 case ISUP_EVENT_SUS:
2281 chanpos = ss7_find_cic_gripe(linkset, e->sus.cic, e->sus.opc,
"SUS");
2283 isup_free_call(ss7, e->sus.call);
2287 p = linkset->
pvts[chanpos];
2288 sig_ss7_lock_private(p);
2293 sig_ss7_unlock_private(p);
2295 case ISUP_EVENT_RES:
2296 chanpos = ss7_find_cic_gripe(linkset, e->res.cic, e->res.opc,
"RES");
2298 isup_free_call(ss7, e->res.call);
2302 p = linkset->
pvts[chanpos];
2303 sig_ss7_lock_private(p);
2308 sig_ss7_unlock_private(p);
2311 ast_debug(1,
"Unknown event %s\n", ss7_event2str(e->e));
2320 ast_mutex_unlock(&linkset->
lock);
2329 ast_mutex_unlock(&ss7->
lock);
2332 if (ss7->
master != AST_PTHREADT_NULL) {
2333 pthread_kill(ss7->
master, SIGURG);
2340 while (ast_mutex_trylock(&ss7->
lock)) {
2342 sig_ss7_deadlock_avoidance_private(pvt);
2356 int sig_ss7_reset_cic(
struct sig_ss7_linkset *linkset,
int cic,
unsigned int dpc)
2360 ast_mutex_lock(&linkset->
lock);
2361 for (i = 0; i < linkset->numchans; i++) {
2362 if (linkset->
pvts[i] && linkset->
pvts[i]->
cic == cic && linkset->
pvts[i]->
dpc == dpc) {
2365 sig_ss7_lock_private(linkset->
pvts[i]);
2366 sig_ss7_set_locallyblocked(linkset->
pvts[i], 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
2367 res = ss7_start_rsc(linkset, i);
2368 sig_ss7_unlock_private(linkset->
pvts[i]);
2388 int sig_ss7_cic_blocking(
struct sig_ss7_linkset *linkset,
int do_block,
int which)
2390 ast_mutex_lock(&linkset->
lock);
2391 sig_ss7_lock_private(linkset->
pvts[which]);
2392 if (!ss7_find_alloc_call(linkset->
pvts[which])) {
2393 sig_ss7_unlock_private(linkset->
pvts[which]);
2399 isup_blo(linkset->ss7, linkset->
pvts[which]->
ss7call);
2401 isup_ubl(linkset->ss7, linkset->
pvts[which]->
ss7call);
2404 sig_ss7_unlock_private(linkset->
pvts[which]);
2425 int sig_ss7_group_blocking(
struct sig_ss7_linkset *linkset,
int do_block,
int chanpos,
int endcic,
unsigned char state[],
int type)
2427 sig_ss7_lock_private(linkset->
pvts[chanpos]);
2428 if (!ss7_find_alloc_call(linkset->
pvts[chanpos])) {
2429 sig_ss7_unlock_private(linkset->
pvts[chanpos]);
2434 isup_cgb(linkset->ss7, linkset->
pvts[chanpos]->
ss7call, endcic, state, type);
2436 isup_cgu(linkset->ss7, linkset->
pvts[chanpos]->
ss7call, endcic, state, type);
2439 sig_ss7_unlock_private(linkset->
pvts[chanpos]);
2456 int sig_ss7_reset_group(
struct sig_ss7_linkset *linkset,
int cic,
unsigned int dpc,
int range)
2460 for (i = 0; i < linkset->numchans; i++) {
2461 if (linkset->
pvts[i] && linkset->
pvts[i]->
cic == cic && linkset->
pvts[i]->
dpc == dpc) {
2462 ss7_clear_channels(linkset, cic, cic + range, dpc, SS7_HANGUP_FREE_CALL);
2463 ss7_block_cics(linkset, cic, cic + range, dpc, NULL, 0, 1,
2464 SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
2465 ss7_block_cics(linkset, cic, cic + range, dpc, NULL, 0, 0,
2466 SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
2468 sig_ss7_lock_private(linkset->
pvts[i]);
2469 if (!ss7_find_alloc_call(linkset->
pvts[i])) {
2470 sig_ss7_unlock_private(linkset->
pvts[i]);
2474 sig_ss7_unlock_private(linkset->
pvts[i]);
2481 void sig_ss7_free_isup_call(
struct sig_ss7_linkset *linkset,
int channel)
2483 sig_ss7_lock_private(linkset->
pvts[channel]);
2485 isup_free_call(linkset->ss7, linkset->
pvts[channel]->
ss7call);
2488 sig_ss7_unlock_private(linkset->
pvts[channel]);
2491 static int ss7_parse_prefix(
struct sig_ss7_chan *p,
const char *number,
char *nai)
2497 *nai = SS7_NAI_INTERNATIONAL;
2500 *nai = SS7_NAI_NATIONAL;
2501 }
else if (strncmp(number, p->ss7->networkroutedprefix, strlen(p->ss7->networkroutedprefix)) == 0) {
2502 strip = strlen(p->ss7->networkroutedprefix);
2503 *nai = SS7_NAI_NETWORKROUTED;
2506 *nai = SS7_NAI_UNKNOWN;
2509 *nai = SS7_NAI_SUBSCRIBER;
2511 *nai = SS7_NAI_SUBSCRIBER;
2526 linkset->linkstate[which] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
2527 linkset->linkstate[which] &= ~LINKSTATE_UP;
2528 ss7_link_alarm(linkset->ss7, linkset->fds[which]);
2540 linkset->linkstate[which] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
2541 linkset->linkstate[which] |= LINKSTATE_STARTING;
2542 ss7_link_noalarm(linkset->ss7, linkset->fds[which]);
2562 int sig_ss7_add_sigchan(
struct sig_ss7_linkset *linkset,
int which,
int ss7type,
int transport,
int inalarm,
int networkindicator,
int pointcode,
int adjpointcode,
int cur_slc)
2564 if (!linkset->ss7) {
2565 linkset->
type = ss7type;
2566 linkset->ss7 = ss7_new(ss7type);
2567 if (!linkset->ss7) {
2568 ast_log(LOG_ERROR,
"Can't create new SS7!\n");
2573 ss7_set_network_ind(linkset->ss7, networkindicator);
2574 ss7_set_pc(linkset->ss7, pointcode);
2576 if (ss7_add_link(linkset->ss7, transport, linkset->fds[which], cur_slc, adjpointcode)) {
2577 ast_log(LOG_WARNING,
"Could not add SS7 link!\n");
2581 linkset->linkstate[which] = LINKSTATE_DOWN | LINKSTATE_INALARM;
2582 ss7_link_alarm(linkset->ss7, linkset->fds[which]);
2584 linkset->linkstate[which] = LINKSTATE_DOWN;
2585 ss7_link_noalarm(linkset->ss7, linkset->fds[which]);
2609 ast_mutex_lock(&p->ss7->
lock);
2610 available = sig_ss7_is_chan_available(p);
2614 ast_log(LOG_ERROR,
"Unable to allocate new SS7 call!\n");
2620 ast_mutex_unlock(&p->ss7->
lock);
2625 static unsigned char cid_pres2ss7pres(
int cid_pres)
2627 return (cid_pres >> 5) & 0x03;
2630 static unsigned char cid_pres2ss7screen(
int cid_pres)
2632 return cid_pres & 0x03;
2637 int connected_strip = 0;
2639 unsigned char connected_pres;
2640 unsigned char connected_screen;
2641 const char *connected_num;
2649 connected_strip = ss7_parse_prefix(p, connected_num, &connected_nai);
2657 isup_set_connected(p->
ss7call, connected_num + connected_strip, connected_nai, connected_pres, connected_screen);
2665 case AST_REDIRECTING_REASON_USER_BUSY:
2666 return SS7_REDIRECTING_REASON_USER_BUSY;
2667 case AST_REDIRECTING_REASON_NO_ANSWER:
2668 return SS7_REDIRECTING_REASON_NO_ANSWER;
2669 case AST_REDIRECTING_REASON_UNCONDITIONAL:
2670 return SS7_REDIRECTING_REASON_UNCONDITIONAL;
2673 if (orig || reason == AST_REDIRECTING_REASON_UNKNOWN) {
2674 return SS7_REDIRECTING_REASON_UNKNOWN;
2677 if (reason == AST_REDIRECTING_REASON_UNAVAILABLE) {
2678 return SS7_REDIRECTING_REASON_UNAVAILABLE;
2681 if (reason == AST_REDIRECTING_REASON_DEFLECTION) {
2683 return SS7_REDIRECTING_REASON_DEFLECTION_DURING_ALERTING;
2685 return SS7_REDIRECTING_REASON_DEFLECTION_IMMEDIATE_RESPONSE;
2688 return SS7_REDIRECTING_REASON_UNKNOWN;
2691 static unsigned char ss7_redirect_info_ind(
struct ast_channel *ast)
2693 const char *redirect_info_ind;
2697 if (!ast_strlen_zero(redirect_info_ind)) {
2698 if (!strcasecmp(redirect_info_ind,
"CALL_REROUTED_PRES_ALLOWED")) {
2699 return SS7_INDICATION_REROUTED_PRES_ALLOWED;
2701 if (!strcasecmp(redirect_info_ind,
"CALL_REROUTED_INFO_RESTRICTED")) {
2702 return SS7_INDICATION_REROUTED_INFO_RESTRICTED;
2704 if (!strcasecmp(redirect_info_ind,
"CALL_DIVERTED_PRES_ALLOWED")) {
2705 return SS7_INDICATION_DIVERTED_PRES_ALLOWED;
2707 if (!strcasecmp(redirect_info_ind,
"CALL_DIVERTED_INFO_RESTRICTED")) {
2708 return SS7_INDICATION_DIVERTED_INFO_RESTRICTED;
2710 if (!strcasecmp(redirect_info_ind,
"CALL_REROUTED_PRES_RESTRICTED")) {
2711 return SS7_INDICATION_REROUTED_PRES_RESTRICTED;
2713 if (!strcasecmp(redirect_info_ind,
"CALL_DIVERTED_PRES_RESTRICTED")) {
2714 return SS7_INDICATION_DIVERTED_PRES_RESTRICTED;
2716 if (!strcasecmp(redirect_info_ind,
"SPARE")) {
2717 return SS7_INDICATION_SPARE;
2719 return SS7_INDICATION_NO_REDIRECTION;
2722 if (redirecting->
reason.
code == AST_REDIRECTING_REASON_DEFLECTION) {
2725 return SS7_INDICATION_DIVERTED_PRES_ALLOWED;
2727 return SS7_INDICATION_DIVERTED_PRES_RESTRICTED;
2729 return SS7_INDICATION_DIVERTED_INFO_RESTRICTED;
2734 return SS7_INDICATION_REROUTED_PRES_ALLOWED;
2736 return SS7_INDICATION_REROUTED_PRES_RESTRICTED;
2738 return SS7_INDICATION_REROUTED_INFO_RESTRICTED;
2743 int num_nai_strip = 0;
2746 if (!redirecting->
count) {
2750 isup_set_redirect_counter(p->
ss7call, redirecting->
count);
2753 char ss7_orig_called_nai = p->ss7->
called_nai;
2756 if (ss7_orig_called_nai == SS7_NAI_DYNAMIC) {
2757 num_nai_strip = ss7_parse_prefix(p, ss7_orig_called_num, &ss7_orig_called_nai);
2761 isup_set_orig_called_num(p->
ss7call, ss7_orig_called_num + num_nai_strip,
2762 ss7_orig_called_nai,
2768 char ss7_redirecting_num_nai = p->ss7->
calling_nai;
2771 if (ss7_redirecting_num_nai == SS7_NAI_DYNAMIC) {
2772 num_nai_strip = ss7_parse_prefix(p, redirecting_number, &ss7_redirecting_num_nai);
2777 isup_set_redirecting_number(p->
ss7call, redirecting_number + num_nai_strip,
2778 ss7_redirecting_num_nai,
2783 isup_set_redirection_info(p->
ss7call, ss7_redirect_info_ind(ast),
2784 ss7_redirect_reason(p, ast_channel_redirecting(ast), 1),
2785 redirecting->
count, ss7_redirect_reason(p, ast_channel_redirecting(ast), 0));
2801 char ss7_called_nai;
2802 int called_nai_strip;
2803 char ss7_calling_nai;
2804 int calling_nai_strip;
2805 const char *col_req = NULL;
2806 const char *ss7_cug_indicator_str;
2807 const char *ss7_cug_interlock_ni;
2808 const char *ss7_cug_interlock_code;
2809 const char *ss7_interworking_indicator;
2810 const char *ss7_forward_indicator_pmbits;
2811 unsigned char ss7_cug_indicator;
2812 const char *charge_str = NULL;
2813 const char *gen_address = NULL;
2814 const char *gen_digits = NULL;
2815 const char *gen_dig_type = NULL;
2816 const char *gen_dig_scheme = NULL;
2817 const char *gen_name = NULL;
2818 const char *jip_digits = NULL;
2819 const char *lspi_ident = NULL;
2820 const char *rlt_flag = NULL;
2821 const char *call_ref_id = NULL;
2822 const char *call_ref_pc = NULL;
2823 const char *send_far = NULL;
2824 const char *tmr = NULL;
2831 c = strchr(dest,
'/');
2838 ast_log(LOG_WARNING,
"Number '%s' is shorter than stripmsd (%d)\n", c, p->
stripmsd);
2848 ss7_grab(p, p->ss7);
2856 called_nai_strip = 0;
2858 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
2859 called_nai_strip = ss7_parse_prefix(p, c + p->
stripmsd, &ss7_called_nai);
2861 isup_set_called(p->
ss7call, c + p->
stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
2863 calling_nai_strip = 0;
2865 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
2866 calling_nai_strip = ss7_parse_prefix(p, l, &ss7_calling_nai);
2869 isup_set_calling(p->
ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
2870 p->
use_callingpres ? cid_pres2ss7pres(ast_channel_connected(ast)->
id.number.presentation)
2871 : (l ? SS7_PRESENTATION_ALLOWED
2872 : (ast_channel_connected(ast)->
id.number.presentation == AST_PRES_UNAVAILABLE
2873 ? SS7_PRESENTATION_ADDR_NOT_AVAILABLE : SS7_PRESENTATION_RESTRICTED)),
2874 p->
use_callingpres ? cid_pres2ss7screen(ast_channel_connected(ast)->
id.number.presentation) : SS7_SCREENING_USER_PROVIDED);
2876 isup_set_oli(p->
ss7call, ast_channel_connected(ast)->ani2);
2881 isup_set_charge(p->
ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
2885 isup_set_gen_address(p->
ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type);
2891 isup_set_gen_digits(p->
ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
2895 isup_set_generic_name(p->
ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
2899 isup_set_jip_digits(p->
ss7call, jip_digits);
2903 isup_set_lspi(p->
ss7call, lspi_ident, 0x18, 0x7, 0x00);
2906 if ((rlt_flag) && ((strncmp(
"NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
2907 isup_set_lspi(p->
ss7call, rlt_flag, 0x18, 0x7, 0x00);
2912 if (call_ref_id && call_ref_pc) {
2913 isup_set_callref(p->
ss7call, atoi(call_ref_id),
2914 call_ref_pc ? atoi(call_ref_pc) : 0);
2918 if (send_far && strncmp(
"NO", send_far, strlen(send_far)) != 0) {
2919 isup_far(p->ss7->ss7, p->
ss7call);
2924 isup_set_tmr(p->
ss7call, atoi(tmr));
2926 if (!strcasecmp(tmr,
"SPEECH")) {
2927 isup_set_tmr(p->
ss7call, SS7_TMR_SPEECH);
2928 }
else if (!strcasecmp(tmr,
"SPARE")) {
2929 isup_set_tmr(p->
ss7call, SS7_TMR_SPARE);
2930 }
else if (!strcasecmp(tmr,
"3K1_AUDIO")) {
2931 isup_set_tmr(p->
ss7call, SS7_TMR_3K1_AUDIO);
2932 }
else if (!strcasecmp(tmr,
"64K_UNRESTRICTED")) {
2933 isup_set_tmr(p->
ss7call, SS7_TMR_64K_UNRESTRICTED);
2935 isup_set_tmr(p->
ss7call, SS7_TMR_N64K_OR_SPARE);
2945 if (!ast_strlen_zero(ss7_cug_indicator_str)) {
2946 if (!strcasecmp(ss7_cug_indicator_str,
"OUTGOING_ALLOWED")) {
2947 ss7_cug_indicator = ISUP_CUG_OUTGOING_ALLOWED;
2948 }
else if (!strcasecmp(ss7_cug_indicator_str,
"OUTGOING_NOT_ALLOWED")) {
2949 ss7_cug_indicator = ISUP_CUG_OUTGOING_NOT_ALLOWED;
2951 ss7_cug_indicator = ISUP_CUG_NON;
2954 if (ss7_cug_indicator != ISUP_CUG_NON) {
2957 if (ss7_cug_interlock_code && ss7_cug_interlock_ni && strlen(ss7_cug_interlock_ni) == 4) {
2958 isup_set_cug(p->
ss7call, ss7_cug_indicator, ss7_cug_interlock_ni, atoi(ss7_cug_interlock_code));
2963 ss7_redirecting_update(p, ast);
2965 isup_set_echocontrol(p->
ss7call, (p->ss7->
flags & LINKSET_FLAG_DEFAULTECHOCONTROL) ? 1 : 0);
2967 if (ss7_interworking_indicator) {
2968 isup_set_interworking_indicator(p->
ss7call,
ast_true(ss7_interworking_indicator));
2972 if (ss7_forward_indicator_pmbits) {
2973 isup_set_forward_indicator_pmbits(p->
ss7call, atoi(ss7_forward_indicator_pmbits));
2977 p->do_hangup = SS7_HANGUP_SEND_REL;
2978 isup_iam(p->ss7->ss7, p->
ss7call);
2979 sig_ss7_set_dialing(p, 1);
2997 if (!ast_channel_tech_pvt(ast)) {
2998 ast_log(LOG_WARNING,
"Asked to hangup channel not connected\n");
3003 sig_ss7_set_dialing(p, 0);
3004 sig_ss7_set_outgoing(p, 0);
3009 ss7_grab(p, p->ss7);
3012 switch (p->do_hangup) {
3013 case SS7_HANGUP_SEND_REL:
3016 int icause = ast_channel_hangupcause(ast) ? ast_channel_hangupcause(ast) : -1;
3020 icause = atoi(cause);
3027 isup_rel(p->ss7->ss7, p->
ss7call, icause);
3028 p->do_hangup = SS7_HANGUP_DO_NOTHING;
3031 case SS7_HANGUP_SEND_RSC:
3033 p->do_hangup = SS7_HANGUP_DO_NOTHING;
3035 case SS7_HANGUP_SEND_RLC:
3036 isup_rlc(p->ss7->ss7, p->
ss7call);
3037 p->do_hangup = SS7_HANGUP_DO_NOTHING;
3040 case SS7_HANGUP_FREE_CALL:
3041 p->do_hangup = SS7_HANGUP_DO_NOTHING;
3042 isup_free_call(p->ss7->ss7, p->
ss7call);
3045 case SS7_HANGUP_REEVENT_IAM:
3046 isup_event_iam(p->ss7->ss7, p->
ss7call, p->
dpc);
3047 p->do_hangup = SS7_HANGUP_SEND_REL;
3049 case SS7_HANGUP_DO_NOTHING:
3073 ss7_grab(p, p->ss7);
3076 isup_acm(p->ss7->ss7, p->
ss7call);
3081 res = isup_anm(p->ss7->ss7, p->
ss7call);
3082 sig_ss7_open_media(p);
3097 if (pchan->owner == oldchan) {
3098 pchan->owner = newchan;
3115 int sig_ss7_indicate(
struct sig_ss7_chan *p,
struct ast_channel *chan,
int condition,
const void *data,
size_t datalen)
3119 switch (condition) {
3122 ast_channel_hangupcause_set(chan, AST_CAUSE_USER_BUSY);
3127 res = sig_ss7_play_tone(p, SIG_SS7_TONE_BUSY);
3130 ss7_grab(p, p->ss7);
3132 if ((isup_far(p->ss7->ss7, p->
ss7call)) != -1) {
3137 isup_acm(p->ss7->ss7, p->
ss7call);
3142 isup_cpg(p->ss7->ss7, p->
ss7call, CPG_EVENT_ALERTING);
3149 res = sig_ss7_play_tone(p, SIG_SS7_TONE_RINGTONE);
3156 ast_debug(1,
"Received AST_CONTROL_PROCEEDING on %s\n",ast_channel_name(chan));
3157 ss7_grab(p, p->ss7);
3160 if ((isup_far(p->ss7->ss7, p->
ss7call)) != -1) {
3167 isup_acm(p->ss7->ss7, p->
ss7call);
3174 ast_debug(1,
"Received AST_CONTROL_PROGRESS on %s\n",ast_channel_name(chan));
3175 ss7_grab(p, p->ss7);
3178 isup_cpg(p->ss7->ss7, p->
ss7call, CPG_EVENT_INBANDINFO);
3181 if (!p->echocontrol_ind || !(p->ss7->
flags & LINKSET_FLAG_USEECHOCONTROL)) {
3182 sig_ss7_set_echocanceller(p, 1);
3191 ast_channel_hangupcause_set(chan, AST_CAUSE_INVALID_NUMBER_FORMAT);
3201 ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
3206 res = sig_ss7_play_tone(p, SIG_SS7_TONE_CONGESTION);
3218 ss7_connected_line_update(p, ast_channel_connected(chan));
3222 ss7_redirecting_update(p, chan);
3226 res = sig_ss7_play_tone(p, -1);
3246 int transfercapability)
3251 if (p->ss7->
type == SS7_ITU) {
3257 sig_ss7_set_outgoing(p, 1);
3259 p->exten, assignedids, requestor);
3261 sig_ss7_set_outgoing(p, 0);
3264 ast_mutex_lock(&p->ss7->
lock);
3266 isup_free_call(p->ss7->ss7, p->
ss7call);
3267 ast_mutex_unlock(&p->ss7->
lock);
3283 #define SIG_SS7_SC_HEADER "%-4s %4s %-4s %-3s %-3s %-10s %-4s %s\n"
3284 #define SIG_SS7_SC_LINE "%4d %4d %-4s %-3s %-3s %-10s %-4s %s"
3285 void sig_ss7_cli_show_channels_header(
int fd)
3287 ast_cli(fd, SIG_SS7_SC_HEADER,
"link",
"",
"Chan",
"Lcl",
"Rem",
"Call",
"SS7",
"Channel");
3288 ast_cli(fd, SIG_SS7_SC_HEADER,
"set",
"Chan",
"Idle",
"Blk",
"Blk",
"Level",
"Call",
"Name");
3291 void sig_ss7_cli_show_channels(
int fd,
struct sig_ss7_linkset *linkset)
3297 ast_mutex_lock(&linkset->
lock);
3298 for (idx = 0; idx < linkset->numchans; ++idx) {
3299 if (!linkset->
pvts[idx]) {
3302 pvt = linkset->
pvts[idx];
3303 sig_ss7_lock_private(pvt);
3304 sig_ss7_lock_owner(linkset, idx);
3306 snprintf(line,
sizeof(line), SIG_SS7_SC_LINE,
3309 sig_ss7_is_chan_available(pvt) ?
"Yes" :
"No",
3314 pvt->owner ? ast_channel_name(pvt->owner) :
"");
3317 ast_channel_unlock(pvt->owner);
3319 sig_ss7_unlock_private(pvt);
3321 ast_mutex_unlock(&linkset->
lock);
3322 ast_cli(fd,
"%s\n", line);
3323 ast_mutex_lock(&linkset->
lock);
3325 ast_mutex_unlock(&linkset->
lock);
3363 memset(ss7, 0,
sizeof(*ss7));
3365 ast_mutex_init(&ss7->
lock);
3367 ss7->
master = AST_PTHREADT_NULL;
3368 for (idx = 0; idx < ARRAY_LEN(ss7->fds); ++idx) {
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
Main Channel structure associated with a channel.
char * str
Subscriber phone number (Malloced)
General Asterisk channel transcoding definitions.
enum sig_ss7_call_level call_level
Asterisk main include file. File version handling, generic pbx functions.
char chan_name[AST_CHANNEL_NAME]
unsigned int outgoing
TRUE if this channel is being used for an outgoing call.
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
struct ast_party_id id
Connected party ID.
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Indicate that the redirecting id has changed.
unsigned char cug_indicator
Indication of the call being a CUG call and its permissions.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
char cug_interlock_ni[5]
Network Identify Code as per Q.763 3.15.a.
unsigned short cug_interlock_code
Binari Code to uniquely identify a CUG inside the network.
unsigned int loopedback
TRUE if this channel is in loopback.
void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
Copy the source party id information to the destination party id.
Structure to pass both assignedid values to channel drivers.
struct sig_ss7_callback sig_ss7_callbacks
Interface header for SS7 signaling module.
ast_channel_state
ast_channel states
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
unsigned int inalarm
TRUE if channel is associated with a link that is down.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
unsigned short transfercapability
#define ast_strdup(str)
A wrapper for strdup()
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
int code
enum AST_REDIRECTING_REASON value for redirection
char cid_subaddr[AST_MAX_EXTENSION]
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_frame_subclass subclass
struct ast_party_id orig
Who originally redirected the call (Sent to the party the call is redirected toward) ...
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls...
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked.
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
unsigned int use_callerid
TRUE if caller ID is used on this channel.
unsigned int progress
TRUE if the call has seen inband-information progress through the network.
void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Queue a connected line update frame on a channel.
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
struct ast_party_redirecting_reason orig_reason
Reason for the redirection by the original party.
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_callid_threadstorage_auto_clean(ast_callid callid, int callid_created)
Use in conjunction with ast_callid_threadstorage_auto. Cleans up the references and if the callid was...
#define AST_MAX_EXTENSION
Caller Party information.
#define ast_debug(level,...)
Log a DEBUG message.
unsigned int inservice
TRUE if channel is in service.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
char subscriberprefix[20]
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
struct sig_ss7_chan * pvts[SIG_SS7_MAX_CHANNELS]
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
#define SIG_SS7_NUM_DCHANS
Connected Line/Party information.
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Redirecting Line information. RDNIS (Redirecting Directory Number Information Service) Where a call d...
unsigned int rlt
XXX BOOLEAN Purpose???
#define ast_calloc(num, len)
A wrapper for calloc()
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
#define SIG_SS7_DEBUG_DEFAULT
struct ast_party_redirecting_reason reason
Reason for the redirection.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int ast_callid_threadstorage_auto(ast_callid *callid)
Checks thread storage for a callid and stores a reference if it exists. If not, then a new one will b...
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
int count
Number of times the call was redirected.
Standard Command Line Interface.
struct ast_party_id to
Call is redirecting to a new party (Sent to the caller)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
void ast_party_redirecting_init(struct ast_party_redirecting *init)
Initialize the given redirecting structure.
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
char * ast_transfercapability2str(int transfercapability) attribute_const
Gives the string form of a given transfer capability.
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Data structure associated with a single frame of data.
Internal Asterisk hangup causes.
char internationalprefix[10]
unsigned int called_complete
TRUE if the channel has completed collecting digits.
struct isup_call * ss7call
Opaque libss7 call control structure.
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
void ast_party_caller_init(struct ast_party_caller *init)
Initialize the given caller structure.
unsigned char valid
TRUE if the number information is valid/present.
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash on the given channel. ...
char exten[AST_MAX_EXTENSION]
struct ast_party_number number
Subscriber phone number.