📄 chan_ss7.c
字号:
ast_mutex_unlock(&dump_mutex);
return RESULT_SUCCESS;
}
static int cmd_dump_stop(int fd, int argc, char *argv[]) {
int in, out;
if(argc == 3) {
in = 1;
out = 1;
} else if(argc == 4) {
if(0 == strcasecmp(argv[3], "in")) {
in = 1;
out = 0;
} else if(0 == strcasecmp(argv[3], "out")) {
in = 0;
out = 1;
} else if(0 == strcasecmp(argv[3], "both")) {
in = 1;
out = 1;
} else {
return RESULT_SHOWUSAGE;
}
} else {
return RESULT_SHOWUSAGE;
}
ast_mutex_lock(&dump_mutex);
if((in && !out && dump_in_fh == NULL) ||
(out && !in && dump_out_fh == NULL) ||
(in && out && dump_in_fh == NULL && dump_out_fh == NULL)) {
ast_cli(fd, "No dump running.\n");
ast_mutex_unlock(&dump_mutex);
return RESULT_SUCCESS;
}
if(in && dump_in_fh != NULL) {
if(dump_out_fh == dump_in_fh) {
/* Avoid closing it twice. */
dump_out_fh = NULL;
}
fclose(dump_in_fh);
dump_in_fh = NULL;
}
if(out && dump_out_fh != NULL) {
fclose(dump_out_fh);
dump_out_fh = NULL;
}
ast_mutex_unlock(&dump_mutex);
return RESULT_SUCCESS;
}
static int cmd_dump_status(int fd, int argc, char *argv[]) {
ast_mutex_lock(&dump_mutex);
/* ToDo: This doesn't seem to work, the output is getting lost somehow.
Not sure why, but could be related to ast_carefulwrite() called in
ast_cli(). */
ast_cli(fd, "Yuck! what is going on here?!?\n");
if(dump_in_fh != NULL) {
ast_cli(fd, "Dump of incoming frames is running.\n");
}
if(dump_out_fh != NULL) {
ast_cli(fd, "Dump of outgoing frames is running.\n");
}
if(dump_in_fh != NULL || dump_out_fh != NULL) {
ast_cli(fd, "Filter:%s%s%s.\n",
(dump_do_fisu ? " fisu" : ""),
(dump_do_lssu ? " lssu" : ""),
(dump_do_msu ? " msu" : ""));
}
ast_mutex_unlock(&dump_mutex);
return RESULT_SUCCESS;
}
static int cmd_version(int fd, int argc, char *argv[])
{
ast_cli(fd, "chan_ss7 version %s\n", CHAN_SS7_VERSION);
return RESULT_SUCCESS;
}
static int cmd_ss7_status(int fd, int argc, char *argv[])
{
cmd_linkset_status(fd, argc, argv);
return RESULT_SUCCESS;
}
static void process_event(struct mtp_event* event)
{
FILE *dump_fh;
switch(event->typ) {
case MTP_EVENT_ISUP:
l4isup_event(event);
break;
case MTP_EVENT_SCCP:
break;
case MTP_EVENT_REQ_REGISTER:
if (event->regist.ss7_protocol == 5) {
struct link* link = &links[event->regist.isup.slinkix];
mtp3_register_isup(link->mtp3fd, link->linkix);
}
break;
case MTP_EVENT_LOG:
ast_log(event->log.level, event->log.file, event->log.line,
event->log.function, "%s", event->buf);
break;
case MTP_EVENT_DUMP:
ast_mutex_lock(&dump_mutex);
if(event->dump.out) {
dump_fh = dump_out_fh;
} else {
dump_fh = dump_in_fh;
}
if(dump_fh != NULL) {
if(event->len < 3 ||
( !(event->buf[2] == 0 && !dump_do_fisu) &&
!((event->buf[2] == 1 || event->buf[2] == 2) && !dump_do_lssu) &&
!(event->buf[2] > 2 && !dump_do_msu)))
dump_pcap(dump_fh, event);
}
ast_mutex_unlock(&dump_mutex);
break;
case MTP_EVENT_STATUS:
{
struct link* link = event->status.link;
char* name = link ? link->name : "(peer)";
switch(event->status.link_state) {
case MTP_EVENT_STATUS_LINK_UP:
l4isup_link_status_change(link, 1);
ast_log(LOG_WARNING, "MTP is now UP on link '%s'.\n", name);
break;
case MTP_EVENT_STATUS_LINK_DOWN:
l4isup_link_status_change(link, 0);
ast_log(LOG_WARNING, "MTP is now DOWN on link '%s'.\n", name);
break;
case MTP_EVENT_STATUS_INSERVICE:
ast_log(LOG_WARNING, "Signaling ready for linkset '%s'.\n", link->linkset->name);
l4isup_inservice(link);
break;
default:
ast_log(LOG_NOTICE, "Unknown event type STATUS (%d), "
"not processed.\n", event->status.link_state);
}
}
break;
default:
ast_log(LOG_NOTICE, "Unexpected mtp event type %d.\n", event->typ);
}
}
/* Monitor thread main loop.
Monitor reads events from the realtime MTP thread, and processes them at
non-realtime priority. It also handles timers for ISUP etc.
*/
static void *monitor_main(void *data) {
int res, nres;
struct pollfd fds[(MAX_LINKS+1)];
int i, n_fds;
int rebuild_fds = 1;
struct lffifo *receive_fifo = mtp_get_receive_fifo();
ast_verbose(VERBOSE_PREFIX_3 "Starting monitor thread, pid=%d.\n", getpid());
fds[0].fd = get_receive_pipe();
fds[0].events = POLLIN;
while(monitor_running) {
if (rebuild_fds) {
if (rebuild_fds > 1)
poll(fds, 0, 200); /* sleep */
rebuild_fds = 0;
n_fds = 1;
for (i = 0; i < n_linksets; i++) {
struct linkset* linkset = &linksets[i];
int j;
for (j = 0; j < linkset->n_links; j++) {
int k;
struct link* link = linkset->links[j];
for (k = 0; k < this_host->n_spans; k++) {
if (this_host->spans[k].link == link)
break;
if ((this_host->spans[k].link->linkset == link->linkset) ||
(is_combined_linkset(this_host->spans[k].link->linkset, link->linkset)))
break;
}
if (k < this_host->n_spans) {
if (link->remote) {
if (link->mtp3fd == -1) {
link->mtp3fd = mtp3_connect_socket(link->mtp3server_host, link->mtp3server_port);
if (link->mtp3fd != -1)
res = mtp3_register_isup(link->mtp3fd, link->linkix);
if ((link->mtp3fd == -1) || (res == -1))
rebuild_fds += 2;
}
fds[n_fds].fd = link->mtp3fd;
fds[n_fds++].events = POLLIN|POLLERR|POLLNVAL|POLLHUP;
}
}
}
}
}
int timeout = timers_wait();
nres = poll(fds, n_fds, timeout);
if(nres < 0) {
if(errno == EINTR) {
/* Just try again. */
} else {
ast_log(LOG_ERROR, "poll() failure, errno=%d: %s\n",
errno, strerror(errno));
}
} else if(nres > 0) {
for (i = 0; (i < n_fds) && (nres > 0); i++) {
unsigned char eventbuf[MTP_EVENT_MAX_SIZE];
struct mtp_event *event = (struct mtp_event*) eventbuf;
struct link* link = NULL;
if(fds[i].revents) {
int j;
for (j = 0; j < n_links; j++) {
if (links[j].remote && (links[j].mtp3fd == fds[i].fd)) {
link = &links[j];
break;
}
}
}
else
continue;
if(fds[i].revents & (POLLERR|POLLNVAL|POLLHUP)) {
if (i == 0) { /* receivepipe */
ast_log(LOG_ERROR, "poll() return bad revents for receivepipe, 0x%04x\n", fds[i].revents);
}
close(fds[i].fd);
if (link)
link->mtp3fd = -1;
rebuild_fds++; rebuild_fds++; /* when > 1, use short sleep */
nres--;
continue;
}
if(!(fds[i].revents & POLLIN))
continue;
if (i == 0) {
/* Events waiting in the receive buffer. */
unsigned char dummy[512];
/* Empty the pipe before pulling from fifo. This way the race
condition between mtp and monitor threads may cause spurious
wakeups, but not loss/delay of messages. */
read(fds[i].fd, dummy, sizeof(dummy));
/* Process all available events. */
while((res = lffifo_get(receive_fifo, eventbuf, sizeof(eventbuf))) != 0) {
if(res < 0) {
ast_log(LOG_ERROR, "Yuck! oversized frame in receive fifo, bailing out.\n");
return NULL;
}
process_event(event);
}
}
else {
#if MTP3_SOCKET == SOCK_STREAM
res = read(fds[i].fd, eventbuf, sizeof(struct mtp_event));
if ((res > 0) && (event->len > 0)) {
int p = res;
int len = event->len;
if (sizeof(struct mtp_event) + event->len > MTP_EVENT_MAX_SIZE) {
ast_log(LOG_NOTICE, "Got too large packet: len %d, max %d, discarded", sizeof(struct mtp_event) + event->len, MTP_EVENT_MAX_SIZE);
len = 0;
res = 0;
}
do {
res = read(fds[i].fd, &eventbuf[p], len);
if (res > 0) {
p += res;
len -= res;
}
else if ((res < 0) && (errno != EINTR)) {
len = 0;
}
else {
len = 0;
}
} while (len > 0);
}
#else
res = read(fds[i].fd, eventbuf, sizeof(eventbuf)+MTP_MAX_PCK_SIZE);
#endif
if (res > 0) {
if (event->typ == MTP_EVENT_ISUP) {
event->isup.link = NULL;
event->isup.slink = &links[event->isup.slinkix];
}
process_event(event);
}
else if (res == 0) {
int j;
for (j = 0; j < n_links; j++) {
struct link* link = &links[j];
if (link->remote && (link->mtp3fd == fds[i].fd)) {
close(fds[i].fd);
link->mtp3fd = -1;
rebuild_fds++;
}
}
}
}
nres--;
}
}
/* We need to lock the global glock mutex around ast_sched_runq() so that
we avoid a race with ss7_hangup. With the lock, invalidating the
channel in ss7_hangup() and removing associated monitor_sched entries
is an atomic operation, so that we avoid calling timer handlers with
references to invalidated channels. */
run_timers();
}
return NULL;
}
static void stop_monitor(void) {
int i;
if(monitor_running) {
monitor_running = 0;
/* Monitor wakes up every 1/2 sec, so no need to signal it explicitly. */
pthread_join(monitor_thread, NULL);
}
for (i = 0; i < n_links; i++) {
struct link* link = &links[i];
if (link->remote && (link->mtp3fd > -1))
close(link->mtp3fd);
}
}
static int ss7_reload_module(void) {
ast_log(LOG_NOTICE, "SS7 reload not implemented.\n");
return AST_MODULE_LOAD_SUCCESS;
}
static int ss7_load_module(void)
{
if(load_config(0)) {
return AST_MODULE_LOAD_FAILURE;
}
if (timers_init()) {
ast_log(LOG_ERROR, "Unable to initialize timers.\n");
return AST_MODULE_LOAD_FAILURE;
}
if (isup_init()) {
ast_log(LOG_ERROR, "Unable to initialize ISUP.\n");
return AST_MODULE_LOAD_FAILURE;
}
#ifdef SCCP
if (sccp_init()) {
ast_log(LOG_ERROR, "Unable to initialize SCCP.\n");
return AST_MODULE_LOAD_FAILURE;
}
#endif
if(mtp_init()) {
ast_log(LOG_ERROR, "Unable to initialize MTP.\n");
return AST_MODULE_LOAD_FAILURE;
}
if(start_mtp_thread()) {
ast_log(LOG_ERROR, "Unable to start MTP thread.\n");
return AST_MODULE_LOAD_FAILURE;
}
mtp_control_fifo = mtp_get_control_fifo();
monitor_running = 1; /* Otherwise there is a race, and
monitor may exit immediately */
if(ast_pthread_create(&monitor_thread, NULL, monitor_main, NULL) < 0) {
ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
monitor_running = 0;
return AST_MODULE_LOAD_FAILURE;
}
ast_cli_register_multiple(my_clis, sizeof(my_clis)/ sizeof(my_clis[0]));
ast_verbose(VERBOSE_PREFIX_3 "SS7 channel loaded successfully.\n");
return AST_MODULE_LOAD_SUCCESS;
}
static int ss7_unload_module(void)
{
ast_cli_unregister_multiple(my_clis, sizeof(my_clis)/ sizeof(my_clis[0]));
#ifdef SCCP
sccp_cleanup();
#endif
isup_cleanup();
ast_mutex_lock(&dump_mutex);
if(dump_in_fh != NULL) {
if(dump_in_fh == dump_out_fh) {
dump_out_fh = NULL;
}
fclose(dump_in_fh);
dump_in_fh = NULL;
}
if(dump_out_fh != NULL) {
fclose(dump_out_fh);
dump_out_fh = NULL;
}
ast_mutex_unlock(&dump_mutex);
if(monitor_running) {
stop_monitor();
}
stop_mtp_thread();
mtp_cleanup();
timers_cleanup();
destroy_config();
ast_verbose(VERBOSE_PREFIX_3 "SS7 channel unloaded.\n");
return AST_MODULE_LOAD_SUCCESS;
}
#ifdef USE_ASTERISK_1_2
int reload(void)
{
return ss7_reload_module();
}
int load_module(void)
{
return ss7_load_module();
}
int unload_module(void)
{
return ss7_unload_module();
}
char *description() {
return (char *) desc;
}
char *key() {
return ASTERISK_GPL_KEY;
}
#else
#define AST_MODULE "chan_ss7"
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, desc,
.load = ss7_load_module,
.unload = ss7_unload_module,
.reload = ss7_reload_module,
);
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -