00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "asterisk.h"
00035
00036 #if defined(HAVE_SS7)
00037
00038 #include <signal.h>
00039
00040 #include "asterisk/pbx.h"
00041 #include "asterisk/causes.h"
00042 #include "asterisk/musiconhold.h"
00043 #include "asterisk/cli.h"
00044 #include "asterisk/transcap.h"
00045
00046 #include "sig_ss7.h"
00047 #if defined(LIBSS7_ABI_COMPATIBILITY)
00048 #error "Your installed libss7 is not compatible"
00049 #endif
00050
00051
00052
00053 static const char *sig_ss7_call_level2str(enum sig_ss7_call_level level)
00054 {
00055 switch (level) {
00056 case SIG_SS7_CALL_LEVEL_IDLE:
00057 return "Idle";
00058 case SIG_SS7_CALL_LEVEL_ALLOCATED:
00059 return "Allocated";
00060 case SIG_SS7_CALL_LEVEL_CONTINUITY:
00061 return "Continuity";
00062 case SIG_SS7_CALL_LEVEL_SETUP:
00063 return "Setup";
00064 case SIG_SS7_CALL_LEVEL_PROCEEDING:
00065 return "Proceeding";
00066 case SIG_SS7_CALL_LEVEL_ALERTING:
00067 return "Alerting";
00068 case SIG_SS7_CALL_LEVEL_CONNECT:
00069 return "Connect";
00070 case SIG_SS7_CALL_LEVEL_GLARE:
00071 return "Glare";
00072 }
00073 return "Unknown";
00074 }
00075
00076 static void sig_ss7_unlock_private(struct sig_ss7_chan *p)
00077 {
00078 if (p->calls->unlock_private) {
00079 p->calls->unlock_private(p->chan_pvt);
00080 }
00081 }
00082
00083 static void sig_ss7_lock_private(struct sig_ss7_chan *p)
00084 {
00085 if (p->calls->lock_private) {
00086 p->calls->lock_private(p->chan_pvt);
00087 }
00088 }
00089
00090 void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
00091 {
00092 p->inalarm = in_alarm;
00093 if (p->calls->set_alarm) {
00094 p->calls->set_alarm(p->chan_pvt, in_alarm);
00095 }
00096 }
00097
00098 static void sig_ss7_set_dialing(struct sig_ss7_chan *p, int is_dialing)
00099 {
00100 if (p->calls->set_dialing) {
00101 p->calls->set_dialing(p->chan_pvt, is_dialing);
00102 }
00103 }
00104
00105 static void sig_ss7_set_digital(struct sig_ss7_chan *p, int is_digital)
00106 {
00107 if (p->calls->set_digital) {
00108 p->calls->set_digital(p->chan_pvt, is_digital);
00109 }
00110 }
00111
00112 static void sig_ss7_set_outgoing(struct sig_ss7_chan *p, int is_outgoing)
00113 {
00114 p->outgoing = is_outgoing;
00115 if (p->calls->set_outgoing) {
00116 p->calls->set_outgoing(p->chan_pvt, is_outgoing);
00117 }
00118 }
00119
00120 static void sig_ss7_set_inservice(struct sig_ss7_chan *p, int is_inservice)
00121 {
00122 if (p->calls->set_inservice) {
00123 p->calls->set_inservice(p->chan_pvt, is_inservice);
00124 }
00125 }
00126
00127 static void sig_ss7_set_locallyblocked(struct sig_ss7_chan *p, int is_blocked)
00128 {
00129 p->locallyblocked = is_blocked;
00130 if (p->calls->set_locallyblocked) {
00131 p->calls->set_locallyblocked(p->chan_pvt, is_blocked);
00132 }
00133 }
00134
00135 static void sig_ss7_set_remotelyblocked(struct sig_ss7_chan *p, int is_blocked)
00136 {
00137 p->remotelyblocked = is_blocked;
00138 if (p->calls->set_remotelyblocked) {
00139 p->calls->set_remotelyblocked(p->chan_pvt, is_blocked);
00140 }
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 static void sig_ss7_open_media(struct sig_ss7_chan *p)
00153 {
00154 if (p->calls->open_media) {
00155 p->calls->open_media(p->chan_pvt);
00156 }
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 static void sig_ss7_set_caller_id(struct sig_ss7_chan *p)
00169 {
00170 struct ast_party_caller caller;
00171
00172 if (p->calls->set_callerid) {
00173 ast_party_caller_init(&caller);
00174
00175 caller.id.name.str = p->cid_name;
00176 caller.id.name.presentation = p->callingpres;
00177 caller.id.name.valid = 1;
00178
00179 caller.id.number.str = p->cid_num;
00180 caller.id.number.plan = p->cid_ton;
00181 caller.id.number.presentation = p->callingpres;
00182 caller.id.number.valid = 1;
00183
00184 if (!ast_strlen_zero(p->cid_subaddr)) {
00185 caller.id.subaddress.valid = 1;
00186
00187
00188 caller.id.subaddress.str = p->cid_subaddr;
00189 }
00190
00191 caller.ani.number.str = p->cid_ani;
00192
00193
00194 caller.ani.number.valid = 1;
00195
00196 caller.ani2 = p->cid_ani2;
00197 p->calls->set_callerid(p->chan_pvt, &caller);
00198 }
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 static void sig_ss7_set_dnid(struct sig_ss7_chan *p, const char *dnid)
00212 {
00213 if (p->calls->set_dnid) {
00214 p->calls->set_dnid(p->chan_pvt, dnid);
00215 }
00216 }
00217
00218 static int sig_ss7_play_tone(struct sig_ss7_chan *p, enum sig_ss7_tone tone)
00219 {
00220 int res;
00221
00222 if (p->calls->play_tone) {
00223 res = p->calls->play_tone(p->chan_pvt, tone);
00224 } else {
00225 res = -1;
00226 }
00227 return res;
00228 }
00229
00230 static int sig_ss7_set_echocanceller(struct sig_ss7_chan *p, int enable)
00231 {
00232 if (p->calls->set_echocanceller) {
00233 return p->calls->set_echocanceller(p->chan_pvt, enable);
00234 }
00235 return -1;
00236 }
00237
00238 static void sig_ss7_loopback(struct sig_ss7_chan *p, int enable)
00239 {
00240 if (p->loopedback != enable) {
00241 p->loopedback = enable;
00242 if (p->calls->set_loopback) {
00243 p->calls->set_loopback(p->chan_pvt, enable);
00244 }
00245 }
00246 }
00247
00248 static struct ast_channel *sig_ss7_new_ast_channel(struct sig_ss7_chan *p, int state, int ulaw, int transfercapability, char *exten, const struct ast_channel *requestor)
00249 {
00250 struct ast_channel *ast;
00251
00252 if (p->calls->new_ast_channel) {
00253 ast = p->calls->new_ast_channel(p->chan_pvt, state, ulaw, exten, requestor);
00254 } else {
00255 return NULL;
00256 }
00257 if (!ast) {
00258 return NULL;
00259 }
00260
00261 if (!p->owner) {
00262 p->owner = ast;
00263 }
00264 p->alreadyhungup = 0;
00265 ast->transfercapability = transfercapability;
00266 pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY",
00267 ast_transfercapability2str(transfercapability));
00268 if (transfercapability & AST_TRANS_CAP_DIGITAL) {
00269 sig_ss7_set_digital(p, 1);
00270 }
00271
00272 return ast;
00273 }
00274
00275 static void sig_ss7_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
00276 {
00277 if (linkset->calls->handle_link_exception) {
00278 linkset->calls->handle_link_exception(linkset, which);
00279 }
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 static int sig_ss7_is_chan_available(struct sig_ss7_chan *pvt)
00291 {
00292 if (!pvt->inalarm && !pvt->owner && !pvt->ss7call
00293 && pvt->call_level == SIG_SS7_CALL_LEVEL_IDLE
00294 && !pvt->locallyblocked && !pvt->remotelyblocked) {
00295 return 1;
00296 }
00297 return 0;
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 static void sig_ss7_lock_owner(struct sig_ss7_linkset *ss7, int chanpos)
00314 {
00315 for (;;) {
00316 if (!ss7->pvts[chanpos]->owner) {
00317
00318 break;
00319 }
00320 if (!ast_channel_trylock(ss7->pvts[chanpos]->owner)) {
00321
00322 break;
00323 }
00324
00325
00326 sig_ss7_unlock_private(ss7->pvts[chanpos]);
00327 DEADLOCK_AVOIDANCE(&ss7->lock);
00328 sig_ss7_lock_private(ss7->pvts[chanpos]);
00329 }
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 static void sig_ss7_queue_frame(struct sig_ss7_linkset *ss7, int chanpos, struct ast_frame *frame)
00347 {
00348 sig_ss7_lock_owner(ss7, chanpos);
00349 if (ss7->pvts[chanpos]->owner) {
00350 ast_queue_frame(ss7->pvts[chanpos]->owner, frame);
00351 ast_channel_unlock(ss7->pvts[chanpos]->owner);
00352 }
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 static void sig_ss7_queue_control(struct sig_ss7_linkset *ss7, int chanpos, int subclass)
00370 {
00371 struct ast_frame f = {AST_FRAME_CONTROL, };
00372 struct sig_ss7_chan *p = ss7->pvts[chanpos];
00373
00374 if (p->calls->queue_control) {
00375 p->calls->queue_control(p->chan_pvt, subclass);
00376 }
00377
00378 f.subclass.integer = subclass;
00379 sig_ss7_queue_frame(ss7, chanpos, &f);
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 static int ss7_find_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
00394 {
00395 int i;
00396 int winner = -1;
00397 for (i = 0; i < linkset->numchans; i++) {
00398 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
00399 winner = i;
00400 break;
00401 }
00402 }
00403 return winner;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 static int ss7_find_cic_gripe(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc, const char *msg_name)
00419 {
00420 int chanpos;
00421
00422 chanpos = ss7_find_cic(linkset, cic, dpc);
00423 if (chanpos < 0) {
00424 ast_log(LOG_WARNING, "Linkset %d: SS7 %s requested unconfigured CIC/DPC %d/%d.\n",
00425 linkset->span, msg_name, cic, dpc);
00426 return -1;
00427 }
00428 return chanpos;
00429 }
00430
00431 static void ss7_handle_cqm(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
00432 {
00433 unsigned char status[32];
00434 struct sig_ss7_chan *p = NULL;
00435 int i, offset;
00436
00437 for (i = 0; i < linkset->numchans; i++) {
00438 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
00439 p = linkset->pvts[i];
00440 offset = p->cic - startcic;
00441 status[offset] = 0;
00442 if (p->locallyblocked)
00443 status[offset] |= (1 << 0) | (1 << 4);
00444 if (p->remotelyblocked)
00445 status[offset] |= (1 << 1) | (1 << 5);
00446 if (p->ss7call) {
00447 if (p->outgoing)
00448 status[offset] |= (1 << 3);
00449 else
00450 status[offset] |= (1 << 2);
00451 } else
00452 status[offset] |= 0x3 << 2;
00453 }
00454 }
00455
00456 if (p)
00457 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
00458 else
00459 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
00460
00461 }
00462
00463 static inline void ss7_hangup_cics(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
00464 {
00465 int i;
00466
00467 for (i = 0; i < linkset->numchans; i++) {
00468 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
00469 sig_ss7_lock_private(linkset->pvts[i]);
00470 sig_ss7_lock_owner(linkset, i);
00471 if (linkset->pvts[i]->owner) {
00472 ast_softhangup_nolock(linkset->pvts[i]->owner, AST_SOFTHANGUP_DEV);
00473 ast_channel_unlock(linkset->pvts[i]->owner);
00474 }
00475 sig_ss7_unlock_private(linkset->pvts[i]);
00476 }
00477 }
00478 }
00479
00480 static inline void ss7_block_cics(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
00481 {
00482 int i;
00483
00484
00485 for (i = 0; i < linkset->numchans; i++) {
00486 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
00487 if (state) {
00488 if (state[i])
00489 sig_ss7_set_remotelyblocked(linkset->pvts[i], block);
00490 } else
00491 sig_ss7_set_remotelyblocked(linkset->pvts[i], block);
00492 }
00493 }
00494 }
00495
00496 static void ss7_inservice(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
00497 {
00498 int i;
00499
00500 for (i = 0; i < linkset->numchans; i++) {
00501 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
00502 sig_ss7_set_inservice(linkset->pvts[i], 1);
00503 }
00504 }
00505
00506 static void ss7_reset_linkset(struct sig_ss7_linkset *linkset)
00507 {
00508 int i, startcic = -1, endcic, dpc;
00509
00510 if (linkset->numchans <= 0)
00511 return;
00512
00513 startcic = linkset->pvts[0]->cic;
00514
00515 dpc = linkset->pvts[0]->dpc;
00516
00517 for (i = 0; i < linkset->numchans; i++) {
00518 if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
00519 continue;
00520 } else {
00521 endcic = linkset->pvts[i]->cic;
00522 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
00523 isup_grs(linkset->ss7, startcic, endcic, dpc);
00524
00525
00526 if (linkset->pvts[i+1]) {
00527 startcic = linkset->pvts[i+1]->cic;
00528 dpc = linkset->pvts[i+1]->dpc;
00529 }
00530 }
00531 }
00532 }
00533
00534
00535 static void ss7_start_call(struct sig_ss7_chan *p, struct sig_ss7_linkset *linkset)
00536 {
00537 struct ss7 *ss7 = linkset->ss7;
00538 int law;
00539 struct ast_channel *c;
00540 char tmp[256];
00541
00542 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
00543 p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING;
00544 isup_acm(ss7, p->ss7call);
00545 } else {
00546 p->call_level = SIG_SS7_CALL_LEVEL_SETUP;
00547 }
00548
00549
00550 if (linkset->type == SS7_ITU) {
00551 law = SIG_SS7_ALAW;
00552 } else {
00553 law = SIG_SS7_ULAW;
00554 }
00555
00556
00557
00558
00559
00560
00561 ast_mutex_unlock(&linkset->lock);
00562 sig_ss7_unlock_private(p);
00563 c = sig_ss7_new_ast_channel(p, AST_STATE_RING, law, 0, p->exten, NULL);
00564 if (!c) {
00565 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
00566 ast_mutex_lock(&linkset->lock);
00567 sig_ss7_lock_private(p);
00568 isup_rel(linkset->ss7, p->ss7call, AST_CAUSE_SWITCH_CONGESTION);
00569 p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
00570 p->alreadyhungup = 1;
00571 return;
00572 }
00573
00574
00575 ast_channel_lock(c);
00576 sig_ss7_lock_private(p);
00577
00578 sig_ss7_set_echocanceller(p, 1);
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 if (!ast_strlen_zero(p->charge_number)) {
00592 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
00593
00594 p->charge_number[0] = 0;
00595 }
00596 if (!ast_strlen_zero(p->gen_add_number)) {
00597 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
00598
00599 p->gen_add_number[0] = 0;
00600 }
00601 if (!ast_strlen_zero(p->jip_number)) {
00602 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
00603
00604 p->jip_number[0] = 0;
00605 }
00606 if (!ast_strlen_zero(p->gen_dig_number)) {
00607 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
00608
00609 p->gen_dig_number[0] = 0;
00610 }
00611 if (!ast_strlen_zero(p->orig_called_num)) {
00612 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
00613
00614 p->orig_called_num[0] = 0;
00615 }
00616
00617 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
00618 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
00619
00620 p->gen_dig_type = 0;
00621
00622 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
00623 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
00624
00625 p->gen_dig_scheme = 0;
00626
00627 if (!ast_strlen_zero(p->lspi_ident)) {
00628 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
00629
00630 p->lspi_ident[0] = 0;
00631 }
00632
00633 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
00634 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
00635
00636 p->call_ref_ident = 0;
00637
00638 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
00639 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
00640
00641 p->call_ref_pc = 0;
00642
00643 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
00644 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
00645
00646 p->calling_party_cat = 0;
00647
00648 if (!ast_strlen_zero(p->redirecting_num)) {
00649 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
00650
00651 p->redirecting_num[0] = 0;
00652 }
00653 if (!ast_strlen_zero(p->generic_name)) {
00654 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
00655
00656 p->generic_name[0] = 0;
00657 }
00658
00659 sig_ss7_unlock_private(p);
00660 ast_channel_unlock(c);
00661
00662 if (ast_pbx_start(c)) {
00663 ast_log(LOG_WARNING, "Unable to start PBX on %s (CIC %d)\n", c->name, p->cic);
00664 ast_hangup(c);
00665 } else {
00666 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
00667 }
00668
00669
00670 ast_mutex_lock(&linkset->lock);
00671 sig_ss7_lock_private(p);
00672 }
00673
00674 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct sig_ss7_linkset *ss7, const char *number, const unsigned nai)
00675 {
00676 if (ast_strlen_zero(number)) {
00677 if (size) {
00678 *buf = '\0';
00679 }
00680 return;
00681 }
00682 switch (nai) {
00683 case SS7_NAI_INTERNATIONAL:
00684 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
00685 break;
00686 case SS7_NAI_NATIONAL:
00687 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
00688 break;
00689 case SS7_NAI_SUBSCRIBER:
00690 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
00691 break;
00692 case SS7_NAI_UNKNOWN:
00693 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
00694 break;
00695 default:
00696 snprintf(buf, size, "%s", number);
00697 break;
00698 }
00699 }
00700
00701 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
00702 {
00703 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
00704 }
00705
00706
00707 void *ss7_linkset(void *data)
00708 {
00709 int res, i;
00710 struct timeval *next = NULL, tv;
00711 struct sig_ss7_linkset *linkset = (struct sig_ss7_linkset *) data;
00712 struct ss7 *ss7 = linkset->ss7;
00713 ss7_event *e = NULL;
00714 struct sig_ss7_chan *p;
00715 int chanpos;
00716 struct pollfd pollers[SIG_SS7_NUM_DCHANS];
00717 int nextms = 0;
00718
00719 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
00720
00721 ss7_set_debug(ss7, SIG_SS7_DEBUG_DEFAULT);
00722 ast_mutex_lock(&linkset->lock);
00723 ss7_start(ss7);
00724 ast_mutex_unlock(&linkset->lock);
00725
00726 for (;;) {
00727 ast_mutex_lock(&linkset->lock);
00728 if ((next = ss7_schedule_next(ss7))) {
00729 tv = ast_tvnow();
00730 tv.tv_sec = next->tv_sec - tv.tv_sec;
00731 tv.tv_usec = next->tv_usec - tv.tv_usec;
00732 if (tv.tv_usec < 0) {
00733 tv.tv_usec += 1000000;
00734 tv.tv_sec -= 1;
00735 }
00736 if (tv.tv_sec < 0) {
00737 tv.tv_sec = 0;
00738 tv.tv_usec = 0;
00739 }
00740 nextms = tv.tv_sec * 1000;
00741 nextms += tv.tv_usec / 1000;
00742 }
00743
00744 for (i = 0; i < linkset->numsigchans; i++) {
00745 pollers[i].fd = linkset->fds[i];
00746 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
00747 pollers[i].revents = 0;
00748 }
00749 ast_mutex_unlock(&linkset->lock);
00750
00751 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
00752 pthread_testcancel();
00753 res = poll(pollers, linkset->numsigchans, nextms);
00754 pthread_testcancel();
00755 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
00756
00757 if ((res < 0) && (errno != EINTR)) {
00758 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
00759 } else if (!res) {
00760 ast_mutex_lock(&linkset->lock);
00761 ss7_schedule_run(ss7);
00762 ast_mutex_unlock(&linkset->lock);
00763 continue;
00764 }
00765
00766 ast_mutex_lock(&linkset->lock);
00767 for (i = 0; i < linkset->numsigchans; i++) {
00768 if (pollers[i].revents & POLLPRI) {
00769 sig_ss7_handle_link_exception(linkset, i);
00770 }
00771 if (pollers[i].revents & POLLIN) {
00772 res = ss7_read(ss7, pollers[i].fd);
00773 }
00774 if (pollers[i].revents & POLLOUT) {
00775 res = ss7_write(ss7, pollers[i].fd);
00776 if (res < 0) {
00777 ast_debug(1, "Error in write %s\n", strerror(errno));
00778 }
00779 }
00780 }
00781
00782 while ((e = ss7_check_event(ss7))) {
00783 if (linkset->debug) {
00784 ast_verbose("Linkset %d: Processing event: %s\n",
00785 linkset->span, ss7_event2str(e->e));
00786 }
00787
00788 switch (e->e) {
00789 case SS7_EVENT_UP:
00790 if (linkset->state != LINKSET_STATE_UP) {
00791 ast_verbose("--- SS7 Up ---\n");
00792 ss7_reset_linkset(linkset);
00793 }
00794 linkset->state = LINKSET_STATE_UP;
00795 break;
00796 case SS7_EVENT_DOWN:
00797 ast_verbose("--- SS7 Down ---\n");
00798 linkset->state = LINKSET_STATE_DOWN;
00799 for (i = 0; i < linkset->numchans; i++) {
00800 p = linkset->pvts[i];
00801 if (p) {
00802 sig_ss7_set_alarm(p, 1);
00803 }
00804 }
00805 break;
00806 case MTP2_LINK_UP:
00807 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
00808 break;
00809 case MTP2_LINK_DOWN:
00810 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
00811 break;
00812 case ISUP_EVENT_CPG:
00813 chanpos = ss7_find_cic_gripe(linkset, e->cpg.cic, e->cpg.opc, "CPG");
00814 if (chanpos < 0) {
00815 break;
00816 }
00817 p = linkset->pvts[chanpos];
00818 sig_ss7_lock_private(p);
00819 switch (e->cpg.event) {
00820 case CPG_EVENT_ALERTING:
00821 if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING) {
00822 p->call_level = SIG_SS7_CALL_LEVEL_ALERTING;
00823 }
00824 sig_ss7_lock_owner(linkset, chanpos);
00825 if (p->owner) {
00826 ast_setstate(p->owner, AST_STATE_RINGING);
00827 ast_channel_unlock(p->owner);
00828 }
00829 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING);
00830 break;
00831 case CPG_EVENT_PROGRESS:
00832 case CPG_EVENT_INBANDINFO:
00833 {
00834 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
00835 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROGRESS);
00836 p->progress = 1;
00837 sig_ss7_set_dialing(p, 0);
00838 sig_ss7_open_media(p);
00839 }
00840 break;
00841 default:
00842 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
00843 break;
00844 }
00845
00846 sig_ss7_unlock_private(p);
00847 break;
00848 case ISUP_EVENT_RSC:
00849 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
00850 chanpos = ss7_find_cic_gripe(linkset, e->rsc.cic, e->rsc.opc, "RSC");
00851 if (chanpos < 0) {
00852 break;
00853 }
00854 p = linkset->pvts[chanpos];
00855 sig_ss7_lock_private(p);
00856 sig_ss7_set_inservice(p, 1);
00857 sig_ss7_set_remotelyblocked(p, 0);
00858 isup_set_call_dpc(e->rsc.call, p->dpc);
00859 sig_ss7_lock_owner(linkset, chanpos);
00860 p->ss7call = NULL;
00861 if (p->owner) {
00862 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
00863 ast_channel_unlock(p->owner);
00864 }
00865 sig_ss7_unlock_private(p);
00866 isup_rlc(ss7, e->rsc.call);
00867 break;
00868 case ISUP_EVENT_GRS:
00869 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
00870 chanpos = ss7_find_cic_gripe(linkset, e->grs.startcic, e->grs.opc, "GRS");
00871 if (chanpos < 0) {
00872 break;
00873 }
00874 p = linkset->pvts[chanpos];
00875 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
00876 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
00877 ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
00878 break;
00879 case ISUP_EVENT_CQM:
00880 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
00881 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
00882 break;
00883 case ISUP_EVENT_GRA:
00884 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
00885 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
00886 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
00887 break;
00888 case ISUP_EVENT_IAM:
00889 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);
00890 chanpos = ss7_find_cic_gripe(linkset, e->iam.cic, e->iam.opc, "IAM");
00891 if (chanpos < 0) {
00892 isup_rel(ss7, e->iam.call, -1);
00893 break;
00894 }
00895 p = linkset->pvts[chanpos];
00896 sig_ss7_lock_private(p);
00897 sig_ss7_lock_owner(linkset, chanpos);
00898 if (p->call_level != SIG_SS7_CALL_LEVEL_IDLE) {
00899
00900
00901
00902
00903
00904
00905
00906
00907 ast_debug(1,
00908 "Linkset %d: SS7 IAM glare on CIC/DPC %d/%d. Dropping both calls.\n",
00909 linkset->span, e->iam.cic, e->iam.opc);
00910 if (p->call_level == SIG_SS7_CALL_LEVEL_ALLOCATED) {
00911
00912
00913
00914 p->alreadyhungup = 1;
00915 isup_rel(ss7, e->iam.call, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
00916 }
00917 p->call_level = SIG_SS7_CALL_LEVEL_GLARE;
00918 if (p->owner) {
00919 p->owner->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
00920 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
00921 ast_channel_unlock(p->owner);
00922 }
00923 sig_ss7_unlock_private(p);
00924 break;
00925 }
00926
00927
00928
00929
00930 ast_assert(!p->owner);
00931
00932 if (!sig_ss7_is_chan_available(p)) {
00933
00934 isup_rel(ss7, e->iam.call, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
00935 sig_ss7_unlock_private(p);
00936 break;
00937 }
00938
00939
00940 p->call_level = SIG_SS7_CALL_LEVEL_ALLOCATED;
00941 p->ss7call = e->iam.call;
00942
00943 isup_set_call_dpc(p->ss7call, p->dpc);
00944
00945 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
00946 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
00947 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
00948 } else
00949 p->cid_num[0] = 0;
00950
00951
00952 if (!ast_strlen_zero(e->iam.called_party_num)) {
00953 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset,
00954 e->iam.called_party_num, e->iam.called_nai);
00955 } else {
00956 p->exten[0] = '\0';
00957 }
00958 sig_ss7_set_dnid(p, p->exten);
00959
00960 if (p->immediate) {
00961 p->exten[0] = 's';
00962 p->exten[1] = '\0';
00963 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
00964 char *st;
00965 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
00966 st = strchr(p->exten, '#');
00967 if (st) {
00968 *st = '\0';
00969 }
00970 } else {
00971 p->exten[0] = '\0';
00972 }
00973
00974 p->cid_ani[0] = '\0';
00975 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
00976 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
00977 else
00978 p->cid_name[0] = '\0';
00979
00980 p->cid_ani2 = e->iam.oli_ani2;
00981 p->cid_ton = 0;
00982 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
00983 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
00984 p->gen_add_type = e->iam.gen_add_type;
00985 p->gen_add_nai = e->iam.gen_add_nai;
00986 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
00987 p->gen_add_num_plan = e->iam.gen_add_num_plan;
00988 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
00989 p->gen_dig_type = e->iam.gen_dig_type;
00990 p->gen_dig_scheme = e->iam.gen_dig_scheme;
00991 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
00992 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
00993 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
00994 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
00995 p->calling_party_cat = e->iam.calling_party_cat;
00996
00997 sig_ss7_set_caller_id(p);
00998
00999 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01000 if (e->iam.cot_check_required) {
01001 p->call_level = SIG_SS7_CALL_LEVEL_CONTINUITY;
01002 sig_ss7_loopback(p, 1);
01003 } else {
01004 ss7_start_call(p, linkset);
01005 }
01006 } else {
01007 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
01008 p->alreadyhungup = 1;
01009 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
01010 }
01011 sig_ss7_unlock_private(p);
01012 break;
01013 case ISUP_EVENT_COT:
01014 chanpos = ss7_find_cic_gripe(linkset, e->cot.cic, e->cot.opc, "COT");
01015 if (chanpos < 0) {
01016 isup_rel(ss7, e->cot.call, -1);
01017 break;
01018 }
01019 p = linkset->pvts[chanpos];
01020
01021 sig_ss7_lock_private(p);
01022 if (p->loopedback) {
01023 sig_ss7_loopback(p, 0);
01024 ss7_start_call(p, linkset);
01025 }
01026 sig_ss7_unlock_private(p);
01027 break;
01028 case ISUP_EVENT_CCR:
01029 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
01030 chanpos = ss7_find_cic_gripe(linkset, e->ccr.cic, e->ccr.opc, "CCR");
01031 if (chanpos < 0) {
01032 break;
01033 }
01034
01035 p = linkset->pvts[chanpos];
01036
01037 sig_ss7_lock_private(p);
01038 sig_ss7_loopback(p, 1);
01039 sig_ss7_unlock_private(p);
01040
01041 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
01042 break;
01043 case ISUP_EVENT_CVT:
01044 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
01045 chanpos = ss7_find_cic_gripe(linkset, e->cvt.cic, e->cvt.opc, "CVT");
01046 if (chanpos < 0) {
01047 break;
01048 }
01049
01050 p = linkset->pvts[chanpos];
01051
01052 sig_ss7_lock_private(p);
01053 sig_ss7_loopback(p, 1);
01054 sig_ss7_unlock_private(p);
01055
01056 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
01057 break;
01058 case ISUP_EVENT_REL:
01059 chanpos = ss7_find_cic_gripe(linkset, e->rel.cic, e->rel.opc, "REL");
01060 if (chanpos < 0) {
01061
01062 isup_rlc(ss7, e->rel.call);
01063 break;
01064 }
01065 p = linkset->pvts[chanpos];
01066 sig_ss7_lock_private(p);
01067 sig_ss7_lock_owner(linkset, chanpos);
01068 if (p->owner) {
01069 p->owner->hangupcause = e->rel.cause;
01070 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
01071 ast_channel_unlock(p->owner);
01072 }
01073
01074
01075 sig_ss7_loopback(p, 0);
01076
01077 isup_rlc(ss7, e->rel.call);
01078 p->ss7call = NULL;
01079
01080 sig_ss7_unlock_private(p);
01081 break;
01082 case ISUP_EVENT_ACM:
01083 chanpos = ss7_find_cic_gripe(linkset, e->acm.cic, e->acm.opc, "ACM");
01084 if (chanpos < 0) {
01085 isup_rel(ss7, e->acm.call, -1);
01086 break;
01087 }
01088 {
01089 p = linkset->pvts[chanpos];
01090
01091 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
01092
01093 if (e->acm.call_ref_ident > 0) {
01094 p->rlt = 1;
01095 }
01096
01097 sig_ss7_lock_private(p);
01098 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROCEEDING);
01099 if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING) {
01100 p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING;
01101 }
01102 sig_ss7_set_dialing(p, 0);
01103
01104 if (e->acm.called_party_status_ind == 1) {
01105 if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING) {
01106 p->call_level = SIG_SS7_CALL_LEVEL_ALERTING;
01107 }
01108 sig_ss7_lock_owner(linkset, chanpos);
01109 if (p->owner) {
01110 ast_setstate(p->owner, AST_STATE_RINGING);
01111 ast_channel_unlock(p->owner);
01112 }
01113 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING);
01114 }
01115 sig_ss7_unlock_private(p);
01116 }
01117 break;
01118 case ISUP_EVENT_CGB:
01119 chanpos = ss7_find_cic_gripe(linkset, e->cgb.startcic, e->cgb.opc, "CGB");
01120 if (chanpos < 0) {
01121 break;
01122 }
01123 p = linkset->pvts[chanpos];
01124 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
01125 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
01126 break;
01127 case ISUP_EVENT_CGU:
01128 chanpos = ss7_find_cic_gripe(linkset, e->cgu.startcic, e->cgu.opc, "CGU");
01129 if (chanpos < 0) {
01130 break;
01131 }
01132 p = linkset->pvts[chanpos];
01133 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
01134 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
01135 break;
01136 case ISUP_EVENT_UCIC:
01137 chanpos = ss7_find_cic_gripe(linkset, e->ucic.cic, e->ucic.opc, "UCIC");
01138 if (chanpos < 0) {
01139 break;
01140 }
01141 p = linkset->pvts[chanpos];
01142 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
01143 sig_ss7_lock_private(p);
01144 sig_ss7_set_remotelyblocked(p, 1);
01145 sig_ss7_set_inservice(p, 0);
01146 sig_ss7_unlock_private(p);
01147 break;
01148 case ISUP_EVENT_BLO:
01149 chanpos = ss7_find_cic_gripe(linkset, e->blo.cic, e->blo.opc, "BLO");
01150 if (chanpos < 0) {
01151 break;
01152 }
01153 p = linkset->pvts[chanpos];
01154 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
01155 sig_ss7_lock_private(p);
01156 sig_ss7_set_remotelyblocked(p, 1);
01157 sig_ss7_unlock_private(p);
01158 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
01159 break;
01160 case ISUP_EVENT_BLA:
01161 chanpos = ss7_find_cic_gripe(linkset, e->bla.cic, e->bla.opc, "BLA");
01162 if (chanpos < 0) {
01163 break;
01164 }
01165 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
01166 p = linkset->pvts[chanpos];
01167 sig_ss7_lock_private(p);
01168 sig_ss7_set_locallyblocked(p, 1);
01169 sig_ss7_unlock_private(p);
01170 break;
01171 case ISUP_EVENT_UBL:
01172 chanpos = ss7_find_cic_gripe(linkset, e->ubl.cic, e->ubl.opc, "UBL");
01173 if (chanpos < 0) {
01174 break;
01175 }
01176 p = linkset->pvts[chanpos];
01177 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
01178 sig_ss7_lock_private(p);
01179 sig_ss7_set_remotelyblocked(p, 0);
01180 sig_ss7_unlock_private(p);
01181 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
01182 break;
01183 case ISUP_EVENT_UBA:
01184 chanpos = ss7_find_cic_gripe(linkset, e->uba.cic, e->uba.opc, "UBA");
01185 if (chanpos < 0) {
01186 break;
01187 }
01188 p = linkset->pvts[chanpos];
01189 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
01190 sig_ss7_lock_private(p);
01191 sig_ss7_set_locallyblocked(p, 0);
01192 sig_ss7_unlock_private(p);
01193 break;
01194 case ISUP_EVENT_CON:
01195 case ISUP_EVENT_ANM:
01196 if (e->e == ISUP_EVENT_CON) {
01197 chanpos = ss7_find_cic_gripe(linkset, e->con.cic, e->con.opc, "CON");
01198 if (chanpos < 0) {
01199 isup_rel(ss7, e->con.call, -1);
01200 break;
01201 }
01202 } else {
01203 chanpos = ss7_find_cic_gripe(linkset, e->anm.cic, e->anm.opc, "ANM");
01204 if (chanpos < 0) {
01205 isup_rel(ss7, e->anm.call, -1);
01206 break;
01207 }
01208 }
01209
01210 {
01211 p = linkset->pvts[chanpos];
01212 sig_ss7_lock_private(p);
01213 if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
01214 p->call_level = SIG_SS7_CALL_LEVEL_CONNECT;
01215 }
01216 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_ANSWER);
01217 sig_ss7_set_dialing(p, 0);
01218 sig_ss7_open_media(p);
01219 sig_ss7_set_echocanceller(p, 1);
01220 sig_ss7_unlock_private(p);
01221 }
01222 break;
01223 case ISUP_EVENT_RLC:
01224
01225 chanpos = ss7_find_cic_gripe(linkset, e->rlc.cic, e->rlc.opc, "RLC");
01226 if (chanpos < 0) {
01227 break;
01228 }
01229 {
01230 p = linkset->pvts[chanpos];
01231 sig_ss7_lock_private(p);
01232 if (p->alreadyhungup) {
01233 if (!p->owner) {
01234 p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
01235 }
01236 p->ss7call = NULL;
01237 }
01238 sig_ss7_unlock_private(p);
01239 }
01240 break;
01241 case ISUP_EVENT_FAA:
01242
01243
01244
01245
01246 chanpos = ss7_find_cic_gripe(linkset, e->faa.cic, e->faa.opc, "FAA");
01247 if (chanpos < 0) {
01248 isup_rel(linkset->ss7, e->faa.call, -1);
01249 break;
01250 }
01251 {
01252
01253 p = linkset->pvts[chanpos];
01254 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
01255 sig_ss7_lock_private(p);
01256 if (p->alreadyhungup){
01257 if (!p->owner) {
01258 p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
01259 }
01260
01261 p->ss7call = NULL;
01262 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
01263 }
01264 sig_ss7_unlock_private(p);
01265 }
01266 break;
01267 default:
01268 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
01269 break;
01270 }
01271 }
01272 ast_mutex_unlock(&linkset->lock);
01273 }
01274
01275 return 0;
01276 }
01277
01278 static inline void ss7_rel(struct sig_ss7_linkset *ss7)
01279 {
01280 ast_mutex_unlock(&ss7->lock);
01281 }
01282
01283 static void ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7)
01284 {
01285
01286 while (ast_mutex_trylock(&ss7->lock)) {
01287
01288 sig_ss7_unlock_private(pvt);
01289 sched_yield();
01290 sig_ss7_lock_private(pvt);
01291 }
01292
01293 if (ss7->master != AST_PTHREADT_NULL) {
01294 pthread_kill(ss7->master, SIGURG);
01295 }
01296 }
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307 void sig_ss7_link_alarm(struct sig_ss7_linkset *linkset, int which)
01308 {
01309 linkset->linkstate[which] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
01310 linkset->linkstate[which] &= ~LINKSTATE_UP;
01311 ss7_link_alarm(linkset->ss7, linkset->fds[which]);
01312 }
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323 void sig_ss7_link_noalarm(struct sig_ss7_linkset *linkset, int which)
01324 {
01325 linkset->linkstate[which] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
01326 linkset->linkstate[which] |= LINKSTATE_STARTING;
01327 ss7_link_noalarm(linkset->ss7, linkset->fds[which]);
01328 }
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346 int sig_ss7_add_sigchan(struct sig_ss7_linkset *linkset, int which, int ss7type, int transport, int inalarm, int networkindicator, int pointcode, int adjpointcode)
01347 {
01348 if (!linkset->ss7) {
01349 linkset->type = ss7type;
01350 linkset->ss7 = ss7_new(ss7type);
01351 if (!linkset->ss7) {
01352 ast_log(LOG_ERROR, "Can't create new SS7!\n");
01353 return -1;
01354 }
01355 }
01356
01357 ss7_set_network_ind(linkset->ss7, networkindicator);
01358 ss7_set_pc(linkset->ss7, pointcode);
01359
01360 if (ss7_add_link(linkset->ss7, transport, linkset->fds[which])) {
01361 ast_log(LOG_WARNING, "Could not add SS7 link!\n");
01362 }
01363
01364 if (inalarm) {
01365 linkset->linkstate[which] = LINKSTATE_DOWN | LINKSTATE_INALARM;
01366 ss7_link_alarm(linkset->ss7, linkset->fds[which]);
01367 } else {
01368 linkset->linkstate[which] = LINKSTATE_DOWN;
01369 ss7_link_noalarm(linkset->ss7, linkset->fds[which]);
01370 }
01371
01372 ss7_set_adjpc(linkset->ss7, linkset->fds[which], adjpointcode);
01373
01374 return 0;
01375 }
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385 int sig_ss7_available(struct sig_ss7_chan *p)
01386 {
01387 int available;
01388
01389 if (!p->ss7) {
01390
01391 return 0;
01392 }
01393
01394
01395 ast_mutex_lock(&p->ss7->lock);
01396 available = sig_ss7_is_chan_available(p);
01397 if (available) {
01398 p->call_level = SIG_SS7_CALL_LEVEL_ALLOCATED;
01399 }
01400 ast_mutex_unlock(&p->ss7->lock);
01401
01402 return available;
01403 }
01404
01405 static unsigned char cid_pres2ss7pres(int cid_pres)
01406 {
01407 return (cid_pres >> 5) & 0x03;
01408 }
01409
01410 static unsigned char cid_pres2ss7screen(int cid_pres)
01411 {
01412 return cid_pres & 0x03;
01413 }
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426 int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest)
01427 {
01428 char ss7_called_nai;
01429 int called_nai_strip;
01430 char ss7_calling_nai;
01431 int calling_nai_strip;
01432 const char *charge_str = NULL;
01433 const char *gen_address = NULL;
01434 const char *gen_digits = NULL;
01435 const char *gen_dig_type = NULL;
01436 const char *gen_dig_scheme = NULL;
01437 const char *gen_name = NULL;
01438 const char *jip_digits = NULL;
01439 const char *lspi_ident = NULL;
01440 const char *rlt_flag = NULL;
01441 const char *call_ref_id = NULL;
01442 const char *call_ref_pc = NULL;
01443 const char *send_far = NULL;
01444 char *c;
01445 char *l;
01446 char dest[256];
01447
01448 ast_copy_string(dest, rdest, sizeof(dest));
01449
01450 c = strchr(dest, '/');
01451 if (c) {
01452 c++;
01453 } else {
01454 c = "";
01455 }
01456 if (strlen(c) < p->stripmsd) {
01457 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01458 return -1;
01459 }
01460
01461 if (!p->hidecallerid) {
01462 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
01463 } else {
01464 l = NULL;
01465 }
01466
01467 ss7_grab(p, p->ss7);
01468
01469 if (p->call_level != SIG_SS7_CALL_LEVEL_ALLOCATED) {
01470
01471 ss7_rel(p->ss7);
01472 return -1;
01473 }
01474
01475 p->ss7call = isup_new_call(p->ss7->ss7);
01476 if (!p->ss7call) {
01477 ss7_rel(p->ss7);
01478 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
01479 return -1;
01480 }
01481
01482 called_nai_strip = 0;
01483 ss7_called_nai = p->ss7->called_nai;
01484 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
01485 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
01486 called_nai_strip = strlen(p->ss7->internationalprefix);
01487 ss7_called_nai = SS7_NAI_INTERNATIONAL;
01488 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
01489 called_nai_strip = strlen(p->ss7->nationalprefix);
01490 ss7_called_nai = SS7_NAI_NATIONAL;
01491 } else {
01492 ss7_called_nai = SS7_NAI_SUBSCRIBER;
01493 }
01494 }
01495 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
01496
01497 calling_nai_strip = 0;
01498 ss7_calling_nai = p->ss7->calling_nai;
01499 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
01500 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
01501 calling_nai_strip = strlen(p->ss7->internationalprefix);
01502 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
01503 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
01504 calling_nai_strip = strlen(p->ss7->nationalprefix);
01505 ss7_calling_nai = SS7_NAI_NATIONAL;
01506 } else {
01507 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
01508 }
01509 }
01510 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
01511 p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number.presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
01512 p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number.presentation) : SS7_SCREENING_USER_PROVIDED);
01513
01514 isup_set_oli(p->ss7call, ast->connected.ani2);
01515 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
01516
01517
01518 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
01519 if (charge_str)
01520 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
01521
01522 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
01523 if (gen_address)
01524 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);
01525
01526 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
01527 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
01528 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
01529 if (gen_digits)
01530 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
01531
01532 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
01533 if (gen_name)
01534 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
01535
01536 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
01537 if (jip_digits)
01538 isup_set_jip_digits(p->ss7call, jip_digits);
01539
01540 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
01541 if (lspi_ident)
01542 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
01543
01544 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
01545 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
01546 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
01547 }
01548
01549 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
01550 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
01551 if (call_ref_id && call_ref_pc) {
01552 isup_set_callref(p->ss7call, atoi(call_ref_id),
01553 call_ref_pc ? atoi(call_ref_pc) : 0);
01554 }
01555
01556 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
01557 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
01558 (isup_far(p->ss7->ss7, p->ss7call));
01559
01560 p->call_level = SIG_SS7_CALL_LEVEL_SETUP;
01561 isup_iam(p->ss7->ss7, p->ss7call);
01562 sig_ss7_set_dialing(p, 1);
01563 ast_setstate(ast, AST_STATE_DIALING);
01564 ss7_rel(p->ss7);
01565 return 0;
01566 }
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578 int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
01579 {
01580 int res = 0;
01581
01582 if (!ast->tech_pvt) {
01583 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
01584 return 0;
01585 }
01586
01587 p->owner = NULL;
01588 sig_ss7_set_dialing(p, 0);
01589 sig_ss7_set_outgoing(p, 0);
01590 p->progress = 0;
01591 p->rlt = 0;
01592 p->exten[0] = '\0';
01593
01594 ss7_grab(p, p->ss7);
01595 p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
01596 if (p->ss7call) {
01597 if (!p->alreadyhungup) {
01598 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
01599 int icause = ast->hangupcause ? ast->hangupcause : -1;
01600
01601 if (cause) {
01602 if (atoi(cause)) {
01603 icause = atoi(cause);
01604 }
01605 }
01606 isup_rel(p->ss7->ss7, p->ss7call, icause);
01607 p->alreadyhungup = 1;
01608 }
01609 }
01610 ss7_rel(p->ss7);
01611
01612 return res;
01613 }
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625 int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
01626 {
01627 int res;
01628
01629 ss7_grab(p, p->ss7);
01630 if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
01631 p->call_level = SIG_SS7_CALL_LEVEL_CONNECT;
01632 }
01633 sig_ss7_open_media(p);
01634 res = isup_anm(p->ss7->ss7, p->ss7call);
01635 ss7_rel(p->ss7);
01636 return res;
01637 }
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649 void sig_ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan)
01650 {
01651 if (pchan->owner == oldchan) {
01652 pchan->owner = newchan;
01653 }
01654 }
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669 int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
01670 {
01671 int res = -1;
01672
01673 switch (condition) {
01674 case AST_CONTROL_BUSY:
01675 if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
01676 chan->hangupcause = AST_CAUSE_USER_BUSY;
01677 ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);
01678 res = 0;
01679 break;
01680 }
01681 res = sig_ss7_play_tone(p, SIG_SS7_TONE_BUSY);
01682 break;
01683 case AST_CONTROL_RINGING:
01684 ss7_grab(p, p->ss7);
01685 if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING && !p->outgoing) {
01686 p->call_level = SIG_SS7_CALL_LEVEL_ALERTING;
01687 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) {
01688 p->rlt = 1;
01689 }
01690
01691
01692 if (p->rlt != 1) {
01693 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
01694 }
01695 }
01696 ss7_rel(p->ss7);
01697
01698 res = sig_ss7_play_tone(p, SIG_SS7_TONE_RINGTONE);
01699
01700 if (chan->_state != AST_STATE_UP && chan->_state != AST_STATE_RING) {
01701 ast_setstate(chan, AST_STATE_RINGING);
01702 }
01703 break;
01704 case AST_CONTROL_PROCEEDING:
01705 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
01706 ss7_grab(p, p->ss7);
01707
01708 if (chan->_state == AST_STATE_UP && (p->rlt != 1)){
01709 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) {
01710 p->rlt = 1;
01711 }
01712 }
01713
01714 if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING && !p->outgoing) {
01715 p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING;
01716 isup_acm(p->ss7->ss7, p->ss7call);
01717 }
01718 ss7_rel(p->ss7);
01719
01720 res = 0;
01721 break;
01722 case AST_CONTROL_PROGRESS:
01723 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
01724 ss7_grab(p, p->ss7);
01725 if (!p->progress && p->call_level < SIG_SS7_CALL_LEVEL_ALERTING && !p->outgoing) {
01726 p->progress = 1;
01727 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
01728 ss7_rel(p->ss7);
01729
01730
01731 sig_ss7_set_echocanceller(p, 1);
01732 } else {
01733 ss7_rel(p->ss7);
01734 }
01735
01736 res = 0;
01737 break;
01738 case AST_CONTROL_INCOMPLETE:
01739 if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
01740 chan->hangupcause = AST_CAUSE_INVALID_NUMBER_FORMAT;
01741 ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);
01742 res = 0;
01743 break;
01744 }
01745
01746 res = 0;
01747 break;
01748 case AST_CONTROL_CONGESTION:
01749 if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
01750 chan->hangupcause = AST_CAUSE_CONGESTION;
01751 ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);
01752 res = 0;
01753 break;
01754 }
01755 res = sig_ss7_play_tone(p, SIG_SS7_TONE_CONGESTION);
01756 break;
01757 case AST_CONTROL_HOLD:
01758 ast_moh_start(chan, data, p->mohinterpret);
01759 break;
01760 case AST_CONTROL_UNHOLD:
01761 ast_moh_stop(chan);
01762 break;
01763 case AST_CONTROL_SRCUPDATE:
01764 res = 0;
01765 break;
01766 case -1:
01767 res = sig_ss7_play_tone(p, -1);
01768 break;
01769 }
01770 return res;
01771 }
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785 struct ast_channel *sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_channel *requestor, int transfercapability)
01786 {
01787 struct ast_channel *ast;
01788
01789
01790 if (p->ss7->type == SS7_ITU) {
01791 law = SIG_SS7_ALAW;
01792 } else {
01793 law = SIG_SS7_ULAW;
01794 }
01795
01796 sig_ss7_set_outgoing(p, 1);
01797 ast = sig_ss7_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor);
01798 if (!ast) {
01799 sig_ss7_set_outgoing(p, 0);
01800
01801
01802 ast_mutex_lock(&p->ss7->lock);
01803 p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
01804 ast_mutex_unlock(&p->ss7->lock);
01805 }
01806 return ast;
01807 }
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817 void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
01818 {
01819 ast_free(doomed);
01820 }
01821
01822 #define SIG_SS7_SC_HEADER "%-4s %4s %-4s %-3s %-3s %-10s %-4s %s\n"
01823 #define SIG_SS7_SC_LINE "%4d %4d %-4s %-3s %-3s %-10s %-4s %s"
01824 void sig_ss7_cli_show_channels_header(int fd)
01825 {
01826 ast_cli(fd, SIG_SS7_SC_HEADER, "link", "", "Chan", "Lcl", "Rem", "Call", "SS7", "Channel");
01827 ast_cli(fd, SIG_SS7_SC_HEADER, "set", "Chan", "Idle", "Blk", "Blk", "Level", "Call", "Name");
01828 }
01829
01830 void sig_ss7_cli_show_channels(int fd, struct sig_ss7_linkset *linkset)
01831 {
01832 char line[256];
01833 int idx;
01834 struct sig_ss7_chan *pvt;
01835
01836 ast_mutex_lock(&linkset->lock);
01837 for (idx = 0; idx < linkset->numchans; ++idx) {
01838 if (!linkset->pvts[idx]) {
01839 continue;
01840 }
01841 pvt = linkset->pvts[idx];
01842 sig_ss7_lock_private(pvt);
01843 sig_ss7_lock_owner(linkset, idx);
01844
01845 snprintf(line, sizeof(line), SIG_SS7_SC_LINE,
01846 linkset->span,
01847 pvt->channel,
01848 sig_ss7_is_chan_available(pvt) ? "Yes" : "No",
01849 pvt->locallyblocked ? "Yes" : "No",
01850 pvt->remotelyblocked ? "Yes" : "No",
01851 sig_ss7_call_level2str(pvt->call_level),
01852 pvt->ss7call ? "Yes" : "No",
01853 pvt->owner ? pvt->owner->name : "");
01854
01855 if (pvt->owner) {
01856 ast_channel_unlock(pvt->owner);
01857 }
01858 sig_ss7_unlock_private(pvt);
01859
01860 ast_mutex_unlock(&linkset->lock);
01861 ast_cli(fd, "%s\n", line);
01862 ast_mutex_lock(&linkset->lock);
01863 }
01864 ast_mutex_unlock(&linkset->lock);
01865 }
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878 struct sig_ss7_chan *sig_ss7_chan_new(void *pvt_data, struct sig_ss7_callback *callback, struct sig_ss7_linkset *ss7)
01879 {
01880 struct sig_ss7_chan *pvt;
01881
01882 pvt = ast_calloc(1, sizeof(*pvt));
01883 if (!pvt) {
01884 return pvt;
01885 }
01886
01887 pvt->calls = callback;
01888 pvt->chan_pvt = pvt_data;
01889 pvt->ss7 = ss7;
01890
01891 return pvt;
01892 }
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902 void sig_ss7_init_linkset(struct sig_ss7_linkset *ss7)
01903 {
01904 int idx;
01905
01906 memset(ss7, 0, sizeof(*ss7));
01907
01908 ast_mutex_init(&ss7->lock);
01909
01910 ss7->master = AST_PTHREADT_NULL;
01911 for (idx = 0; idx < ARRAY_LEN(ss7->fds); ++idx) {
01912 ss7->fds[idx] = -1;
01913 }
01914 }
01915
01916
01917
01918 #endif
01919