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