#include "asterisk/channel.h"
#include <libss7.h>
Go to the source code of this file.
Data Structures | |
struct | sig_ss7_callback |
struct | sig_ss7_chan |
struct | sig_ss7_linkset |
Defines | |
#define | LINKSET_FLAG_EXPLICITACM (1 << 0) |
#define | LINKSTATE_DOWN (1 << 3) |
#define | LINKSTATE_INALARM (1 << 0) |
#define | LINKSTATE_STARTING (1 << 1) |
#define | LINKSTATE_UP (1 << 2) |
#define | SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
#define | SIG_SS7_DEBUG (SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP) |
#define | SIG_SS7_DEBUG_DEFAULT 0 |
#define | SIG_SS7_MAX_CHANNELS 672 |
#define | SIG_SS7_NUM_DCHANS 4 |
#define | SS7_NAI_DYNAMIC -1 |
Enumerations | |
enum | sig_ss7_call_level { SIG_SS7_CALL_LEVEL_IDLE, SIG_SS7_CALL_LEVEL_ALLOCATED, SIG_SS7_CALL_LEVEL_CONTINUITY, SIG_SS7_CALL_LEVEL_SETUP, SIG_SS7_CALL_LEVEL_PROCEEDING, SIG_SS7_CALL_LEVEL_ALERTING, SIG_SS7_CALL_LEVEL_CONNECT, SIG_SS7_CALL_LEVEL_GLARE } |
enum | sig_ss7_law { SIG_SS7_DEFLAW = 0, SIG_SS7_ULAW, SIG_SS7_ALAW } |
enum | sig_ss7_tone { SIG_SS7_TONE_RINGTONE = 0, SIG_SS7_TONE_STUTTER, SIG_SS7_TONE_CONGESTION, SIG_SS7_TONE_DIALTONE, SIG_SS7_TONE_DIALRECALL, SIG_SS7_TONE_INFO, SIG_SS7_TONE_BUSY } |
Functions | |
int | sig_ss7_add_sigchan (struct sig_ss7_linkset *linkset, int which, int ss7type, int transport, int inalarm, int networkindicator, int pointcode, int adjpointcode) |
Setup and add a SS7 link channel. | |
int | sig_ss7_answer (struct sig_ss7_chan *p, struct ast_channel *ast) |
SS7 answer channel. | |
int | sig_ss7_available (struct sig_ss7_chan *p) |
Determine if the specified channel is available for an outgoing call. | |
int | sig_ss7_call (struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest) |
Dial out using the specified SS7 channel. | |
void | sig_ss7_chan_delete (struct sig_ss7_chan *doomed) |
Delete the sig_ss7 private channel structure. | |
sig_ss7_chan * | sig_ss7_chan_new (void *pvt_data, struct sig_ss7_callback *callback, struct sig_ss7_linkset *ss7) |
Create a new sig_ss7 private channel structure. | |
void | sig_ss7_cli_show_channels (int fd, struct sig_ss7_linkset *linkset) |
void | sig_ss7_cli_show_channels_header (int fd) |
void | sig_ss7_fixup (struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan) |
Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links. | |
int | sig_ss7_hangup (struct sig_ss7_chan *p, struct ast_channel *ast) |
SS7 hangup channel. | |
int | sig_ss7_indicate (struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen) |
SS7 answer channel. | |
void | sig_ss7_init_linkset (struct sig_ss7_linkset *ss7) |
Initialize the SS7 linkset control. | |
void | sig_ss7_link_alarm (struct sig_ss7_linkset *linkset, int which) |
Notify the SS7 layer that the link is in alarm. | |
void | sig_ss7_link_noalarm (struct sig_ss7_linkset *linkset, int which) |
Notify the SS7 layer that the link is no longer in alarm. | |
ast_channel * | sig_ss7_request (struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_channel *requestor, int transfercapability) |
SS7 channel request. | |
void | sig_ss7_set_alarm (struct sig_ss7_chan *p, int in_alarm) |
void * | ss7_linkset (void *data) |
Richard Mudgett <rmudgett@digium.com>
Definition in file sig_ss7.h.
#define LINKSET_FLAG_EXPLICITACM (1 << 0) |
#define LINKSTATE_DOWN (1 << 3) |
Definition at line 64 of file sig_ss7.h.
Referenced by sig_ss7_add_sigchan(), sig_ss7_link_alarm(), and sig_ss7_link_noalarm().
#define LINKSTATE_INALARM (1 << 0) |
Definition at line 61 of file sig_ss7.h.
Referenced by sig_ss7_add_sigchan(), sig_ss7_link_alarm(), and sig_ss7_link_noalarm().
#define LINKSTATE_STARTING (1 << 1) |
#define LINKSTATE_UP (1 << 2) |
#define SIG_SS7_DEBUG (SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP) |
SS7 debug message flags when SS7 debugging is turned on at the command line.
Definition at line 43 of file sig_ss7.h.
Referenced by handle_ss7_debug().
#define SIG_SS7_DEBUG_DEFAULT 0 |
SS7 debug message flags set on initial startup.
Definition at line 51 of file sig_ss7.h.
Referenced by ss7_linkset().
#define SIG_SS7_MAX_CHANNELS 672 |
#define SS7_NAI_DYNAMIC -1 |
enum sig_ss7_call_level |
Call establishment life cycle level for simple comparisons.
Definition at line 88 of file sig_ss7.h.
00088 { 00089 /*! Call does not exist. */ 00090 SIG_SS7_CALL_LEVEL_IDLE, 00091 /*! 00092 * Call is allocated to the channel. 00093 * We have not sent or responded to IAM yet. 00094 */ 00095 SIG_SS7_CALL_LEVEL_ALLOCATED, 00096 /*! 00097 * Call is performing continuity check after receiving IAM. 00098 * We are waiting for COT to proceed further. 00099 */ 00100 SIG_SS7_CALL_LEVEL_CONTINUITY, 00101 /*! 00102 * Call is present. 00103 * We have not seen a response or sent further call progress to an IAM yet. 00104 */ 00105 SIG_SS7_CALL_LEVEL_SETUP, 00106 /*! 00107 * Call routing is happening. 00108 * We have sent or received ACM. 00109 */ 00110 SIG_SS7_CALL_LEVEL_PROCEEDING, 00111 /*! 00112 * Called party is being alerted of the call. 00113 * We have sent or received CPG(ALERTING)/ACM(ALERTING). 00114 */ 00115 SIG_SS7_CALL_LEVEL_ALERTING, 00116 /*! 00117 * Call is connected/answered. 00118 * We have sent or received CON/ANM. 00119 */ 00120 SIG_SS7_CALL_LEVEL_CONNECT, 00121 /*! Call has collided with incoming call. */ 00122 SIG_SS7_CALL_LEVEL_GLARE, 00123 };
enum sig_ss7_law |
Definition at line 81 of file sig_ss7.h.
00081 { 00082 SIG_SS7_DEFLAW = 0, 00083 SIG_SS7_ULAW, 00084 SIG_SS7_ALAW 00085 };
enum sig_ss7_tone |
SIG_SS7_TONE_RINGTONE | |
SIG_SS7_TONE_STUTTER | |
SIG_SS7_TONE_CONGESTION | |
SIG_SS7_TONE_DIALTONE | |
SIG_SS7_TONE_DIALRECALL | |
SIG_SS7_TONE_INFO | |
SIG_SS7_TONE_BUSY |
Definition at line 71 of file sig_ss7.h.
00071 { 00072 SIG_SS7_TONE_RINGTONE = 0, 00073 SIG_SS7_TONE_STUTTER, 00074 SIG_SS7_TONE_CONGESTION, 00075 SIG_SS7_TONE_DIALTONE, 00076 SIG_SS7_TONE_DIALRECALL, 00077 SIG_SS7_TONE_INFO, 00078 SIG_SS7_TONE_BUSY, 00079 };
int sig_ss7_add_sigchan | ( | struct sig_ss7_linkset * | linkset, | |
int | which, | |||
int | ss7type, | |||
int | transport, | |||
int | inalarm, | |||
int | networkindicator, | |||
int | pointcode, | |||
int | adjpointcode | |||
) |
Setup and add a SS7 link channel.
linkset | Controlling linkset for the channel. | |
which | Link index of the signaling channel. | |
ss7type | Switch type of the linkset | |
transport | Signaling transport of channel. | |
inalarm | Non-zero if the channel is in alarm. | |
networkindicator | User configuration parameter. | |
pointcode | User configuration parameter. | |
adjpointcode | User configuration parameter. |
0 | on success. | |
-1 | on error. |
Definition at line 1302 of file sig_ss7.c.
References ast_log(), sig_ss7_linkset::fds, sig_ss7_linkset::linkstate, LINKSTATE_DOWN, LINKSTATE_INALARM, LOG_ERROR, LOG_WARNING, sig_ss7_linkset::ss7, and sig_ss7_linkset::type.
Referenced by linkset_addsigchan().
01303 { 01304 if (!linkset->ss7) { 01305 linkset->type = ss7type; 01306 linkset->ss7 = ss7_new(ss7type); 01307 if (!linkset->ss7) { 01308 ast_log(LOG_ERROR, "Can't create new SS7!\n"); 01309 return -1; 01310 } 01311 } 01312 01313 ss7_set_network_ind(linkset->ss7, networkindicator); 01314 ss7_set_pc(linkset->ss7, pointcode); 01315 01316 if (ss7_add_link(linkset->ss7, transport, linkset->fds[which])) { 01317 ast_log(LOG_WARNING, "Could not add SS7 link!\n"); 01318 } 01319 01320 if (inalarm) { 01321 linkset->linkstate[which] = LINKSTATE_DOWN | LINKSTATE_INALARM; 01322 ss7_link_alarm(linkset->ss7, linkset->fds[which]); 01323 } else { 01324 linkset->linkstate[which] = LINKSTATE_DOWN; 01325 ss7_link_noalarm(linkset->ss7, linkset->fds[which]); 01326 } 01327 01328 ss7_set_adjpc(linkset->ss7, linkset->fds[which], adjpointcode); 01329 01330 return 0; 01331 }
int sig_ss7_answer | ( | struct sig_ss7_chan * | p, | |
struct ast_channel * | ast | |||
) |
SS7 answer channel.
p | Signaling private structure pointer. | |
ast | Asterisk channel structure pointer. |
0 | on success. | |
-1 | on error. |
Definition at line 1599 of file sig_ss7.c.
References sig_ss7_chan::call_level, SIG_SS7_CALL_LEVEL_CONNECT, sig_ss7_linkset::ss7, sig_ss7_chan::ss7, ss7_grab(), ss7_rel(), and sig_ss7_chan::ss7call.
Referenced by dahdi_answer().
01600 { 01601 int res; 01602 01603 ss7_grab(p, p->ss7); 01604 if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) { 01605 p->call_level = SIG_SS7_CALL_LEVEL_CONNECT; 01606 } 01607 res = isup_anm(p->ss7->ss7, p->ss7call); 01608 ss7_rel(p->ss7); 01609 return res; 01610 }
int sig_ss7_available | ( | struct sig_ss7_chan * | p | ) |
Determine if the specified channel is available for an outgoing call.
p | Signaling private structure pointer. |
TRUE | if the channel is available. |
Definition at line 1359 of file sig_ss7.c.
References ast_mutex_lock, ast_mutex_unlock, available(), sig_ss7_chan::call_level, sig_ss7_linkset::lock, SIG_SS7_CALL_LEVEL_ALLOCATED, sig_ss7_is_chan_available(), and sig_ss7_chan::ss7.
Referenced by available().
01360 { 01361 int available; 01362 01363 if (!p->ss7) { 01364 /* Something is wrong here. A SS7 channel without the ss7 pointer? */ 01365 return 0; 01366 } 01367 01368 /* Only have to deal with the linkset lock. */ 01369 ast_mutex_lock(&p->ss7->lock); 01370 available = sig_ss7_is_chan_available(p); 01371 if (available) { 01372 p->call_level = SIG_SS7_CALL_LEVEL_ALLOCATED; 01373 } 01374 ast_mutex_unlock(&p->ss7->lock); 01375 01376 return available; 01377 }
int sig_ss7_call | ( | struct sig_ss7_chan * | p, | |
struct ast_channel * | ast, | |||
char * | rdest | |||
) |
Dial out using the specified SS7 channel.
p | Signaling private structure pointer. | |
ast | Asterisk channel structure pointer. | |
rdest | Dialstring. |
0 | on success. | |
-1 | on error. |
Definition at line 1400 of file sig_ss7.c.
References ast_party_connected_line::ani2, ast_copy_string(), ast_log(), ast_setstate(), AST_STATE_DIALING, sig_ss7_chan::call_level, sig_ss7_linkset::called_nai, sig_ss7_linkset::calling_nai, sig_ss7_chan::cic, cid_pres2ss7pres(), cid_pres2ss7screen(), ast_channel::connected, sig_ss7_chan::dpc, sig_ss7_chan::gen_add_nai, sig_ss7_chan::gen_add_num_plan, sig_ss7_chan::gen_add_pres_ind, sig_ss7_chan::gen_add_type, sig_ss7_chan::hidecallerid, ast_party_connected_line::id, sig_ss7_linkset::internationalprefix, LOG_ERROR, LOG_WARNING, sig_ss7_linkset::nationalprefix, ast_party_id::number, pbx_builtin_getvar_helper(), ast_party_number::presentation, SIG_SS7_CALL_LEVEL_ALLOCATED, SIG_SS7_CALL_LEVEL_SETUP, sig_ss7_set_dialing(), sig_ss7_linkset::ss7, sig_ss7_chan::ss7, ss7_grab(), SS7_NAI_DYNAMIC, ss7_rel(), sig_ss7_chan::ss7call, ast_party_number::str, sig_ss7_chan::stripmsd, sig_ss7_chan::use_callingpres, and ast_party_number::valid.
Referenced by dahdi_call().
01401 { 01402 char ss7_called_nai; 01403 int called_nai_strip; 01404 char ss7_calling_nai; 01405 int calling_nai_strip; 01406 const char *charge_str = NULL; 01407 const char *gen_address = NULL; 01408 const char *gen_digits = NULL; 01409 const char *gen_dig_type = NULL; 01410 const char *gen_dig_scheme = NULL; 01411 const char *gen_name = NULL; 01412 const char *jip_digits = NULL; 01413 const char *lspi_ident = NULL; 01414 const char *rlt_flag = NULL; 01415 const char *call_ref_id = NULL; 01416 const char *call_ref_pc = NULL; 01417 const char *send_far = NULL; 01418 char *c; 01419 char *l; 01420 char dest[256]; 01421 01422 ast_copy_string(dest, rdest, sizeof(dest)); 01423 01424 c = strchr(dest, '/'); 01425 if (c) { 01426 c++; 01427 } else { 01428 c = ""; 01429 } 01430 if (strlen(c) < p->stripmsd) { 01431 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 01432 return -1; 01433 } 01434 01435 if (!p->hidecallerid) { 01436 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL; 01437 } else { 01438 l = NULL; 01439 } 01440 01441 ss7_grab(p, p->ss7); 01442 01443 if (p->call_level != SIG_SS7_CALL_LEVEL_ALLOCATED) { 01444 /* Call collision before sending IAM. Abort call. */ 01445 ss7_rel(p->ss7); 01446 return -1; 01447 } 01448 01449 p->ss7call = isup_new_call(p->ss7->ss7); 01450 if (!p->ss7call) { 01451 ss7_rel(p->ss7); 01452 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n"); 01453 return -1; 01454 } 01455 01456 called_nai_strip = 0; 01457 ss7_called_nai = p->ss7->called_nai; 01458 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */ 01459 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 01460 called_nai_strip = strlen(p->ss7->internationalprefix); 01461 ss7_called_nai = SS7_NAI_INTERNATIONAL; 01462 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 01463 called_nai_strip = strlen(p->ss7->nationalprefix); 01464 ss7_called_nai = SS7_NAI_NATIONAL; 01465 } else { 01466 ss7_called_nai = SS7_NAI_SUBSCRIBER; 01467 } 01468 } 01469 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7); 01470 01471 calling_nai_strip = 0; 01472 ss7_calling_nai = p->ss7->calling_nai; 01473 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */ 01474 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 01475 calling_nai_strip = strlen(p->ss7->internationalprefix); 01476 ss7_calling_nai = SS7_NAI_INTERNATIONAL; 01477 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 01478 calling_nai_strip = strlen(p->ss7->nationalprefix); 01479 ss7_calling_nai = SS7_NAI_NATIONAL; 01480 } else { 01481 ss7_calling_nai = SS7_NAI_SUBSCRIBER; 01482 } 01483 } 01484 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai, 01485 p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number.presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED), 01486 p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number.presentation) : SS7_SCREENING_USER_PROVIDED); 01487 01488 isup_set_oli(p->ss7call, ast->connected.ani2); 01489 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc); 01490 01491 /* Set the charge number if it is set */ 01492 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER"); 01493 if (charge_str) 01494 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10); 01495 01496 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS"); 01497 if (gen_address) 01498 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); /* need to add some types here for NAI,PRES,TYPE */ 01499 01500 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS"); 01501 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE"); 01502 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME"); 01503 if (gen_digits) 01504 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 01505 01506 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME"); 01507 if (gen_name) 01508 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED); 01509 01510 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP"); 01511 if (jip_digits) 01512 isup_set_jip_digits(p->ss7call, jip_digits); 01513 01514 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT"); 01515 if (lspi_ident) 01516 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 01517 01518 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON"); 01519 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) { 01520 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */ 01521 } 01522 01523 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT"); 01524 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC"); 01525 if (call_ref_id && call_ref_pc) { 01526 isup_set_callref(p->ss7call, atoi(call_ref_id), 01527 call_ref_pc ? atoi(call_ref_pc) : 0); 01528 } 01529 01530 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR"); 01531 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 )) 01532 (isup_far(p->ss7->ss7, p->ss7call)); 01533 01534 p->call_level = SIG_SS7_CALL_LEVEL_SETUP; 01535 isup_iam(p->ss7->ss7, p->ss7call); 01536 sig_ss7_set_dialing(p, 1); 01537 ast_setstate(ast, AST_STATE_DIALING); 01538 ss7_rel(p->ss7); 01539 return 0; 01540 }
void sig_ss7_chan_delete | ( | struct sig_ss7_chan * | doomed | ) |
Delete the sig_ss7 private channel structure.
doomed | sig_ss7 private channel structure to delete. |
Definition at line 1769 of file sig_ss7.c.
References ast_free.
Referenced by destroy_dahdi_pvt().
01770 { 01771 ast_free(doomed); 01772 }
struct sig_ss7_chan* sig_ss7_chan_new | ( | void * | pvt_data, | |
struct sig_ss7_callback * | callback, | |||
struct sig_ss7_linkset * | ss7 | |||
) |
Create a new sig_ss7 private channel structure.
pvt_data | Upper layer private data structure. | |
callback | Callbacks to the upper layer. | |
ss7 | Controlling linkset for the channel. |
sig_ss7_chan | on success. | |
NULL | on error. |
Definition at line 1830 of file sig_ss7.c.
References ast_calloc, and sig_ss7_chan::ss7.
01831 { 01832 struct sig_ss7_chan *pvt; 01833 01834 pvt = ast_calloc(1, sizeof(*pvt)); 01835 if (!pvt) { 01836 return pvt; 01837 } 01838 01839 pvt->calls = callback; 01840 pvt->chan_pvt = pvt_data; 01841 pvt->ss7 = ss7; 01842 01843 return pvt; 01844 }
void sig_ss7_cli_show_channels | ( | int | fd, | |
struct sig_ss7_linkset * | linkset | |||
) |
Definition at line 1782 of file sig_ss7.c.
References ast_channel_unlock, ast_cli(), ast_mutex_lock, ast_mutex_unlock, sig_ss7_chan::call_level, sig_ss7_chan::channel, sig_ss7_chan::locallyblocked, sig_ss7_linkset::lock, ast_channel::name, sig_ss7_linkset::numchans, sig_ss7_chan::owner, sig_ss7_linkset::pvts, sig_ss7_chan::remotelyblocked, sig_ss7_call_level2str(), sig_ss7_is_chan_available(), sig_ss7_lock_owner(), sig_ss7_lock_private(), SIG_SS7_SC_LINE, sig_ss7_unlock_private(), sig_ss7_linkset::span, and sig_ss7_chan::ss7call.
Referenced by handle_ss7_show_channels().
01783 { 01784 char line[256]; 01785 int idx; 01786 struct sig_ss7_chan *pvt; 01787 01788 ast_mutex_lock(&linkset->lock); 01789 for (idx = 0; idx < linkset->numchans; ++idx) { 01790 if (!linkset->pvts[idx]) { 01791 continue; 01792 } 01793 pvt = linkset->pvts[idx]; 01794 sig_ss7_lock_private(pvt); 01795 sig_ss7_lock_owner(linkset, idx); 01796 01797 snprintf(line, sizeof(line), SIG_SS7_SC_LINE, 01798 linkset->span, 01799 pvt->channel, 01800 sig_ss7_is_chan_available(pvt) ? "Yes" : "No", 01801 pvt->locallyblocked ? "Yes" : "No", 01802 pvt->remotelyblocked ? "Yes" : "No", 01803 sig_ss7_call_level2str(pvt->call_level), 01804 pvt->ss7call ? "Yes" : "No", 01805 pvt->owner ? pvt->owner->name : ""); 01806 01807 if (pvt->owner) { 01808 ast_channel_unlock(pvt->owner); 01809 } 01810 sig_ss7_unlock_private(pvt); 01811 01812 ast_mutex_unlock(&linkset->lock); 01813 ast_cli(fd, "%s\n", line); 01814 ast_mutex_lock(&linkset->lock); 01815 } 01816 ast_mutex_unlock(&linkset->lock); 01817 }
void sig_ss7_cli_show_channels_header | ( | int | fd | ) |
Definition at line 1776 of file sig_ss7.c.
References ast_cli(), and SIG_SS7_SC_HEADER.
Referenced by handle_ss7_show_channels().
01777 { 01778 ast_cli(fd, SIG_SS7_SC_HEADER, "link", "", "Chan", "Lcl", "Rem", "Call", "SS7", "Channel"); 01779 ast_cli(fd, SIG_SS7_SC_HEADER, "set", "Chan", "Idle", "Blk", "Blk", "Level", "Call", "Name"); 01780 }
void sig_ss7_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan, | |||
struct sig_ss7_chan * | pchan | |||
) |
Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links.
oldchan | Old channel pointer to replace. | |
newchan | New channel pointer to set. | |
pchan | Signaling private structure pointer. |
Definition at line 1622 of file sig_ss7.c.
References sig_ss7_chan::owner.
int sig_ss7_hangup | ( | struct sig_ss7_chan * | p, | |
struct ast_channel * | ast | |||
) |
SS7 hangup channel.
p | Signaling private structure pointer. | |
ast | Asterisk channel structure pointer. |
0 | on success. | |
-1 | on error. |
Definition at line 1552 of file sig_ss7.c.
References sig_ss7_chan::alreadyhungup, ast_log(), sig_ss7_chan::call_level, cause, sig_ss7_chan::exten, ast_channel::hangupcause, LOG_WARNING, sig_ss7_chan::outgoing, sig_ss7_chan::owner, pbx_builtin_getvar_helper(), sig_ss7_chan::progress, sig_ss7_chan::rlt, SIG_SS7_CALL_LEVEL_IDLE, sig_ss7_set_dialing(), sig_ss7_linkset::ss7, sig_ss7_chan::ss7, ss7_grab(), ss7_rel(), sig_ss7_chan::ss7call, and ast_channel::tech_pvt.
Referenced by dahdi_hangup().
01553 { 01554 int res = 0; 01555 01556 if (!ast->tech_pvt) { 01557 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 01558 return 0; 01559 } 01560 01561 p->owner = NULL; 01562 sig_ss7_set_dialing(p, 0); 01563 p->outgoing = 0; 01564 p->progress = 0; 01565 p->rlt = 0; 01566 p->exten[0] = '\0'; 01567 /* Perform low level hangup if no owner left */ 01568 ss7_grab(p, p->ss7); 01569 p->call_level = SIG_SS7_CALL_LEVEL_IDLE; 01570 if (p->ss7call) { 01571 if (!p->alreadyhungup) { 01572 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE"); 01573 int icause = ast->hangupcause ? ast->hangupcause : -1; 01574 01575 if (cause) { 01576 if (atoi(cause)) { 01577 icause = atoi(cause); 01578 } 01579 } 01580 isup_rel(p->ss7->ss7, p->ss7call, icause); 01581 p->alreadyhungup = 1; 01582 } 01583 } 01584 ss7_rel(p->ss7); 01585 01586 return res; 01587 }
int sig_ss7_indicate | ( | struct sig_ss7_chan * | p, | |
struct ast_channel * | chan, | |||
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) |
SS7 answer channel.
p | Signaling private structure pointer. | |
chan | Asterisk channel structure pointer. | |
condition | AST control frame subtype. | |
data | AST control frame payload contents. | |
datalen | Length of payload contents. |
0 | on success. | |
-1 | on error or indication condition not handled. |
Definition at line 1642 of file sig_ss7.c.
References ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_moh_start(), ast_moh_stop(), ast_setstate(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, sig_ss7_chan::call_level, ast_channel::hangupcause, sig_ss7_chan::mohinterpret, ast_channel::name, sig_ss7_chan::outgoing, sig_ss7_chan::progress, sig_ss7_chan::rlt, SIG_SS7_CALL_LEVEL_ALERTING, SIG_SS7_CALL_LEVEL_CONNECT, SIG_SS7_CALL_LEVEL_PROCEEDING, sig_ss7_play_tone(), sig_ss7_set_echocanceller(), SIG_SS7_TONE_BUSY, SIG_SS7_TONE_RINGTONE, sig_ss7_linkset::ss7, sig_ss7_chan::ss7, ss7_grab(), ss7_rel(), and sig_ss7_chan::ss7call.
Referenced by dahdi_indicate().
01643 { 01644 int res = -1; 01645 01646 switch (condition) { 01647 case AST_CONTROL_BUSY: 01648 res = sig_ss7_play_tone(p, SIG_SS7_TONE_BUSY); 01649 break; 01650 case AST_CONTROL_RINGING: 01651 ss7_grab(p, p->ss7); 01652 if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING && !p->outgoing) { 01653 p->call_level = SIG_SS7_CALL_LEVEL_ALERTING; 01654 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) { 01655 p->rlt = 1; 01656 } 01657 01658 /* No need to send CPG if call will be RELEASE */ 01659 if (p->rlt != 1) { 01660 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING); 01661 } 01662 } 01663 ss7_rel(p->ss7); 01664 01665 res = sig_ss7_play_tone(p, SIG_SS7_TONE_RINGTONE); 01666 01667 if (chan->_state != AST_STATE_UP && chan->_state != AST_STATE_RING) { 01668 ast_setstate(chan, AST_STATE_RINGING); 01669 } 01670 break; 01671 case AST_CONTROL_PROCEEDING: 01672 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 01673 ss7_grab(p, p->ss7); 01674 /* This IF sends the FAR for an answered ALEG call */ 01675 if (chan->_state == AST_STATE_UP && (p->rlt != 1)){ 01676 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) { 01677 p->rlt = 1; 01678 } 01679 } 01680 01681 if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING && !p->outgoing) { 01682 p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING; 01683 isup_acm(p->ss7->ss7, p->ss7call); 01684 } 01685 ss7_rel(p->ss7); 01686 /* don't continue in ast_indicate */ 01687 res = 0; 01688 break; 01689 case AST_CONTROL_PROGRESS: 01690 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 01691 ss7_grab(p, p->ss7); 01692 if (!p->progress && p->call_level < SIG_SS7_CALL_LEVEL_ALERTING && !p->outgoing) { 01693 p->progress = 1;/* No need to send inband-information progress again. */ 01694 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO); 01695 ss7_rel(p->ss7); 01696 01697 /* enable echo canceler here on SS7 calls */ 01698 sig_ss7_set_echocanceller(p, 1); 01699 } else { 01700 ss7_rel(p->ss7); 01701 } 01702 /* don't continue in ast_indicate */ 01703 res = 0; 01704 break; 01705 case AST_CONTROL_INCOMPLETE: 01706 /* If the channel is connected, wait for additional input */ 01707 if (p->call_level == SIG_SS7_CALL_LEVEL_CONNECT) { 01708 res = 0; 01709 break; 01710 } 01711 chan->hangupcause = AST_CAUSE_INVALID_NUMBER_FORMAT; 01712 break; 01713 case AST_CONTROL_CONGESTION: 01714 chan->hangupcause = AST_CAUSE_CONGESTION; 01715 break; 01716 case AST_CONTROL_HOLD: 01717 ast_moh_start(chan, data, p->mohinterpret); 01718 break; 01719 case AST_CONTROL_UNHOLD: 01720 ast_moh_stop(chan); 01721 break; 01722 case AST_CONTROL_SRCUPDATE: 01723 res = 0; 01724 break; 01725 case -1: 01726 res = sig_ss7_play_tone(p, -1); 01727 break; 01728 } 01729 return res; 01730 }
void sig_ss7_init_linkset | ( | struct sig_ss7_linkset * | ss7 | ) |
Initialize the SS7 linkset control.
ss7 | SS7 linkset control structure. |
Definition at line 1854 of file sig_ss7.c.
References ARRAY_LEN, ast_mutex_init, AST_PTHREADT_NULL, and sig_ss7_chan::ss7.
Referenced by load_module().
01855 { 01856 int idx; 01857 01858 memset(ss7, 0, sizeof(*ss7)); 01859 01860 ast_mutex_init(&ss7->lock); 01861 01862 ss7->master = AST_PTHREADT_NULL; 01863 for (idx = 0; idx < ARRAY_LEN(ss7->fds); ++idx) { 01864 ss7->fds[idx] = -1; 01865 } 01866 }
void sig_ss7_link_alarm | ( | struct sig_ss7_linkset * | linkset, | |
int | which | |||
) |
Notify the SS7 layer that the link is in alarm.
linkset | Controlling linkset for the channel. | |
which | Link index of the signaling channel. |
Definition at line 1263 of file sig_ss7.c.
References sig_ss7_linkset::fds, sig_ss7_linkset::linkstate, LINKSTATE_DOWN, LINKSTATE_INALARM, LINKSTATE_UP, and sig_ss7_linkset::ss7.
Referenced by my_handle_link_exception().
01264 { 01265 linkset->linkstate[which] |= (LINKSTATE_DOWN | LINKSTATE_INALARM); 01266 linkset->linkstate[which] &= ~LINKSTATE_UP; 01267 ss7_link_alarm(linkset->ss7, linkset->fds[which]); 01268 }
void sig_ss7_link_noalarm | ( | struct sig_ss7_linkset * | linkset, | |
int | which | |||
) |
Notify the SS7 layer that the link is no longer in alarm.
linkset | Controlling linkset for the channel. | |
which | Link index of the signaling channel. |
Definition at line 1279 of file sig_ss7.c.
References sig_ss7_linkset::fds, sig_ss7_linkset::linkstate, LINKSTATE_DOWN, LINKSTATE_INALARM, LINKSTATE_STARTING, and sig_ss7_linkset::ss7.
Referenced by my_handle_link_exception().
01280 { 01281 linkset->linkstate[which] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN); 01282 linkset->linkstate[which] |= LINKSTATE_STARTING; 01283 ss7_link_noalarm(linkset->ss7, linkset->fds[which]); 01284 }
struct ast_channel* sig_ss7_request | ( | struct sig_ss7_chan * | p, | |
enum sig_ss7_law | law, | |||
const struct ast_channel * | requestor, | |||
int | transfercapability | |||
) |
SS7 channel request.
p | Signaling private structure pointer. | |
law | Companding law preferred | |
requestor | Asterisk channel requesting a channel to dial (Can be NULL) | |
transfercapability |
ast_channel | on success. | |
NULL | on error. |
Definition at line 1744 of file sig_ss7.c.
References ast_mutex_lock, ast_mutex_unlock, AST_STATE_RESERVED, sig_ss7_chan::call_level, sig_ss7_chan::exten, sig_ss7_linkset::lock, sig_ss7_chan::outgoing, SIG_SS7_CALL_LEVEL_IDLE, sig_ss7_new_ast_channel(), and sig_ss7_chan::ss7.
Referenced by dahdi_request().
01745 { 01746 struct ast_channel *ast; 01747 01748 p->outgoing = 1; 01749 ast = sig_ss7_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor); 01750 if (!ast) { 01751 p->outgoing = 0; 01752 01753 /* Release the allocated channel. Only have to deal with the linkset lock. */ 01754 ast_mutex_lock(&p->ss7->lock); 01755 p->call_level = SIG_SS7_CALL_LEVEL_IDLE; 01756 ast_mutex_unlock(&p->ss7->lock); 01757 } 01758 return ast; 01759 }
void sig_ss7_set_alarm | ( | struct sig_ss7_chan * | p, | |
int | in_alarm | |||
) |
Definition at line 91 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, sig_ss7_chan::inalarm, and sig_ss7_callback::set_alarm.
Referenced by dahdi_handle_event(), and handle_init_event().
00092 { 00093 p->inalarm = in_alarm; 00094 if (p->calls->set_alarm) { 00095 p->calls->set_alarm(p->chan_pvt, in_alarm); 00096 } 00097 }
void* ss7_linkset | ( | void * | data | ) |
Definition at line 661 of file sig_ss7.c.
References ast_mutex_lock, ast_mutex_unlock, ast_tvnow(), sig_ss7_linkset::lock, SIG_SS7_DEBUG_DEFAULT, sig_ss7_linkset::ss7, and tv.
00662 { 00663 int res, i; 00664 struct timeval *next = NULL, tv; 00665 struct sig_ss7_linkset *linkset = (struct sig_ss7_linkset *) data; 00666 struct ss7 *ss7 = linkset->ss7; 00667 ss7_event *e = NULL; 00668 struct sig_ss7_chan *p; 00669 int chanpos; 00670 struct pollfd pollers[SIG_SS7_NUM_DCHANS]; 00671 int nextms = 0; 00672 00673 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 00674 00675 ss7_set_debug(ss7, SIG_SS7_DEBUG_DEFAULT); 00676 ast_mutex_lock(&linkset->lock); 00677 ss7_start(ss7); 00678 ast_mutex_unlock(&linkset->lock); 00679 00680 for (;;) { 00681 ast_mutex_lock(&linkset->lock); 00682 if ((next = ss7_schedule_next(ss7))) { 00683 tv = ast_tvnow(); 00684 tv.tv_sec = next->tv_sec - tv.tv_sec; 00685 tv.tv_usec = next->tv_usec - tv.tv_usec; 00686 if (tv.tv_usec < 0) { 00687 tv.tv_usec += 1000000; 00688 tv.tv_sec -= 1; 00689 } 00690 if (tv.tv_sec < 0) { 00691 tv.tv_sec = 0; 00692 tv.tv_usec = 0; 00693 } 00694 nextms = tv.tv_sec * 1000; 00695 nextms += tv.tv_usec / 1000; 00696 } 00697 00698 for (i = 0; i < linkset->numsigchans; i++) { 00699 pollers[i].fd = linkset->fds[i]; 00700 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]); 00701 pollers[i].revents = 0; 00702 } 00703 ast_mutex_unlock(&linkset->lock); 00704 00705 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 00706 pthread_testcancel(); 00707 res = poll(pollers, linkset->numsigchans, nextms); 00708 pthread_testcancel(); 00709 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 00710 00711 if ((res < 0) && (errno != EINTR)) { 00712 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno)); 00713 } else if (!res) { 00714 ast_mutex_lock(&linkset->lock); 00715 ss7_schedule_run(ss7); 00716 ast_mutex_unlock(&linkset->lock); 00717 continue; 00718 } 00719 00720 ast_mutex_lock(&linkset->lock); 00721 for (i = 0; i < linkset->numsigchans; i++) { 00722 if (pollers[i].revents & POLLPRI) { 00723 sig_ss7_handle_link_exception(linkset, i); 00724 } 00725 if (pollers[i].revents & POLLIN) { 00726 res = ss7_read(ss7, pollers[i].fd); 00727 } 00728 if (pollers[i].revents & POLLOUT) { 00729 res = ss7_write(ss7, pollers[i].fd); 00730 if (res < 0) { 00731 ast_debug(1, "Error in write %s\n", strerror(errno)); 00732 } 00733 } 00734 } 00735 00736 while ((e = ss7_check_event(ss7))) { 00737 if (linkset->debug) { 00738 ast_verbose("Linkset %d: Processing event: %s\n", 00739 linkset->span, ss7_event2str(e->e)); 00740 } 00741 00742 switch (e->e) { 00743 case SS7_EVENT_UP: 00744 if (linkset->state != LINKSET_STATE_UP) { 00745 ast_verbose("--- SS7 Up ---\n"); 00746 ss7_reset_linkset(linkset); 00747 } 00748 linkset->state = LINKSET_STATE_UP; 00749 break; 00750 case SS7_EVENT_DOWN: 00751 ast_verbose("--- SS7 Down ---\n"); 00752 linkset->state = LINKSET_STATE_DOWN; 00753 for (i = 0; i < linkset->numchans; i++) { 00754 p = linkset->pvts[i]; 00755 if (p) { 00756 sig_ss7_set_alarm(p, 1); 00757 } 00758 } 00759 break; 00760 case MTP2_LINK_UP: 00761 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data); 00762 break; 00763 case MTP2_LINK_DOWN: 00764 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data); 00765 break; 00766 case ISUP_EVENT_CPG: 00767 chanpos = ss7_find_cic_gripe(linkset, e->cpg.cic, e->cpg.opc, "CPG"); 00768 if (chanpos < 0) { 00769 break; 00770 } 00771 p = linkset->pvts[chanpos]; 00772 sig_ss7_lock_private(p); 00773 switch (e->cpg.event) { 00774 case CPG_EVENT_ALERTING: 00775 if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING) { 00776 p->call_level = SIG_SS7_CALL_LEVEL_ALERTING; 00777 } 00778 sig_ss7_lock_owner(linkset, chanpos); 00779 if (p->owner) { 00780 ast_setstate(p->owner, AST_STATE_RINGING); 00781 ast_channel_unlock(p->owner); 00782 } 00783 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING); 00784 break; 00785 case CPG_EVENT_PROGRESS: 00786 case CPG_EVENT_INBANDINFO: 00787 { 00788 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic); 00789 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROGRESS); 00790 p->progress = 1; 00791 sig_ss7_set_dialing(p, 0); 00792 #if 0 /* This code no longer seems to be necessary so I did not convert it. */ 00793 if (p->dsp && p->dsp_features) { 00794 ast_dsp_set_features(p->dsp, p->dsp_features); 00795 p->dsp_features = 0; 00796 } 00797 #endif 00798 } 00799 break; 00800 default: 00801 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event); 00802 break; 00803 } 00804 00805 sig_ss7_unlock_private(p); 00806 break; 00807 case ISUP_EVENT_RSC: 00808 ast_verbose("Resetting CIC %d\n", e->rsc.cic); 00809 chanpos = ss7_find_cic_gripe(linkset, e->rsc.cic, e->rsc.opc, "RSC"); 00810 if (chanpos < 0) { 00811 break; 00812 } 00813 p = linkset->pvts[chanpos]; 00814 sig_ss7_lock_private(p); 00815 sig_ss7_set_inservice(p, 1); 00816 sig_ss7_set_remotelyblocked(p, 0); 00817 isup_set_call_dpc(e->rsc.call, p->dpc); 00818 sig_ss7_lock_owner(linkset, chanpos); 00819 p->ss7call = NULL; 00820 if (p->owner) { 00821 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); 00822 ast_channel_unlock(p->owner); 00823 } 00824 sig_ss7_unlock_private(p); 00825 isup_rlc(ss7, e->rsc.call); 00826 break; 00827 case ISUP_EVENT_GRS: 00828 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic); 00829 chanpos = ss7_find_cic_gripe(linkset, e->grs.startcic, e->grs.opc, "GRS"); 00830 if (chanpos < 0) { 00831 break; 00832 } 00833 p = linkset->pvts[chanpos]; 00834 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc); 00835 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0); 00836 ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc); 00837 break; 00838 case ISUP_EVENT_CQM: 00839 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic); 00840 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc); 00841 break; 00842 case ISUP_EVENT_GRA: 00843 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic); 00844 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc); 00845 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1); 00846 break; 00847 case ISUP_EVENT_IAM: 00848 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); 00849 chanpos = ss7_find_cic_gripe(linkset, e->iam.cic, e->iam.opc, "IAM"); 00850 if (chanpos < 0) { 00851 isup_rel(ss7, e->iam.call, -1); 00852 break; 00853 } 00854 p = linkset->pvts[chanpos]; 00855 sig_ss7_lock_private(p); 00856 sig_ss7_lock_owner(linkset, chanpos); 00857 if (p->call_level != SIG_SS7_CALL_LEVEL_IDLE) { 00858 /* 00859 * Detected glare/dual-seizure 00860 * 00861 * Always abort both calls since we can't implement the dual 00862 * seizure procedures due to our channel assignment architecture 00863 * and the fact that we cannot tell libss7 to discard its call 00864 * structure to ignore the incoming IAM. 00865 */ 00866 ast_debug(1, 00867 "Linkset %d: SS7 IAM glare on CIC/DPC %d/%d. Dropping both calls.\n", 00868 linkset->span, e->iam.cic, e->iam.opc); 00869 if (p->call_level == SIG_SS7_CALL_LEVEL_ALLOCATED) { 00870 /* 00871 * We have not sent our IAM yet and we never will at this point. 00872 */ 00873 p->alreadyhungup = 1; 00874 isup_rel(ss7, e->iam.call, -1); 00875 } 00876 p->call_level = SIG_SS7_CALL_LEVEL_GLARE; 00877 if (p->owner) { 00878 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 00879 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); 00880 ast_channel_unlock(p->owner); 00881 } 00882 sig_ss7_unlock_private(p); 00883 break; 00884 } 00885 /* 00886 * The channel should not have an owner at this point since we 00887 * are in the process of creating an owner for it. 00888 */ 00889 ast_assert(!p->owner); 00890 00891 /* Mark channel as in use so no outgoing call will steal it. */ 00892 p->call_level = SIG_SS7_CALL_LEVEL_ALLOCATED; 00893 p->ss7call = e->iam.call; 00894 00895 isup_set_call_dpc(p->ss7call, p->dpc); 00896 00897 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) { 00898 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai); 00899 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind); 00900 } else 00901 p->cid_num[0] = 0; 00902 00903 /* Set DNID */ 00904 if (!ast_strlen_zero(e->iam.called_party_num)) { 00905 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, 00906 e->iam.called_party_num, e->iam.called_nai); 00907 } else { 00908 p->exten[0] = '\0'; 00909 } 00910 sig_ss7_set_dnid(p, p->exten); 00911 00912 if (p->immediate) { 00913 p->exten[0] = 's'; 00914 p->exten[1] = '\0'; 00915 } else if (!ast_strlen_zero(e->iam.called_party_num)) { 00916 char *st; 00917 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai); 00918 st = strchr(p->exten, '#'); 00919 if (st) { 00920 *st = '\0'; 00921 } 00922 } else { 00923 p->exten[0] = '\0'; 00924 } 00925 00926 p->cid_ani[0] = '\0'; 00927 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name))) 00928 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name)); 00929 else 00930 p->cid_name[0] = '\0'; 00931 00932 p->cid_ani2 = e->iam.oli_ani2; 00933 p->cid_ton = 0; 00934 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number)); 00935 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number)); 00936 p->gen_add_type = e->iam.gen_add_type; 00937 p->gen_add_nai = e->iam.gen_add_nai; 00938 p->gen_add_pres_ind = e->iam.gen_add_pres_ind; 00939 p->gen_add_num_plan = e->iam.gen_add_num_plan; 00940 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number)); 00941 p->gen_dig_type = e->iam.gen_dig_type; 00942 p->gen_dig_scheme = e->iam.gen_dig_scheme; 00943 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number)); 00944 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num)); 00945 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num)); 00946 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name)); 00947 p->calling_party_cat = e->iam.calling_party_cat; 00948 00949 sig_ss7_set_caller_id(p); 00950 00951 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 00952 if (e->iam.cot_check_required) { 00953 p->call_level = SIG_SS7_CALL_LEVEL_CONTINUITY; 00954 sig_ss7_loopback(p, 1); 00955 } else { 00956 ss7_start_call(p, linkset); 00957 } 00958 } else { 00959 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten); 00960 p->alreadyhungup = 1; 00961 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED); 00962 } 00963 sig_ss7_unlock_private(p); 00964 break; 00965 case ISUP_EVENT_COT: 00966 chanpos = ss7_find_cic_gripe(linkset, e->cot.cic, e->cot.opc, "COT"); 00967 if (chanpos < 0) { 00968 isup_rel(ss7, e->cot.call, -1); 00969 break; 00970 } 00971 p = linkset->pvts[chanpos]; 00972 00973 sig_ss7_lock_private(p); 00974 if (p->loopedback) { 00975 sig_ss7_loopback(p, 0); 00976 ss7_start_call(p, linkset); 00977 } 00978 sig_ss7_unlock_private(p); 00979 break; 00980 case ISUP_EVENT_CCR: 00981 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic); 00982 chanpos = ss7_find_cic_gripe(linkset, e->ccr.cic, e->ccr.opc, "CCR"); 00983 if (chanpos < 0) { 00984 break; 00985 } 00986 00987 p = linkset->pvts[chanpos]; 00988 00989 sig_ss7_lock_private(p); 00990 sig_ss7_loopback(p, 1); 00991 sig_ss7_unlock_private(p); 00992 00993 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc); 00994 break; 00995 case ISUP_EVENT_CVT: 00996 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic); 00997 chanpos = ss7_find_cic_gripe(linkset, e->cvt.cic, e->cvt.opc, "CVT"); 00998 if (chanpos < 0) { 00999 break; 01000 } 01001 01002 p = linkset->pvts[chanpos]; 01003 01004 sig_ss7_lock_private(p); 01005 sig_ss7_loopback(p, 1); 01006 sig_ss7_unlock_private(p); 01007 01008 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc); 01009 break; 01010 case ISUP_EVENT_REL: 01011 chanpos = ss7_find_cic_gripe(linkset, e->rel.cic, e->rel.opc, "REL"); 01012 if (chanpos < 0) { 01013 /* Continue hanging up the call anyway. */ 01014 isup_rlc(ss7, e->rel.call); 01015 break; 01016 } 01017 p = linkset->pvts[chanpos]; 01018 sig_ss7_lock_private(p); 01019 sig_ss7_lock_owner(linkset, chanpos); 01020 if (p->owner) { 01021 p->owner->hangupcause = e->rel.cause; 01022 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); 01023 ast_channel_unlock(p->owner); 01024 } 01025 01026 /* End the loopback if we have one */ 01027 sig_ss7_loopback(p, 0); 01028 01029 isup_rlc(ss7, e->rel.call); 01030 p->ss7call = NULL; 01031 01032 sig_ss7_unlock_private(p); 01033 break; 01034 case ISUP_EVENT_ACM: 01035 chanpos = ss7_find_cic_gripe(linkset, e->acm.cic, e->acm.opc, "ACM"); 01036 if (chanpos < 0) { 01037 isup_rel(ss7, e->acm.call, -1); 01038 break; 01039 } 01040 { 01041 p = linkset->pvts[chanpos]; 01042 01043 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic); 01044 01045 if (e->acm.call_ref_ident > 0) { 01046 p->rlt = 1; /* Setting it but not using it here*/ 01047 } 01048 01049 sig_ss7_lock_private(p); 01050 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROCEEDING); 01051 if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING) { 01052 p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING; 01053 } 01054 sig_ss7_set_dialing(p, 0); 01055 /* Send alerting if subscriber is free */ 01056 if (e->acm.called_party_status_ind == 1) { 01057 if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING) { 01058 p->call_level = SIG_SS7_CALL_LEVEL_ALERTING; 01059 } 01060 sig_ss7_lock_owner(linkset, chanpos); 01061 if (p->owner) { 01062 ast_setstate(p->owner, AST_STATE_RINGING); 01063 ast_channel_unlock(p->owner); 01064 } 01065 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING); 01066 } 01067 sig_ss7_unlock_private(p); 01068 } 01069 break; 01070 case ISUP_EVENT_CGB: 01071 chanpos = ss7_find_cic_gripe(linkset, e->cgb.startcic, e->cgb.opc, "CGB"); 01072 if (chanpos < 0) { 01073 break; 01074 } 01075 p = linkset->pvts[chanpos]; 01076 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1); 01077 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type); 01078 break; 01079 case ISUP_EVENT_CGU: 01080 chanpos = ss7_find_cic_gripe(linkset, e->cgu.startcic, e->cgu.opc, "CGU"); 01081 if (chanpos < 0) { 01082 break; 01083 } 01084 p = linkset->pvts[chanpos]; 01085 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0); 01086 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type); 01087 break; 01088 case ISUP_EVENT_UCIC: 01089 chanpos = ss7_find_cic_gripe(linkset, e->ucic.cic, e->ucic.opc, "UCIC"); 01090 if (chanpos < 0) { 01091 break; 01092 } 01093 p = linkset->pvts[chanpos]; 01094 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic); 01095 sig_ss7_lock_private(p); 01096 sig_ss7_set_remotelyblocked(p, 1); 01097 sig_ss7_set_inservice(p, 0); 01098 sig_ss7_unlock_private(p);/* doesn't require a SS7 acknowledgement */ 01099 break; 01100 case ISUP_EVENT_BLO: 01101 chanpos = ss7_find_cic_gripe(linkset, e->blo.cic, e->blo.opc, "BLO"); 01102 if (chanpos < 0) { 01103 break; 01104 } 01105 p = linkset->pvts[chanpos]; 01106 ast_debug(1, "Blocking CIC %d\n", e->blo.cic); 01107 sig_ss7_lock_private(p); 01108 sig_ss7_set_remotelyblocked(p, 1); 01109 sig_ss7_unlock_private(p); 01110 isup_bla(linkset->ss7, e->blo.cic, p->dpc); 01111 break; 01112 case ISUP_EVENT_BLA: 01113 chanpos = ss7_find_cic_gripe(linkset, e->bla.cic, e->bla.opc, "BLA"); 01114 if (chanpos < 0) { 01115 break; 01116 } 01117 ast_debug(1, "Blocking CIC %d\n", e->bla.cic); 01118 p = linkset->pvts[chanpos]; 01119 sig_ss7_lock_private(p); 01120 sig_ss7_set_locallyblocked(p, 1); 01121 sig_ss7_unlock_private(p); 01122 break; 01123 case ISUP_EVENT_UBL: 01124 chanpos = ss7_find_cic_gripe(linkset, e->ubl.cic, e->ubl.opc, "UBL"); 01125 if (chanpos < 0) { 01126 break; 01127 } 01128 p = linkset->pvts[chanpos]; 01129 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic); 01130 sig_ss7_lock_private(p); 01131 sig_ss7_set_remotelyblocked(p, 0); 01132 sig_ss7_unlock_private(p); 01133 isup_uba(linkset->ss7, e->ubl.cic, p->dpc); 01134 break; 01135 case ISUP_EVENT_UBA: 01136 chanpos = ss7_find_cic_gripe(linkset, e->uba.cic, e->uba.opc, "UBA"); 01137 if (chanpos < 0) { 01138 break; 01139 } 01140 p = linkset->pvts[chanpos]; 01141 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic); 01142 sig_ss7_lock_private(p); 01143 sig_ss7_set_locallyblocked(p, 0); 01144 sig_ss7_unlock_private(p); 01145 break; 01146 case ISUP_EVENT_CON: 01147 case ISUP_EVENT_ANM: 01148 if (e->e == ISUP_EVENT_CON) { 01149 chanpos = ss7_find_cic_gripe(linkset, e->con.cic, e->con.opc, "CON"); 01150 if (chanpos < 0) { 01151 isup_rel(ss7, e->con.call, -1); 01152 break; 01153 } 01154 } else { 01155 chanpos = ss7_find_cic_gripe(linkset, e->anm.cic, e->anm.opc, "ANM"); 01156 if (chanpos < 0) { 01157 isup_rel(ss7, e->anm.call, -1); 01158 break; 01159 } 01160 } 01161 01162 { 01163 p = linkset->pvts[chanpos]; 01164 sig_ss7_lock_private(p); 01165 if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) { 01166 p->call_level = SIG_SS7_CALL_LEVEL_CONNECT; 01167 } 01168 sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_ANSWER); 01169 #if 0 /* This code no longer seems to be necessary so I did not convert it. */ 01170 if (p->dsp && p->dsp_features) { 01171 ast_dsp_set_features(p->dsp, p->dsp_features); 01172 p->dsp_features = 0; 01173 } 01174 #endif 01175 sig_ss7_set_echocanceller(p, 1); 01176 sig_ss7_unlock_private(p); 01177 } 01178 break; 01179 case ISUP_EVENT_RLC: 01180 /* XXX Call ptr should be passed up from libss7! */ 01181 chanpos = ss7_find_cic_gripe(linkset, e->rlc.cic, e->rlc.opc, "RLC"); 01182 if (chanpos < 0) { 01183 break; 01184 } 01185 { 01186 p = linkset->pvts[chanpos]; 01187 sig_ss7_lock_private(p); 01188 if (p->alreadyhungup) { 01189 if (!p->owner) { 01190 p->call_level = SIG_SS7_CALL_LEVEL_IDLE; 01191 } 01192 p->ss7call = NULL; 01193 } 01194 sig_ss7_unlock_private(p); 01195 } 01196 break; 01197 case ISUP_EVENT_FAA: 01198 /*! 01199 * \todo The handling of the SS7 FAA message is not good and I 01200 * don't know enough to handle it correctly. 01201 */ 01202 chanpos = ss7_find_cic_gripe(linkset, e->faa.cic, e->faa.opc, "FAA"); 01203 if (chanpos < 0) { 01204 isup_rel(linkset->ss7, e->faa.call, -1); 01205 break; 01206 } 01207 { 01208 /* XXX FAR and FAA used for something dealing with transfers? */ 01209 p = linkset->pvts[chanpos]; 01210 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic); 01211 sig_ss7_lock_private(p); 01212 if (p->alreadyhungup){ 01213 if (!p->owner) { 01214 p->call_level = SIG_SS7_CALL_LEVEL_IDLE; 01215 } 01216 /* XXX We seem to be leaking the isup call structure here. */ 01217 p->ss7call = NULL; 01218 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n"); 01219 } 01220 sig_ss7_unlock_private(p); 01221 } 01222 break; 01223 default: 01224 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e)); 01225 break; 01226 } 01227 } 01228 ast_mutex_unlock(&linkset->lock); 01229 } 01230 01231 return 0; 01232 }