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