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->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING;
00435 isup_acm(ss7, p->ss7call);
00436 } else {
00437 p->call_level = SIG_SS7_CALL_LEVEL_SETUP;
00438 }
00439
00440 if (linkset->type == SS7_ITU) {
00441 law = SIG_SS7_ALAW;
00442 } else {
00443 law = SIG_SS7_ULAW;
00444 }
00445
00446
00447
00448
00449
00450 ast_mutex_unlock(&linkset->lock);
00451 c = sig_ss7_new_ast_channel(p, AST_STATE_RING, law, 0, p->exten, NULL);
00452 if (!c) {
00453 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
00454 ast_mutex_lock(&linkset->lock);
00455 isup_rel(linkset->ss7, p->ss7call, -1);
00456 p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
00457 p->alreadyhungup = 1;
00458 return;
00459 }
00460
00461 sig_ss7_set_echocanceller(p, 1);
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 if (!ast_strlen_zero(p->charge_number)) {
00475 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
00476
00477 p->charge_number[0] = 0;
00478 }
00479 if (!ast_strlen_zero(p->gen_add_number)) {
00480 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
00481
00482 p->gen_add_number[0] = 0;
00483 }
00484 if (!ast_strlen_zero(p->jip_number)) {
00485 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
00486
00487 p->jip_number[0] = 0;
00488 }
00489 if (!ast_strlen_zero(p->gen_dig_number)) {
00490 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
00491
00492 p->gen_dig_number[0] = 0;
00493 }
00494 if (!ast_strlen_zero(p->orig_called_num)) {
00495 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
00496
00497 p->orig_called_num[0] = 0;
00498 }
00499
00500 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
00501 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
00502
00503 p->gen_dig_type = 0;
00504
00505 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
00506 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
00507
00508 p->gen_dig_scheme = 0;
00509
00510 if (!ast_strlen_zero(p->lspi_ident)) {
00511 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
00512
00513 p->lspi_ident[0] = 0;
00514 }
00515
00516 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
00517 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
00518
00519 p->call_ref_ident = 0;
00520
00521 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
00522 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
00523
00524 p->call_ref_pc = 0;
00525
00526 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
00527 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
00528
00529 p->calling_party_cat = 0;
00530
00531 if (!ast_strlen_zero(p->redirecting_num)) {
00532 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
00533
00534 p->redirecting_num[0] = 0;
00535 }
00536 if (!ast_strlen_zero(p->generic_name)) {
00537 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
00538
00539 p->generic_name[0] = 0;
00540 }
00541
00542 if (ast_pbx_start(c)) {
00543 ast_log(LOG_WARNING, "Unable to start PBX on %s (CIC %d)\n", c->name, p->cic);
00544 ast_hangup(c);
00545 } else {
00546 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
00547 }
00548 ast_mutex_lock(&linkset->lock);
00549 }
00550
00551 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct sig_ss7_linkset *ss7, const char *number, const unsigned nai)
00552 {
00553 if (ast_strlen_zero(number)) {
00554 if (size) {
00555 *buf = '\0';
00556 }
00557 return;
00558 }
00559 switch (nai) {
00560 case SS7_NAI_INTERNATIONAL:
00561 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
00562 break;
00563 case SS7_NAI_NATIONAL:
00564 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
00565 break;
00566 case SS7_NAI_SUBSCRIBER:
00567 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
00568 break;
00569 case SS7_NAI_UNKNOWN:
00570 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
00571 break;
00572 default:
00573 snprintf(buf, size, "%s", number);
00574 break;
00575 }
00576 }
00577
00578 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
00579 {
00580 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
00581 }
00582
00583
00584 void *ss7_linkset(void *data)
00585 {
00586 int res, i;
00587 struct timeval *next = NULL, tv;
00588 struct sig_ss7_linkset *linkset = (struct sig_ss7_linkset *) data;
00589 struct ss7 *ss7 = linkset->ss7;
00590 ss7_event *e = NULL;
00591 struct sig_ss7_chan *p;
00592 int chanpos;
00593 struct pollfd pollers[SIG_SS7_NUM_DCHANS];
00594 int cic;
00595 unsigned int dpc;
00596 int nextms = 0;
00597
00598 ss7_set_debug(ss7, SIG_SS7_DEBUG_DEFAULT);
00599 ss7_start(ss7);
00600
00601 for (;;) {
00602 ast_mutex_lock(&linkset->lock);
00603 if ((next = ss7_schedule_next(ss7))) {
00604 tv = ast_tvnow();
00605 tv.tv_sec = next->tv_sec - tv.tv_sec;
00606 tv.tv_usec = next->tv_usec - tv.tv_usec;
00607 if (tv.tv_usec < 0) {
00608 tv.tv_usec += 1000000;
00609 tv.tv_sec -= 1;
00610 }
00611 if (tv.tv_sec < 0) {
00612 tv.tv_sec = 0;
00613 tv.tv_usec = 0;
00614 }
00615 nextms = tv.tv_sec * 1000;
00616 nextms += tv.tv_usec / 1000;
00617 }
00618 ast_mutex_unlock(&linkset->lock);
00619
00620 for (i = 0; i < linkset->numsigchans; i++) {
00621 pollers[i].fd = linkset->fds[i];
00622 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
00623 pollers[i].revents = 0;
00624 }
00625
00626 res = poll(pollers, linkset->numsigchans, nextms);
00627 if ((res < 0) && (errno != EINTR)) {
00628 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
00629 } else if (!res) {
00630 ast_mutex_lock(&linkset->lock);
00631 ss7_schedule_run(ss7);
00632 ast_mutex_unlock(&linkset->lock);
00633 continue;
00634 }
00635
00636 ast_mutex_lock(&linkset->lock);
00637 for (i = 0; i < linkset->numsigchans; i++) {
00638 if (pollers[i].revents & POLLPRI) {
00639 sig_ss7_handle_link_exception(linkset, i);
00640 }
00641 if (pollers[i].revents & POLLIN) {
00642 res = ss7_read(ss7, pollers[i].fd);
00643 }
00644 if (pollers[i].revents & POLLOUT) {
00645 res = ss7_write(ss7, pollers[i].fd);
00646 if (res < 0) {
00647 ast_debug(1, "Error in write %s\n", strerror(errno));
00648 }
00649 }
00650 }
00651
00652 while ((e = ss7_check_event(ss7))) {
00653 switch (e->e) {
00654 case SS7_EVENT_UP:
00655 if (linkset->state != LINKSET_STATE_UP) {
00656 ast_verbose("--- SS7 Up ---\n");
00657 ss7_reset_linkset(linkset);
00658 }
00659 linkset->state = LINKSET_STATE_UP;
00660 break;
00661 case SS7_EVENT_DOWN:
00662 ast_verbose("--- SS7 Down ---\n");
00663 linkset->state = LINKSET_STATE_DOWN;
00664 for (i = 0; i < linkset->numchans; i++) {
00665 p = linkset->pvts[i];
00666 if (p) {
00667 sig_ss7_set_alarm(p, 1);
00668 }
00669 }
00670 break;
00671 case MTP2_LINK_UP:
00672 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
00673 break;
00674 case MTP2_LINK_DOWN:
00675 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
00676 break;
00677 case ISUP_EVENT_CPG:
00678 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
00679 if (chanpos < 0) {
00680 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
00681 break;
00682 }
00683 p = linkset->pvts[chanpos];
00684 sig_ss7_lock_private(p);
00685 switch (e->cpg.event) {
00686 case CPG_EVENT_ALERTING:
00687 if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING) {
00688 p->call_level = SIG_SS7_CALL_LEVEL_ALERTING;
00689 }
00690 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING);
00691 break;
00692 case CPG_EVENT_PROGRESS:
00693 case CPG_EVENT_INBANDINFO:
00694 {
00695 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
00696 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROGRESS);
00697 p->progress = 1;
00698 sig_ss7_set_dialing(p, 0);
00699 #if 0
00700 if (p->dsp && p->dsp_features) {
00701 ast_dsp_set_features(p->dsp, p->dsp_features);
00702 p->dsp_features = 0;
00703 }
00704 #endif
00705 }
00706 break;
00707 default:
00708 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
00709 break;
00710 }
00711
00712 sig_ss7_unlock_private(p);
00713 break;
00714 case ISUP_EVENT_RSC:
00715 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
00716 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
00717 if (chanpos < 0) {
00718 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
00719 break;
00720 }
00721 p = linkset->pvts[chanpos];
00722 sig_ss7_lock_private(p);
00723 sig_ss7_set_inservice(p, 1);
00724 sig_ss7_set_remotelyblocked(p, 0);
00725 dpc = p->dpc;
00726 isup_set_call_dpc(e->rsc.call, dpc);
00727 p->ss7call = NULL;
00728 if (p->owner)
00729 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
00730 sig_ss7_unlock_private(p);
00731 isup_rlc(ss7, e->rsc.call);
00732 break;
00733 case ISUP_EVENT_GRS:
00734 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
00735 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
00736 if (chanpos < 0) {
00737 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
00738 break;
00739 }
00740 p = linkset->pvts[chanpos];
00741 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
00742 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
00743 ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
00744 break;
00745 case ISUP_EVENT_CQM:
00746 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
00747 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
00748 break;
00749 case ISUP_EVENT_GRA:
00750 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
00751 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
00752 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
00753 break;
00754 case ISUP_EVENT_IAM:
00755 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);
00756 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
00757 if (chanpos < 0) {
00758 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
00759 isup_rel(ss7, e->iam.call, -1);
00760 break;
00761 }
00762 p = linkset->pvts[chanpos];
00763 sig_ss7_lock_private(p);
00764 if (p->owner) {
00765 if (p->ss7call == e->iam.call) {
00766 sig_ss7_unlock_private(p);
00767 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
00768 break;
00769 } else {
00770 sig_ss7_unlock_private(p);
00771 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
00772 break;
00773 }
00774 }
00775
00776 dpc = p->dpc;
00777 p->ss7call = e->iam.call;
00778 isup_set_call_dpc(p->ss7call, dpc);
00779
00780 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
00781 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
00782 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
00783 } else
00784 p->cid_num[0] = 0;
00785
00786
00787 if (!ast_strlen_zero(e->iam.called_party_num)) {
00788 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset,
00789 e->iam.called_party_num, e->iam.called_nai);
00790 sig_ss7_set_dnid(p, p->exten);
00791 }
00792
00793 if (p->immediate) {
00794 p->exten[0] = 's';
00795 p->exten[1] = '\0';
00796 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
00797 char *st;
00798 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
00799 st = strchr(p->exten, '#');
00800 if (st) {
00801 *st = '\0';
00802 }
00803 } else {
00804 p->exten[0] = '\0';
00805 }
00806
00807 p->cid_ani[0] = '\0';
00808 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
00809 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
00810 else
00811 p->cid_name[0] = '\0';
00812
00813 p->cid_ani2 = e->iam.oli_ani2;
00814 p->cid_ton = 0;
00815 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
00816 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
00817 p->gen_add_type = e->iam.gen_add_type;
00818 p->gen_add_nai = e->iam.gen_add_nai;
00819 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
00820 p->gen_add_num_plan = e->iam.gen_add_num_plan;
00821 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
00822 p->gen_dig_type = e->iam.gen_dig_type;
00823 p->gen_dig_scheme = e->iam.gen_dig_scheme;
00824 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
00825 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
00826 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
00827 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
00828 p->calling_party_cat = e->iam.calling_party_cat;
00829
00830 sig_ss7_set_caller_id(p);
00831
00832 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
00833 if (e->iam.cot_check_required) {
00834 sig_ss7_loopback(p, 1);
00835 } else
00836 ss7_start_call(p, linkset);
00837 } else {
00838 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
00839 p->alreadyhungup = 1;
00840 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
00841 }
00842 sig_ss7_unlock_private(p);
00843 break;
00844 case ISUP_EVENT_COT:
00845 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
00846 if (chanpos < 0) {
00847 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
00848 isup_rel(ss7, e->cot.call, -1);
00849 break;
00850 }
00851 p = linkset->pvts[chanpos];
00852
00853 sig_ss7_lock_private(p);
00854 if (p->loopedback) {
00855 sig_ss7_loopback(p, 0);
00856 ss7_start_call(p, linkset);
00857 }
00858 sig_ss7_unlock_private(p);
00859 break;
00860 case ISUP_EVENT_CCR:
00861 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
00862 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
00863 if (chanpos < 0) {
00864 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
00865 break;
00866 }
00867
00868 p = linkset->pvts[chanpos];
00869
00870 sig_ss7_lock_private(p);
00871 sig_ss7_loopback(p, 1);
00872 sig_ss7_unlock_private(p);
00873
00874 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
00875 break;
00876 case ISUP_EVENT_CVT:
00877 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
00878 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
00879 if (chanpos < 0) {
00880 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
00881 break;
00882 }
00883
00884 p = linkset->pvts[chanpos];
00885
00886 sig_ss7_lock_private(p);
00887 sig_ss7_loopback(p, 1);
00888 sig_ss7_unlock_private(p);
00889
00890 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
00891 break;
00892 case ISUP_EVENT_REL:
00893 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
00894 if (chanpos < 0) {
00895 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
00896 break;
00897 }
00898 p = linkset->pvts[chanpos];
00899 sig_ss7_lock_private(p);
00900 if (p->owner) {
00901 p->owner->hangupcause = e->rel.cause;
00902 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
00903 } else {
00904 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
00905 }
00906
00907
00908 sig_ss7_loopback(p, 0);
00909
00910 isup_rlc(ss7, e->rel.call);
00911 p->ss7call = NULL;
00912
00913 sig_ss7_unlock_private(p);
00914 break;
00915 case ISUP_EVENT_ACM:
00916 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
00917 if (chanpos < 0) {
00918 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
00919 isup_rel(ss7, e->acm.call, -1);
00920 break;
00921 } else {
00922 p = linkset->pvts[chanpos];
00923
00924 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
00925
00926 if (e->acm.call_ref_ident > 0) {
00927 p->rlt = 1;
00928 }
00929
00930 sig_ss7_lock_private(p);
00931 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROCEEDING);
00932 if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING) {
00933 p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING;
00934 }
00935 sig_ss7_set_dialing(p, 0);
00936
00937 if (e->acm.called_party_status_ind == 1) {
00938 if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING) {
00939 p->call_level = SIG_SS7_CALL_LEVEL_ALERTING;
00940 }
00941 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING);
00942 }
00943 sig_ss7_unlock_private(p);
00944 }
00945 break;
00946 case ISUP_EVENT_CGB:
00947 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
00948 if (chanpos < 0) {
00949 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
00950 break;
00951 }
00952 p = linkset->pvts[chanpos];
00953 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
00954 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
00955 break;
00956 case ISUP_EVENT_CGU:
00957 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
00958 if (chanpos < 0) {
00959 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
00960 break;
00961 }
00962 p = linkset->pvts[chanpos];
00963 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
00964 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
00965 break;
00966 case ISUP_EVENT_UCIC:
00967 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
00968 if (chanpos < 0) {
00969 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
00970 break;
00971 }
00972 p = linkset->pvts[chanpos];
00973 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
00974 sig_ss7_lock_private(p);
00975 sig_ss7_set_remotelyblocked(p, 1);
00976 sig_ss7_set_inservice(p, 0);
00977 sig_ss7_unlock_private(p);
00978 break;
00979 case ISUP_EVENT_BLO:
00980 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
00981 if (chanpos < 0) {
00982 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
00983 break;
00984 }
00985 p = linkset->pvts[chanpos];
00986 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
00987 sig_ss7_lock_private(p);
00988 sig_ss7_set_remotelyblocked(p, 1);
00989 sig_ss7_unlock_private(p);
00990 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
00991 break;
00992 case ISUP_EVENT_BLA:
00993 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
00994 if (chanpos < 0) {
00995 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
00996 break;
00997 }
00998 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
00999 p = linkset->pvts[chanpos];
01000 sig_ss7_lock_private(p);
01001 sig_ss7_set_locallyblocked(p, 1);
01002 sig_ss7_unlock_private(p);
01003 break;
01004 case ISUP_EVENT_UBL:
01005 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
01006 if (chanpos < 0) {
01007 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
01008 break;
01009 }
01010 p = linkset->pvts[chanpos];
01011 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
01012 sig_ss7_lock_private(p);
01013 sig_ss7_set_remotelyblocked(p, 0);
01014 sig_ss7_unlock_private(p);
01015 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
01016 break;
01017 case ISUP_EVENT_UBA:
01018 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
01019 if (chanpos < 0) {
01020 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
01021 break;
01022 }
01023 p = linkset->pvts[chanpos];
01024 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
01025 sig_ss7_lock_private(p);
01026 sig_ss7_set_locallyblocked(p, 0);
01027 sig_ss7_unlock_private(p);
01028 break;
01029 case ISUP_EVENT_CON:
01030 case ISUP_EVENT_ANM:
01031 if (e->e == ISUP_EVENT_CON)
01032 cic = e->con.cic;
01033 else
01034 cic = e->anm.cic;
01035
01036 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
01037 if (chanpos < 0) {
01038 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
01039 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
01040 break;
01041 } else {
01042 p = linkset->pvts[chanpos];
01043 sig_ss7_lock_private(p);
01044 if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
01045 p->call_level = SIG_SS7_CALL_LEVEL_CONNECT;
01046 }
01047 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_ANSWER);
01048 #if 0
01049 if (p->dsp && p->dsp_features) {
01050 ast_dsp_set_features(p->dsp, p->dsp_features);
01051 p->dsp_features = 0;
01052 }
01053 #endif
01054 sig_ss7_set_echocanceller(p, 1);
01055 sig_ss7_unlock_private(p);
01056 }
01057 break;
01058 case ISUP_EVENT_RLC:
01059 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
01060 if (chanpos < 0) {
01061 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
01062 break;
01063 } else {
01064 p = linkset->pvts[chanpos];
01065 sig_ss7_lock_private(p);
01066 if (p->alreadyhungup)
01067 p->ss7call = NULL;
01068 else
01069 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
01070 sig_ss7_unlock_private(p);
01071 }
01072 break;
01073 case ISUP_EVENT_FAA:
01074 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
01075 if (chanpos < 0) {
01076 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
01077 break;
01078 } else {
01079 p = linkset->pvts[chanpos];
01080 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
01081 sig_ss7_lock_private(p);
01082 if (p->alreadyhungup){
01083 p->ss7call = NULL;
01084 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
01085 }
01086 sig_ss7_unlock_private(p);
01087 }
01088 break;
01089 default:
01090 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
01091 break;
01092 }
01093 }
01094 ast_mutex_unlock(&linkset->lock);
01095 }
01096
01097 return 0;
01098 }
01099
01100 static inline void ss7_rel(struct sig_ss7_linkset *ss7)
01101 {
01102 ast_mutex_unlock(&ss7->lock);
01103 }
01104
01105 static inline int ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7)
01106 {
01107 int res;
01108
01109 do {
01110 res = ast_mutex_trylock(&ss7->lock);
01111 if (res) {
01112 SIG_SS7_DEADLOCK_AVOIDANCE(pvt);
01113 }
01114 } while (res);
01115
01116 if (ss7->master != AST_PTHREADT_NULL)
01117 pthread_kill(ss7->master, SIGURG);
01118 return 0;
01119 }
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130 void sig_ss7_link_alarm(struct sig_ss7_linkset *linkset, int which)
01131 {
01132 linkset->linkstate[which] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
01133 linkset->linkstate[which] &= ~LINKSTATE_UP;
01134 ss7_link_alarm(linkset->ss7, linkset->fds[which]);
01135 }
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146 void sig_ss7_link_noalarm(struct sig_ss7_linkset *linkset, int which)
01147 {
01148 linkset->linkstate[which] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
01149 linkset->linkstate[which] |= LINKSTATE_STARTING;
01150 ss7_link_noalarm(linkset->ss7, linkset->fds[which]);
01151 }
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169 int sig_ss7_add_sigchan(struct sig_ss7_linkset *linkset, int which, int ss7type, int transport, int inalarm, int networkindicator, int pointcode, int adjpointcode)
01170 {
01171 if (!linkset->ss7) {
01172 linkset->type = ss7type;
01173 linkset->ss7 = ss7_new(ss7type);
01174 if (!linkset->ss7) {
01175 ast_log(LOG_ERROR, "Can't create new SS7!\n");
01176 return -1;
01177 }
01178 }
01179
01180 ss7_set_network_ind(linkset->ss7, networkindicator);
01181 ss7_set_pc(linkset->ss7, pointcode);
01182
01183 if (ss7_add_link(linkset->ss7, transport, linkset->fds[which])) {
01184 ast_log(LOG_WARNING, "Could not add SS7 link!\n");
01185 }
01186
01187 if (inalarm) {
01188 linkset->linkstate[which] = LINKSTATE_DOWN | LINKSTATE_INALARM;
01189 ss7_link_alarm(linkset->ss7, linkset->fds[which]);
01190 } else {
01191 linkset->linkstate[which] = LINKSTATE_DOWN;
01192 ss7_link_noalarm(linkset->ss7, linkset->fds[which]);
01193 }
01194
01195 ss7_set_adjpc(linkset->ss7, linkset->fds[which], adjpointcode);
01196
01197 return 0;
01198 }
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208 int sig_ss7_available(struct sig_ss7_chan *p)
01209 {
01210 if (!p->ss7) {
01211
01212 return 0;
01213 }
01214
01215 if (!p->inalarm && !p->owner && !p->ss7call
01216 && !p->locallyblocked && !p->remotelyblocked) {
01217 return 1;
01218 }
01219
01220 return 0;
01221 }
01222
01223 static unsigned char cid_pres2ss7pres(int cid_pres)
01224 {
01225 return (cid_pres >> 5) & 0x03;
01226 }
01227
01228 static unsigned char cid_pres2ss7screen(int cid_pres)
01229 {
01230 return cid_pres & 0x03;
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest)
01245 {
01246 char ss7_called_nai;
01247 int called_nai_strip;
01248 char ss7_calling_nai;
01249 int calling_nai_strip;
01250 const char *charge_str = NULL;
01251 const char *gen_address = NULL;
01252 const char *gen_digits = NULL;
01253 const char *gen_dig_type = NULL;
01254 const char *gen_dig_scheme = NULL;
01255 const char *gen_name = NULL;
01256 const char *jip_digits = NULL;
01257 const char *lspi_ident = NULL;
01258 const char *rlt_flag = NULL;
01259 const char *call_ref_id = NULL;
01260 const char *call_ref_pc = NULL;
01261 const char *send_far = NULL;
01262 char *c;
01263 char *l;
01264 char dest[256];
01265
01266 ast_copy_string(dest, rdest, sizeof(dest));
01267
01268 c = strchr(dest, '/');
01269 if (c) {
01270 c++;
01271 } else {
01272 c = "";
01273 }
01274 if (strlen(c) < p->stripmsd) {
01275 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01276 return -1;
01277 }
01278
01279 if (!p->hidecallerid) {
01280 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
01281 } else {
01282 l = NULL;
01283 }
01284
01285 if (ss7_grab(p, p->ss7)) {
01286 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
01287 return -1;
01288 }
01289
01290 p->ss7call = isup_new_call(p->ss7->ss7);
01291 if (!p->ss7call) {
01292 ss7_rel(p->ss7);
01293 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
01294 return -1;
01295 }
01296
01297 called_nai_strip = 0;
01298 ss7_called_nai = p->ss7->called_nai;
01299 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
01300 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
01301 called_nai_strip = strlen(p->ss7->internationalprefix);
01302 ss7_called_nai = SS7_NAI_INTERNATIONAL;
01303 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
01304 called_nai_strip = strlen(p->ss7->nationalprefix);
01305 ss7_called_nai = SS7_NAI_NATIONAL;
01306 } else {
01307 ss7_called_nai = SS7_NAI_SUBSCRIBER;
01308 }
01309 }
01310 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
01311
01312 calling_nai_strip = 0;
01313 ss7_calling_nai = p->ss7->calling_nai;
01314 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
01315 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
01316 calling_nai_strip = strlen(p->ss7->internationalprefix);
01317 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
01318 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
01319 calling_nai_strip = strlen(p->ss7->nationalprefix);
01320 ss7_calling_nai = SS7_NAI_NATIONAL;
01321 } else {
01322 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
01323 }
01324 }
01325 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
01326 p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number.presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
01327 p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number.presentation) : SS7_SCREENING_USER_PROVIDED);
01328
01329 isup_set_oli(p->ss7call, ast->connected.ani2);
01330 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
01331
01332
01333 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
01334 if (charge_str)
01335 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
01336
01337 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
01338 if (gen_address)
01339 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);
01340
01341 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
01342 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
01343 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
01344 if (gen_digits)
01345 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
01346
01347 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
01348 if (gen_name)
01349 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
01350
01351 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
01352 if (jip_digits)
01353 isup_set_jip_digits(p->ss7call, jip_digits);
01354
01355 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
01356 if (lspi_ident)
01357 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
01358
01359 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
01360 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
01361 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
01362 }
01363
01364 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
01365 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
01366 if (call_ref_id && call_ref_pc) {
01367 isup_set_callref(p->ss7call, atoi(call_ref_id),
01368 call_ref_pc ? atoi(call_ref_pc) : 0);
01369 }
01370
01371 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
01372 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
01373 (isup_far(p->ss7->ss7, p->ss7call));
01374
01375 p->call_level = SIG_SS7_CALL_LEVEL_SETUP;
01376 isup_iam(p->ss7->ss7, p->ss7call);
01377 sig_ss7_set_dialing(p, 1);
01378 ast_setstate(ast, AST_STATE_DIALING);
01379 ss7_rel(p->ss7);
01380 return 0;
01381 }
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
01394 {
01395 int res = 0;
01396
01397 if (!ast->tech_pvt) {
01398 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
01399 return 0;
01400 }
01401
01402 p->owner = NULL;
01403 sig_ss7_set_dialing(p, 0);
01404 p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
01405 p->outgoing = 0;
01406 p->progress = 0;
01407 p->rlt = 0;
01408 p->exten[0] = '\0';
01409
01410 if (p->ss7call) {
01411 if (!ss7_grab(p, p->ss7)) {
01412 if (!p->alreadyhungup) {
01413 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
01414 int icause = ast->hangupcause ? ast->hangupcause : -1;
01415
01416 if (cause) {
01417 if (atoi(cause))
01418 icause = atoi(cause);
01419 }
01420 isup_rel(p->ss7->ss7, p->ss7call, icause);
01421 ss7_rel(p->ss7);
01422 p->alreadyhungup = 1;
01423 } else
01424 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
01425 } else {
01426 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
01427 res = -1;
01428 }
01429 }
01430
01431 return res;
01432 }
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444 int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
01445 {
01446 int res;
01447
01448 if (!ss7_grab(p, p->ss7)) {
01449 if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
01450 p->call_level = SIG_SS7_CALL_LEVEL_CONNECT;
01451 }
01452 res = isup_anm(p->ss7->ss7, p->ss7call);
01453 ss7_rel(p->ss7);
01454 } else {
01455 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->ss7->span);
01456 res = -1;
01457 }
01458 return res;
01459 }
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471 void sig_ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan)
01472 {
01473 if (pchan->owner == oldchan) {
01474 pchan->owner = newchan;
01475 }
01476 }
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491 int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
01492 {
01493 int res = -1;
01494
01495 switch (condition) {
01496 case AST_CONTROL_BUSY:
01497 res = sig_ss7_play_tone(p, SIG_SS7_TONE_BUSY);
01498 break;
01499 case AST_CONTROL_RINGING:
01500 if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING && !p->outgoing) {
01501 p->call_level = SIG_SS7_CALL_LEVEL_ALERTING;
01502 if (p->ss7 && p->ss7->ss7) {
01503 ss7_grab(p, p->ss7);
01504 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
01505 p->rlt = 1;
01506 if (p->rlt != 1)
01507 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
01508 ss7_rel(p->ss7);
01509 }
01510 }
01511
01512 res = sig_ss7_play_tone(p, SIG_SS7_TONE_RINGTONE);
01513
01514 if (chan->_state != AST_STATE_UP && chan->_state != AST_STATE_RING) {
01515 ast_setstate(chan, AST_STATE_RINGING);
01516 }
01517 break;
01518 case AST_CONTROL_PROCEEDING:
01519 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
01520
01521 if (chan->_state == AST_STATE_UP && (p->rlt != 1)){
01522 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
01523 p->rlt = 1;
01524 }
01525
01526 if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING && !p->outgoing) {
01527 p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING;
01528 if (p->ss7 && p->ss7->ss7) {
01529 ss7_grab(p, p->ss7);
01530 isup_acm(p->ss7->ss7, p->ss7call);
01531 ss7_rel(p->ss7);
01532 }
01533 }
01534
01535 res = 0;
01536 break;
01537 case AST_CONTROL_PROGRESS:
01538 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
01539 if (!p->progress && p->call_level < SIG_SS7_CALL_LEVEL_ALERTING && !p->outgoing) {
01540 p->progress = 1;
01541 if (p->ss7 && p->ss7->ss7) {
01542 ss7_grab(p, p->ss7);
01543 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
01544 ss7_rel(p->ss7);
01545
01546 sig_ss7_set_echocanceller(p, 1);
01547 }
01548 }
01549
01550 res = 0;
01551 break;
01552 case AST_CONTROL_CONGESTION:
01553 chan->hangupcause = AST_CAUSE_CONGESTION;
01554 break;
01555 case AST_CONTROL_HOLD:
01556 ast_moh_start(chan, data, p->mohinterpret);
01557 break;
01558 case AST_CONTROL_UNHOLD:
01559 ast_moh_stop(chan);
01560 break;
01561 case AST_CONTROL_SRCUPDATE:
01562 res = 0;
01563 break;
01564 case -1:
01565 res = sig_ss7_play_tone(p, -1);
01566 break;
01567 }
01568 return res;
01569 }
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583 struct ast_channel *sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_channel *requestor, int transfercapability)
01584 {
01585 struct ast_channel *ast;
01586
01587 p->outgoing = 1;
01588 ast = sig_ss7_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor);
01589 if (!ast) {
01590 p->outgoing = 0;
01591 }
01592 return ast;
01593 }
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
01604 {
01605 ast_free(doomed);
01606 }
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619 struct sig_ss7_chan *sig_ss7_chan_new(void *pvt_data, struct sig_ss7_callback *callback, struct sig_ss7_linkset *ss7)
01620 {
01621 struct sig_ss7_chan *pvt;
01622
01623 pvt = ast_calloc(1, sizeof(*pvt));
01624 if (!pvt) {
01625 return pvt;
01626 }
01627
01628 pvt->calls = callback;
01629 pvt->chan_pvt = pvt_data;
01630 pvt->ss7 = ss7;
01631
01632 return pvt;
01633 }
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643 void sig_ss7_init_linkset(struct sig_ss7_linkset *ss7)
01644 {
01645 int idx;
01646
01647 memset(ss7, 0, sizeof(*ss7));
01648
01649 ast_mutex_init(&ss7->lock);
01650
01651 ss7->master = AST_PTHREADT_NULL;
01652 for (idx = 0; idx < ARRAY_LEN(ss7->fds); ++idx) {
01653 ss7->fds[idx] = -1;
01654 }
01655 }
01656
01657
01658
01659 #endif
01660