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