#include "asterisk.h"
#include <signal.h>
#include "asterisk/pbx.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/cli.h"
#include "asterisk/transcap.h"
#include "sig_ss7.h"
Go to the source code of this file.
Defines | |
#define | SIG_SS7_DEADLOCK_AVOIDANCE(p) |
#define | SIG_SS7_SC_HEADER "%-4s %4s %-4s %-3s %-3s %-10s %-4s %s\n" |
#define | SIG_SS7_SC_LINE "%4d %4d %-4s %-3s %-3s %-10s %-4s %s" |
Functions | |
static unsigned char | cid_pres2ss7pres (int cid_pres) |
static unsigned char | cid_pres2ss7screen (int cid_pres) |
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. | |
static const char * | sig_ss7_call_level2str (enum sig_ss7_call_level level) |
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. | |
static void | sig_ss7_handle_link_exception (struct sig_ss7_linkset *linkset, int which) |
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. | |
static int | sig_ss7_is_chan_available (struct sig_ss7_chan *pvt) |
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. | |
static void | sig_ss7_lock_owner (struct sig_ss7_linkset *ss7, int chanpos) |
static void | sig_ss7_lock_private (struct sig_ss7_chan *p) |
static void | sig_ss7_loopback (struct sig_ss7_chan *p, int enable) |
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) |
static int | sig_ss7_play_tone (struct sig_ss7_chan *p, enum sig_ss7_tone tone) |
static void | sig_ss7_queue_control (struct sig_ss7_linkset *ss7, int chanpos, int subclass) |
static void | sig_ss7_queue_frame (struct sig_ss7_linkset *ss7, int chanpos, struct ast_frame *frame) |
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) |
static void | sig_ss7_set_caller_id (struct sig_ss7_chan *p) |
static void | sig_ss7_set_dialing (struct sig_ss7_chan *p, int is_dialing) |
static void | sig_ss7_set_digital (struct sig_ss7_chan *p, int is_digital) |
static void | sig_ss7_set_dnid (struct sig_ss7_chan *p, const char *dnid) |
static int | sig_ss7_set_echocanceller (struct sig_ss7_chan *p, int enable) |
static void | sig_ss7_set_inservice (struct sig_ss7_chan *p, int is_inservice) |
static void | sig_ss7_set_locallyblocked (struct sig_ss7_chan *p, int is_blocked) |
static void | sig_ss7_set_remotelyblocked (struct sig_ss7_chan *p, int is_blocked) |
static void | sig_ss7_unlock_private (struct sig_ss7_chan *p) |
static void | ss7_apply_plan_to_number (char *buf, size_t size, const struct sig_ss7_linkset *ss7, const char *number, const unsigned nai) |
static void | ss7_block_cics (struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block) |
static int | ss7_find_cic (struct sig_ss7_linkset *linkset, int cic, unsigned int dpc) |
static int | ss7_find_cic_gripe (struct sig_ss7_linkset *linkset, int cic, unsigned int dpc, const char *msg_name) |
static void | ss7_grab (struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7) |
static void | ss7_handle_cqm (struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc) |
static void | ss7_hangup_cics (struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc) |
static void | ss7_inservice (struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc) |
void * | ss7_linkset (void *data) |
static int | ss7_pres_scr2cid_pres (char presentation_ind, char screening_ind) |
static void | ss7_rel (struct sig_ss7_linkset *ss7) |
static void | ss7_reset_linkset (struct sig_ss7_linkset *linkset) |
static void | ss7_start_call (struct sig_ss7_chan *p, struct sig_ss7_linkset *linkset) |
Richard Mudgett <rmudgett@digium.com>
Definition in file sig_ss7.c.
#define SIG_SS7_DEADLOCK_AVOIDANCE | ( | p | ) |
Value:
do { \ sig_ss7_unlock_private(p); \ usleep(1); \ sig_ss7_lock_private(p); \ } while (0)
Definition at line 70 of file sig_ss7.c.
Referenced by ss7_grab().
#define SIG_SS7_SC_HEADER "%-4s %4s %-4s %-3s %-3s %-10s %-4s %s\n" |
#define SIG_SS7_SC_LINE "%4d %4d %-4s %-3s %-3s %-10s %-4s %s" |
static unsigned char cid_pres2ss7pres | ( | int | cid_pres | ) | [static] |
static unsigned char cid_pres2ss7screen | ( | int | cid_pres | ) | [static] |
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_chan::ss7, sig_ss7_linkset::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_chan::ss7, sig_ss7_linkset::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 }
static const char* sig_ss7_call_level2str | ( | enum sig_ss7_call_level | level | ) | [static] |
Definition at line 47 of file sig_ss7.c.
References SIG_SS7_CALL_LEVEL_ALERTING, SIG_SS7_CALL_LEVEL_ALLOCATED, SIG_SS7_CALL_LEVEL_CONNECT, SIG_SS7_CALL_LEVEL_CONTINUITY, SIG_SS7_CALL_LEVEL_GLARE, SIG_SS7_CALL_LEVEL_IDLE, SIG_SS7_CALL_LEVEL_PROCEEDING, and SIG_SS7_CALL_LEVEL_SETUP.
Referenced by sig_ss7_cli_show_channels().
00048 { 00049 switch (level) { 00050 case SIG_SS7_CALL_LEVEL_IDLE: 00051 return "Idle"; 00052 case SIG_SS7_CALL_LEVEL_ALLOCATED: 00053 return "Allocated"; 00054 case SIG_SS7_CALL_LEVEL_CONTINUITY: 00055 return "Continuity"; 00056 case SIG_SS7_CALL_LEVEL_SETUP: 00057 return "Setup"; 00058 case SIG_SS7_CALL_LEVEL_PROCEEDING: 00059 return "Proceeding"; 00060 case SIG_SS7_CALL_LEVEL_ALERTING: 00061 return "Alerting"; 00062 case SIG_SS7_CALL_LEVEL_CONNECT: 00063 return "Connect"; 00064 case SIG_SS7_CALL_LEVEL_GLARE: 00065 return "Glare"; 00066 } 00067 return "Unknown"; 00068 }
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.
static void sig_ss7_handle_link_exception | ( | struct sig_ss7_linkset * | linkset, | |
int | which | |||
) | [static] |
Definition at line 252 of file sig_ss7.c.
References sig_ss7_linkset::calls, and sig_ss7_callback::handle_link_exception.
00253 { 00254 if (linkset->calls->handle_link_exception) { 00255 linkset->calls->handle_link_exception(linkset, which); 00256 } 00257 }
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_chan::ss7, sig_ss7_linkset::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_chan::ss7, sig_ss7_linkset::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 }
static int sig_ss7_is_chan_available | ( | struct sig_ss7_chan * | pvt | ) | [static] |
Definition at line 1341 of file sig_ss7.c.
References sig_ss7_chan::call_level, sig_ss7_chan::inalarm, sig_ss7_chan::locallyblocked, sig_ss7_chan::owner, sig_ss7_chan::remotelyblocked, SIG_SS7_CALL_LEVEL_IDLE, and sig_ss7_chan::ss7call.
Referenced by sig_ss7_available(), and sig_ss7_cli_show_channels().
01342 { 01343 if (!pvt->inalarm && !pvt->owner && !pvt->ss7call 01344 && pvt->call_level == SIG_SS7_CALL_LEVEL_IDLE 01345 && !pvt->locallyblocked && !pvt->remotelyblocked) { 01346 return 1; 01347 } 01348 return 0; 01349 }
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 }
static void sig_ss7_lock_owner | ( | struct sig_ss7_linkset * | ss7, | |
int | chanpos | |||
) | [static] |
Definition at line 272 of file sig_ss7.c.
References ast_channel_trylock, sig_ss7_chan::owner, and sig_ss7_linkset::pvts.
Referenced by sig_ss7_cli_show_channels(), and sig_ss7_queue_frame().
00273 { 00274 for (;;) { 00275 if (!ss7->pvts[chanpos]->owner) { 00276 /* There is no owner lock to get. */ 00277 break; 00278 } 00279 if (!ast_channel_trylock(ss7->pvts[chanpos]->owner)) { 00280 /* We got the lock */ 00281 break; 00282 } 00283 /* We must unlock the SS7 to avoid the possibility of a deadlock */ 00284 ast_mutex_unlock(&ss7->lock); 00285 SIG_SS7_DEADLOCK_AVOIDANCE(ss7->pvts[chanpos]); 00286 ast_mutex_lock(&ss7->lock); 00287 } 00288 }
static void sig_ss7_lock_private | ( | struct sig_ss7_chan * | p | ) | [static] |
Definition at line 84 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, and sig_ss7_callback::lock_private.
Referenced by sig_ss7_cli_show_channels(), ss7_hangup_cics(), and ss7_start_call().
00085 { 00086 if (p->calls->lock_private) { 00087 p->calls->lock_private(p->chan_pvt); 00088 } 00089 }
static void sig_ss7_loopback | ( | struct sig_ss7_chan * | p, | |
int | enable | |||
) | [static] |
Definition at line 215 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, sig_ss7_chan::loopedback, and sig_ss7_callback::set_loopback.
00216 { 00217 if (p->loopedback != enable) { 00218 p->loopedback = enable; 00219 if (p->calls->set_loopback) { 00220 p->calls->set_loopback(p->chan_pvt, enable); 00221 } 00222 } 00223 }
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 | |||
) | [static] |
Definition at line 225 of file sig_ss7.c.
References sig_ss7_chan::alreadyhungup, AST_TRANS_CAP_DIGITAL, ast_transfercapability2str(), sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, sig_ss7_callback::new_ast_channel, sig_ss7_chan::owner, pbx_builtin_setvar_helper(), sig_ss7_set_digital(), and ast_channel::transfercapability.
Referenced by sig_ss7_request(), and ss7_start_call().
00226 { 00227 struct ast_channel *ast; 00228 00229 if (p->calls->new_ast_channel) { 00230 ast = p->calls->new_ast_channel(p->chan_pvt, state, ulaw, exten, requestor); 00231 } else { 00232 return NULL; 00233 } 00234 if (!ast) { 00235 return NULL; 00236 } 00237 00238 if (!p->owner) { 00239 p->owner = ast; 00240 } 00241 p->alreadyhungup = 0; 00242 ast->transfercapability = transfercapability; 00243 pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", 00244 ast_transfercapability2str(transfercapability)); 00245 if (transfercapability & AST_TRANS_CAP_DIGITAL) { 00246 sig_ss7_set_digital(p, 1); 00247 } 00248 00249 return ast; 00250 }
static int sig_ss7_play_tone | ( | struct sig_ss7_chan * | p, | |
enum sig_ss7_tone | tone | |||
) | [static] |
Definition at line 195 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, and sig_ss7_callback::play_tone.
Referenced by sig_ss7_indicate().
00196 { 00197 int res; 00198 00199 if (p->calls->play_tone) { 00200 res = p->calls->play_tone(p->chan_pvt, tone); 00201 } else { 00202 res = -1; 00203 } 00204 return res; 00205 }
static void sig_ss7_queue_control | ( | struct sig_ss7_linkset * | ss7, | |
int | chanpos, | |||
int | subclass | |||
) | [static] |
Definition at line 327 of file sig_ss7.c.
References AST_FRAME_CONTROL, sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, f, sig_ss7_linkset::pvts, sig_ss7_callback::queue_control, sig_ss7_queue_frame(), and sig_ss7_chan::ss7.
00328 { 00329 struct ast_frame f = {AST_FRAME_CONTROL, }; 00330 struct sig_ss7_chan *p = ss7->pvts[chanpos]; 00331 00332 if (p->calls->queue_control) { 00333 p->calls->queue_control(p->chan_pvt, subclass); 00334 } 00335 00336 f.subclass.integer = subclass; 00337 sig_ss7_queue_frame(ss7, chanpos, &f); 00338 }
static void sig_ss7_queue_frame | ( | struct sig_ss7_linkset * | ss7, | |
int | chanpos, | |||
struct ast_frame * | frame | |||
) | [static] |
Definition at line 304 of file sig_ss7.c.
References ast_channel_unlock, ast_queue_frame(), sig_ss7_chan::owner, sig_ss7_linkset::pvts, and sig_ss7_lock_owner().
Referenced by sig_ss7_queue_control().
00305 { 00306 sig_ss7_lock_owner(ss7, chanpos); 00307 if (ss7->pvts[chanpos]->owner) { 00308 ast_queue_frame(ss7->pvts[chanpos]->owner, frame); 00309 ast_channel_unlock(ss7->pvts[chanpos]->owner); 00310 } 00311 }
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 }
static void sig_ss7_set_caller_id | ( | struct sig_ss7_chan * | p | ) | [static] |
Definition at line 145 of file sig_ss7.c.
References ast_party_caller::ani, ast_party_caller::ani2, ast_party_caller_init(), ast_strlen_zero(), sig_ss7_chan::callingpres, sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, sig_ss7_chan::cid_ani, sig_ss7_chan::cid_ani2, sig_ss7_chan::cid_name, sig_ss7_chan::cid_num, sig_ss7_chan::cid_subaddr, sig_ss7_chan::cid_ton, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_party_number::plan, ast_party_number::presentation, ast_party_name::presentation, sig_ss7_callback::set_callerid, ast_party_subaddress::str, ast_party_number::str, ast_party_name::str, ast_party_id::subaddress, ast_party_subaddress::valid, ast_party_number::valid, and ast_party_name::valid.
00146 { 00147 struct ast_party_caller caller; 00148 00149 if (p->calls->set_callerid) { 00150 ast_party_caller_init(&caller); 00151 00152 caller.id.name.str = p->cid_name; 00153 caller.id.name.presentation = p->callingpres; 00154 caller.id.name.valid = 1; 00155 00156 caller.id.number.str = p->cid_num; 00157 caller.id.number.plan = p->cid_ton; 00158 caller.id.number.presentation = p->callingpres; 00159 caller.id.number.valid = 1; 00160 00161 if (!ast_strlen_zero(p->cid_subaddr)) { 00162 caller.id.subaddress.valid = 1; 00163 //caller.id.subaddress.type = 0;/* nsap */ 00164 //caller.id.subaddress.odd_even_indicator = 0; 00165 caller.id.subaddress.str = p->cid_subaddr; 00166 } 00167 00168 caller.ani.number.str = p->cid_ani; 00169 //caller.ani.number.plan = p->xxx; 00170 //caller.ani.number.presentation = p->xxx; 00171 caller.ani.number.valid = 1; 00172 00173 caller.ani2 = p->cid_ani2; 00174 p->calls->set_callerid(p->chan_pvt, &caller); 00175 } 00176 }
static void sig_ss7_set_dialing | ( | struct sig_ss7_chan * | p, | |
int | is_dialing | |||
) | [static] |
Definition at line 99 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, and sig_ss7_callback::set_dialing.
Referenced by sig_ss7_call(), and sig_ss7_hangup().
00100 { 00101 if (p->calls->set_dialing) { 00102 p->calls->set_dialing(p->chan_pvt, is_dialing); 00103 } 00104 }
static void sig_ss7_set_digital | ( | struct sig_ss7_chan * | p, | |
int | is_digital | |||
) | [static] |
Definition at line 106 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, and sig_ss7_callback::set_digital.
Referenced by sig_ss7_new_ast_channel().
00107 { 00108 if (p->calls->set_digital) { 00109 p->calls->set_digital(p->chan_pvt, is_digital); 00110 } 00111 }
static void sig_ss7_set_dnid | ( | struct sig_ss7_chan * | p, | |
const char * | dnid | |||
) | [static] |
Definition at line 188 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, and sig_ss7_callback::set_dnid.
00189 { 00190 if (p->calls->set_dnid) { 00191 p->calls->set_dnid(p->chan_pvt, dnid); 00192 } 00193 }
static int sig_ss7_set_echocanceller | ( | struct sig_ss7_chan * | p, | |
int | enable | |||
) | [static] |
Definition at line 207 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, and sig_ss7_callback::set_echocanceller.
Referenced by sig_ss7_indicate(), and ss7_start_call().
00208 { 00209 if (p->calls->set_echocanceller) { 00210 return p->calls->set_echocanceller(p->chan_pvt, enable); 00211 } 00212 return -1; 00213 }
static void sig_ss7_set_inservice | ( | struct sig_ss7_chan * | p, | |
int | is_inservice | |||
) | [static] |
Definition at line 113 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, and sig_ss7_callback::set_inservice.
Referenced by ss7_inservice().
00114 { 00115 if (p->calls->set_inservice) { 00116 p->calls->set_inservice(p->chan_pvt, is_inservice); 00117 } 00118 }
static void sig_ss7_set_locallyblocked | ( | struct sig_ss7_chan * | p, | |
int | is_blocked | |||
) | [static] |
Definition at line 120 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, sig_ss7_chan::locallyblocked, and sig_ss7_callback::set_locallyblocked.
00121 { 00122 p->locallyblocked = is_blocked; 00123 if (p->calls->set_locallyblocked) { 00124 p->calls->set_locallyblocked(p->chan_pvt, is_blocked); 00125 } 00126 }
static void sig_ss7_set_remotelyblocked | ( | struct sig_ss7_chan * | p, | |
int | is_blocked | |||
) | [static] |
Definition at line 128 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, sig_ss7_chan::remotelyblocked, and sig_ss7_callback::set_remotelyblocked.
Referenced by ss7_block_cics().
00129 { 00130 p->remotelyblocked = is_blocked; 00131 if (p->calls->set_remotelyblocked) { 00132 p->calls->set_remotelyblocked(p->chan_pvt, is_blocked); 00133 } 00134 }
static void sig_ss7_unlock_private | ( | struct sig_ss7_chan * | p | ) | [static] |
Definition at line 77 of file sig_ss7.c.
References sig_ss7_chan::calls, sig_ss7_chan::chan_pvt, and sig_ss7_callback::unlock_private.
Referenced by sig_ss7_cli_show_channels(), ss7_hangup_cics(), and ss7_start_call().
00078 { 00079 if (p->calls->unlock_private) { 00080 p->calls->unlock_private(p->chan_pvt); 00081 } 00082 }
static void ss7_apply_plan_to_number | ( | char * | buf, | |
size_t | size, | |||
const struct sig_ss7_linkset * | ss7, | |||
const char * | number, | |||
const unsigned | nai | |||
) | [static] |
Definition at line 628 of file sig_ss7.c.
References ast_strlen_zero(), sig_ss7_linkset::internationalprefix, sig_ss7_linkset::nationalprefix, sig_ss7_linkset::subscriberprefix, and sig_ss7_linkset::unknownprefix.
00629 { 00630 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 00631 if (size) { 00632 *buf = '\0'; 00633 } 00634 return; 00635 } 00636 switch (nai) { 00637 case SS7_NAI_INTERNATIONAL: 00638 snprintf(buf, size, "%s%s", ss7->internationalprefix, number); 00639 break; 00640 case SS7_NAI_NATIONAL: 00641 snprintf(buf, size, "%s%s", ss7->nationalprefix, number); 00642 break; 00643 case SS7_NAI_SUBSCRIBER: 00644 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number); 00645 break; 00646 case SS7_NAI_UNKNOWN: 00647 snprintf(buf, size, "%s%s", ss7->unknownprefix, number); 00648 break; 00649 default: 00650 snprintf(buf, size, "%s", number); 00651 break; 00652 } 00653 }
static void ss7_block_cics | ( | struct sig_ss7_linkset * | linkset, | |
int | startcic, | |||
int | endcic, | |||
unsigned int | dpc, | |||
unsigned char | state[], | |||
int | block | |||
) | [inline, static] |
Definition at line 435 of file sig_ss7.c.
References sig_ss7_chan::cic, sig_ss7_chan::dpc, sig_ss7_linkset::numchans, sig_ss7_linkset::pvts, and sig_ss7_set_remotelyblocked().
00436 { 00437 int i; 00438 00439 /* XXX the use of state here seems questionable about matching up with the linkset channels */ 00440 for (i = 0; i < linkset->numchans; i++) { 00441 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 00442 if (state) { 00443 if (state[i]) 00444 sig_ss7_set_remotelyblocked(linkset->pvts[i], block); 00445 } else 00446 sig_ss7_set_remotelyblocked(linkset->pvts[i], block); 00447 } 00448 } 00449 }
static int ss7_find_cic | ( | struct sig_ss7_linkset * | linkset, | |
int | cic, | |||
unsigned int | dpc | |||
) | [static] |
Definition at line 351 of file sig_ss7.c.
References sig_ss7_chan::cic, sig_ss7_chan::dpc, sig_ss7_linkset::numchans, and sig_ss7_linkset::pvts.
Referenced by ss7_find_cic_gripe().
00352 { 00353 int i; 00354 int winner = -1; 00355 for (i = 0; i < linkset->numchans; i++) { 00356 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) { 00357 winner = i; 00358 break; 00359 } 00360 } 00361 return winner; 00362 }
static int ss7_find_cic_gripe | ( | struct sig_ss7_linkset * | linkset, | |
int | cic, | |||
unsigned int | dpc, | |||
const char * | msg_name | |||
) | [static] |
Definition at line 376 of file sig_ss7.c.
References ast_log(), LOG_WARNING, sig_ss7_linkset::span, and ss7_find_cic().
00377 { 00378 int chanpos; 00379 00380 chanpos = ss7_find_cic(linkset, cic, dpc); 00381 if (chanpos < 0) { 00382 ast_log(LOG_WARNING, "Linkset %d: SS7 %s requested unconfigured CIC/DPC %d/%d.\n", 00383 linkset->span, msg_name, cic, dpc); 00384 return -1; 00385 } 00386 return chanpos; 00387 }
static void ss7_grab | ( | struct sig_ss7_chan * | pvt, | |
struct sig_ss7_linkset * | ss7 | |||
) | [static] |
Definition at line 1239 of file sig_ss7.c.
References ast_mutex_trylock, AST_PTHREADT_NULL, sig_ss7_linkset::lock, sig_ss7_linkset::master, and SIG_SS7_DEADLOCK_AVOIDANCE.
Referenced by sig_ss7_answer(), sig_ss7_call(), sig_ss7_hangup(), and sig_ss7_indicate().
01240 { 01241 int res; 01242 /* Grab the lock first */ 01243 do { 01244 res = ast_mutex_trylock(&ss7->lock); 01245 if (res) { 01246 SIG_SS7_DEADLOCK_AVOIDANCE(pvt); 01247 } 01248 } while (res); 01249 /* Then break the poll */ 01250 if (ss7->master != AST_PTHREADT_NULL) 01251 pthread_kill(ss7->master, SIGURG); 01252 }
static void ss7_handle_cqm | ( | struct sig_ss7_linkset * | linkset, | |
int | startcic, | |||
int | endcic, | |||
unsigned int | dpc | |||
) | [static] |
Definition at line 389 of file sig_ss7.c.
References sig_ss7_chan::cic, sig_ss7_chan::dpc, sig_ss7_chan::locallyblocked, sig_ss7_linkset::numchans, sig_ss7_chan::outgoing, sig_ss7_linkset::pvts, sig_ss7_chan::remotelyblocked, sig_ss7_chan::ss7call, and status.
00390 { 00391 unsigned char status[32]; 00392 struct sig_ss7_chan *p = NULL; 00393 int i, offset; 00394 00395 for (i = 0; i < linkset->numchans; i++) { 00396 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 00397 p = linkset->pvts[i]; 00398 offset = p->cic - startcic; 00399 status[offset] = 0; 00400 if (p->locallyblocked) 00401 status[offset] |= (1 << 0) | (1 << 4); 00402 if (p->remotelyblocked) 00403 status[offset] |= (1 << 1) | (1 << 5); 00404 if (p->ss7call) { 00405 if (p->outgoing) 00406 status[offset] |= (1 << 3); 00407 else 00408 status[offset] |= (1 << 2); 00409 } else 00410 status[offset] |= 0x3 << 2; 00411 } 00412 } 00413 00414 if (p) 00415 isup_cqr(linkset->ss7, startcic, endcic, dpc, status); 00416 else 00417 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n"); 00418 00419 }
static void ss7_hangup_cics | ( | struct sig_ss7_linkset * | linkset, | |
int | startcic, | |||
int | endcic, | |||
unsigned int | dpc | |||
) | [inline, static] |
Definition at line 421 of file sig_ss7.c.
References ast_channel::_softhangup, AST_SOFTHANGUP_DEV, sig_ss7_chan::cic, sig_ss7_chan::dpc, sig_ss7_linkset::numchans, sig_ss7_chan::owner, sig_ss7_linkset::pvts, sig_ss7_lock_private(), and sig_ss7_unlock_private().
00422 { 00423 int i; 00424 00425 for (i = 0; i < linkset->numchans; i++) { 00426 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 00427 sig_ss7_lock_private(linkset->pvts[i]); 00428 if (linkset->pvts[i]->owner) 00429 linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 00430 sig_ss7_unlock_private(linkset->pvts[i]); 00431 } 00432 } 00433 }
static void ss7_inservice | ( | struct sig_ss7_linkset * | linkset, | |
int | startcic, | |||
int | endcic, | |||
unsigned int | dpc | |||
) | [static] |
Definition at line 451 of file sig_ss7.c.
References sig_ss7_chan::cic, sig_ss7_chan::dpc, sig_ss7_linkset::numchans, sig_ss7_linkset::pvts, and sig_ss7_set_inservice().
00452 { 00453 int i; 00454 00455 for (i = 0; i < linkset->numchans; i++) { 00456 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) 00457 sig_ss7_set_inservice(linkset->pvts[i], 1); 00458 } 00459 }
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 }
static int ss7_pres_scr2cid_pres | ( | char | presentation_ind, | |
char | screening_ind | |||
) | [static] |
static void ss7_rel | ( | struct sig_ss7_linkset * | ss7 | ) | [inline, static] |
Definition at line 1234 of file sig_ss7.c.
References ast_mutex_unlock, and sig_ss7_linkset::lock.
Referenced by sig_ss7_answer(), sig_ss7_call(), sig_ss7_hangup(), and sig_ss7_indicate().
01235 { 01236 ast_mutex_unlock(&ss7->lock); 01237 }
static void ss7_reset_linkset | ( | struct sig_ss7_linkset * | linkset | ) | [static] |
Definition at line 461 of file sig_ss7.c.
References ast_verbose, sig_ss7_chan::cic, sig_ss7_chan::dpc, sig_ss7_linkset::numchans, sig_ss7_linkset::pvts, and sig_ss7_linkset::ss7.
00462 { 00463 int i, startcic = -1, endcic, dpc; 00464 00465 if (linkset->numchans <= 0) 00466 return; 00467 00468 startcic = linkset->pvts[0]->cic; 00469 /* DB: CIC's DPC fix */ 00470 dpc = linkset->pvts[0]->dpc; 00471 00472 for (i = 0; i < linkset->numchans; i++) { 00473 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)) { 00474 continue; 00475 } else { 00476 endcic = linkset->pvts[i]->cic; 00477 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic); 00478 isup_grs(linkset->ss7, startcic, endcic, dpc); 00479 00480 /* DB: CIC's DPC fix */ 00481 if (linkset->pvts[i+1]) { 00482 startcic = linkset->pvts[i+1]->cic; 00483 dpc = linkset->pvts[i+1]->dpc; 00484 } 00485 } 00486 } 00487 }
static void ss7_start_call | ( | struct sig_ss7_chan * | p, | |
struct sig_ss7_linkset * | linkset | |||
) | [static] |
Definition at line 490 of file sig_ss7.c.
References sig_ss7_chan::alreadyhungup, ast_channel_lock, ast_channel_unlock, ast_hangup(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pbx_start(), AST_STATE_RING, ast_strlen_zero(), ast_verb, sig_ss7_chan::call_level, sig_ss7_chan::call_ref_ident, sig_ss7_chan::call_ref_pc, sig_ss7_chan::calling_party_cat, sig_ss7_chan::charge_number, sig_ss7_chan::cic, sig_ss7_chan::exten, sig_ss7_linkset::flags, sig_ss7_chan::gen_add_number, sig_ss7_chan::gen_dig_number, sig_ss7_chan::gen_dig_scheme, sig_ss7_chan::gen_dig_type, sig_ss7_chan::generic_name, sig_ss7_chan::jip_number, LINKSET_FLAG_EXPLICITACM, sig_ss7_linkset::lock, LOG_WARNING, sig_ss7_chan::lspi_ident, ast_channel::name, sig_ss7_chan::orig_called_num, pbx_builtin_setvar_helper(), sig_ss7_chan::redirecting_num, SIG_SS7_ALAW, SIG_SS7_CALL_LEVEL_IDLE, SIG_SS7_CALL_LEVEL_PROCEEDING, SIG_SS7_CALL_LEVEL_SETUP, sig_ss7_lock_private(), sig_ss7_new_ast_channel(), sig_ss7_set_echocanceller(), SIG_SS7_ULAW, sig_ss7_unlock_private(), sig_ss7_linkset::ss7, sig_ss7_chan::ss7call, and sig_ss7_linkset::type.
00491 { 00492 struct ss7 *ss7 = linkset->ss7; 00493 int law; 00494 struct ast_channel *c; 00495 char tmp[256]; 00496 00497 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) { 00498 p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING; 00499 isup_acm(ss7, p->ss7call); 00500 } else { 00501 p->call_level = SIG_SS7_CALL_LEVEL_SETUP; 00502 } 00503 00504 if (linkset->type == SS7_ITU) { 00505 law = SIG_SS7_ALAW; 00506 } else { 00507 law = SIG_SS7_ULAW; 00508 } 00509 00510 /* 00511 * Release the SS7 lock while we create the channel so other 00512 * threads can send messages. We must also release the private 00513 * lock to prevent deadlock while creating the channel. 00514 */ 00515 ast_mutex_unlock(&linkset->lock); 00516 sig_ss7_unlock_private(p); 00517 c = sig_ss7_new_ast_channel(p, AST_STATE_RING, law, 0, p->exten, NULL); 00518 if (!c) { 00519 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic); 00520 ast_mutex_lock(&linkset->lock); 00521 sig_ss7_lock_private(p); 00522 isup_rel(linkset->ss7, p->ss7call, -1); 00523 p->call_level = SIG_SS7_CALL_LEVEL_IDLE; 00524 p->alreadyhungup = 1; 00525 return; 00526 } 00527 00528 /* Hold the channel and private lock while we setup the channel. */ 00529 ast_channel_lock(c); 00530 sig_ss7_lock_private(p); 00531 00532 sig_ss7_set_echocanceller(p, 1); 00533 00534 /* 00535 * It is reasonably safe to set the following 00536 * channel variables while the channel private 00537 * structure is locked. The PBX has not been 00538 * started yet and it is unlikely that any other task 00539 * will do anything with the channel we have just 00540 * created. 00541 * 00542 * We only reference these variables in the context of the ss7_linkset function 00543 * when receiving either and IAM or a COT message. 00544 */ 00545 if (!ast_strlen_zero(p->charge_number)) { 00546 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number); 00547 /* Clear this after we set it */ 00548 p->charge_number[0] = 0; 00549 } 00550 if (!ast_strlen_zero(p->gen_add_number)) { 00551 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number); 00552 /* Clear this after we set it */ 00553 p->gen_add_number[0] = 0; 00554 } 00555 if (!ast_strlen_zero(p->jip_number)) { 00556 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number); 00557 /* Clear this after we set it */ 00558 p->jip_number[0] = 0; 00559 } 00560 if (!ast_strlen_zero(p->gen_dig_number)) { 00561 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number); 00562 /* Clear this after we set it */ 00563 p->gen_dig_number[0] = 0; 00564 } 00565 if (!ast_strlen_zero(p->orig_called_num)) { 00566 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num); 00567 /* Clear this after we set it */ 00568 p->orig_called_num[0] = 0; 00569 } 00570 00571 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type); 00572 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp); 00573 /* Clear this after we set it */ 00574 p->gen_dig_type = 0; 00575 00576 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme); 00577 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp); 00578 /* Clear this after we set it */ 00579 p->gen_dig_scheme = 0; 00580 00581 if (!ast_strlen_zero(p->lspi_ident)) { 00582 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident); 00583 /* Clear this after we set it */ 00584 p->lspi_ident[0] = 0; 00585 } 00586 00587 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident); 00588 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp); 00589 /* Clear this after we set it */ 00590 p->call_ref_ident = 0; 00591 00592 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc); 00593 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp); 00594 /* Clear this after we set it */ 00595 p->call_ref_pc = 0; 00596 00597 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat); 00598 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp); 00599 /* Clear this after we set it */ 00600 p->calling_party_cat = 0; 00601 00602 if (!ast_strlen_zero(p->redirecting_num)) { 00603 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num); 00604 /* Clear this after we set it */ 00605 p->redirecting_num[0] = 0; 00606 } 00607 if (!ast_strlen_zero(p->generic_name)) { 00608 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name); 00609 /* Clear this after we set it */ 00610 p->generic_name[0] = 0; 00611 } 00612 00613 sig_ss7_unlock_private(p); 00614 ast_channel_unlock(c); 00615 00616 if (ast_pbx_start(c)) { 00617 ast_log(LOG_WARNING, "Unable to start PBX on %s (CIC %d)\n", c->name, p->cic); 00618 ast_hangup(c); 00619 } else { 00620 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic); 00621 } 00622 00623 /* Must return with linkset and private lock. */ 00624 ast_mutex_lock(&linkset->lock); 00625 sig_ss7_lock_private(p); 00626 }