Mon May 14 04:42:54 2007

Asterisk developer's documentation


chan_ss7.c

Go to the documentation of this file.
00001 /* chan_ss7.c - Implementation of SS7 (MTP2, MTP3, and ISUP) for Asterisk.
00002  *
00003  * Copyright (C) 2005-2006, Sifira A/S.
00004  *
00005  * Author: Kristian Nielsen <kn@sifira.dk>,
00006  *         Anders Baekgaard <ab@sifira.dk>
00007  *
00008  * This file is part of chan_ss7.
00009  *
00010  * chan_ss7 is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * chan_ss7 is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with chan_ss7; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00023  */
00024 
00025 #include <asterisk.h>
00026 
00027 #include <errno.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <stdio.h>
00031 
00032 #include <unistd.h>
00033 #include <sys/poll.h>
00034 #include <netinet/in.h>
00035 
00036 #include "asterisk/module.h"
00037 #include "asterisk/logger.h"
00038 #include "asterisk/options.h"
00039 #include "asterisk/utils.h"
00040 #include "asterisk/sched.h"
00041 #include "asterisk/cli.h"
00042 #include "asterisk/lock.h"
00043 
00044 #include "config.h"
00045 #include "lffifo.h"
00046 #include "utils.h"
00047 #include "mtp.h"
00048 #include "isup.h"
00049 #include "l4isup.h"
00050 #ifdef SCCP
00051 #include "l4sccp.h"
00052 #endif
00053 #include "cluster.h"
00054 
00055 
00056 /* Send fifo for sending control requests to the MTP thread.
00057    The fifo is lock-free (one thread may put and another get simultaneously),
00058    but multiple threads doing put must be serialized with this mutex. */
00059 AST_MUTEX_DEFINE_STATIC(mtp_control_mutex);
00060 static struct lffifo *mtp_control_fifo = NULL;
00061 
00062 /* This is the MTP2/MTP3 thread, which runs at high real-time priority
00063    and is careful not to wait for locks in order not to loose MTP
00064    frames. */
00065 static pthread_t mtp_thread = AST_PTHREADT_NULL;
00066 static int mtp_thread_running = 0;
00067 
00068 
00069 /* This is the monitor thread which mainly handles scheduling/timeouts. */
00070 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00071 static int monitor_running = 0;
00072 
00073 
00074 
00075 /* State for raw dumps. */
00076 AST_MUTEX_DEFINE_STATIC(dump_mutex);
00077 static FILE *dump_in_fh = NULL;
00078 static FILE *dump_out_fh = NULL;
00079 static int dump_do_fisu, dump_do_lssu, dump_do_msu;
00080 
00081 
00082 static const char desc[] = "SS7 Protocol Support";
00083 static const char config[] = "ss7.conf";
00084 
00085 
00086 
00087 
00088 static int cmd_version(int fd, int argc, char *argv[]);
00089 static int cmd_dump_status(int fd, int argc, char *argv[]);
00090 static int cmd_dump_stop(int fd, int argc, char *argv[]);
00091 static int cmd_dump_start(int fd, int argc, char *argv[]);
00092 static char *complete_dump_stop(char *line, char *word, int pos, int state);
00093 static char *complete_dump_start(char *line, char *word, int pos, int state);
00094 static int cmd_link_up(int fd, int argc, char *argv[]);
00095 static int cmd_link_down(int fd, int argc, char *argv[]);
00096 static int cmd_link_status(int fd, int argc, char *argv[]);
00097 
00098 static struct ast_cli_entry my_clis[] = {
00099   { {"ss7", "version", NULL}, cmd_version,
00100     "Show current version of chan_ss7",
00101     "Usage: ss7 version\n",
00102     NULL
00103   },
00104 
00105   { { "ss7", "dump", "start", NULL}, cmd_dump_start,
00106     "Start raw MTP2 dump to a file",
00107     "Usage: ss7 dump start <file> [in|out|both] [fisu] [lssu] [msu]\n"
00108     "       Start raw mtp2 dump to file. Either incoming, outgoing, or both(default).\n"
00109     "       Optinally specify which of fisu, lssu, and msu should be dumped.\n"
00110     "       The output can be converted with `text2pcap -t %s. -l 140' and\n"
00111     "       subsequently fed to Ethereal for protocol decoding.\n",
00112     complete_dump_start
00113   },
00114 
00115   { {"ss7", "dump", "stop", NULL}, cmd_dump_stop,
00116     "Stop a running raw MTP2 dump",
00117     "Usage: ss7 dump stop [in|out|both]\n"
00118     "       Stop raw mtp2 dump started with \"ss7 start dump\". Either incoming,\n"
00119     "       outgoing, or both(default).\n",
00120     complete_dump_stop
00121   },
00122 
00123   { {"ss7", "dump", "status", NULL}, cmd_dump_status,
00124     "Stop what dumps are running",
00125     "Usage: ss7 dump status\n",
00126     NULL
00127   },
00128 
00129 #ifndef MODULETEST
00130   { {"ss7", "link", "down", NULL}, cmd_link_down,
00131     "Stop the MTP2 link(s) [logical-link-no]...",
00132     "Usage: ss7 link down [logical-link-no]\n"
00133     "       Take the link(s) down; it will be down until started explicitly with\n"
00134     "       'ss7 link up'.\n"
00135     "       Until then, it will continuously transmit LSSU 'OS' (out-of-service)\n"
00136     "       frames.\n"
00137     "       If no logical-link-no argument is given, all links are affected.\n",
00138     NULL
00139   },
00140 
00141   { {"ss7", "link", "up", NULL}, cmd_link_up,
00142     "Start the MTP2 link(s) [logical-link-no]...",
00143     "Usage: ss7 link up\n"
00144     "       Attempt to take the MTP2 link(s) up with the initial alignment procedure.\n"
00145     "       If no logical-link-no argument is given, all links are affected.\n",
00146     NULL
00147   },
00148 
00149   { {"ss7", "link", "status", NULL}, cmd_link_status,
00150     "Show status of the MTP2 links",
00151     "Usage: ss7 link status\n"
00152     "       Show the status of the MTP2 links.\n",
00153     NULL
00154   },
00155 #endif
00156 
00157   { {"ss7", "block", NULL}, cmd_block,
00158     "Set circuits in local maintenance blocked mode",
00159     "Usage: ss7 block <first> <count> [<linksetname>]\n"
00160     "       Set <count> lines into local maintenance blocked mode, starting at circuit <first>on linkset <linksetname>\n",
00161     NULL
00162   },
00163 
00164   { {"ss7", "unblock", NULL}, cmd_unblock,
00165     "Remove local maintenance blocked mode from circuits",
00166     "Usage: ss7 unblock <first> <count> [<linksetname>]\n"
00167     "       Remove <count> lines from local maintenance blocked mode, starting at circuit <first> on linkset <linksetname>.\n",
00168     NULL
00169   },
00170 
00171   { {"ss7", "linestat", NULL}, cmd_linestat,
00172     "Show line states",
00173     "Usage: ss7 linestat\n"
00174     "       Show status for all circuits.\n",
00175     NULL
00176   },
00177 
00178   { {"ss7", "show", "channels", NULL}, cmd_linestat,
00179     "Show channel states",
00180     "Usage: ss7 show channels\n"
00181     "       Show status for all channels.\n",
00182     NULL
00183   },
00184 
00185   { {"ss7", "cluster", "start", NULL}, cmd_cluster_start,
00186     "Start cluster",
00187     "Usage: ss7 cluster start\n"
00188     "       Start the cluster.\n",
00189     NULL
00190   },
00191 
00192   { {"ss7", "cluster", "stop", NULL}, cmd_cluster_stop,
00193     "Stop cluster",
00194     "Usage: ss7 cluster stop\n"
00195     "       Stop the cluster.\n",
00196     NULL
00197   },
00198 
00199   { {"ss7", "cluster", "status", NULL}, cmd_cluster_status,
00200     "Show status of the cluster",
00201     "Usage: ss7 cluster status\n"
00202     "       Show the status of the cluster.\n",
00203     NULL
00204   },
00205 
00206   { {"ss7", "reset", NULL}, cmd_reset,
00207     "Reset all circuits",
00208     "Usage: ss7 reset\n"
00209     "       Reset all circuits.\n",
00210     NULL
00211   },
00212 
00213   { { "ss7", "mtp", "data", NULL}, mtp_cmd_data,
00214     "Copy hex encoded string to MTP",
00215     "Usage: ss7 mtp data string\n"
00216     "       Copy hex encoded string to MTP",
00217     NULL,
00218   },
00219 
00220 #ifdef MODULETEST
00221   { {"ss7", "testfailover", NULL}, cmd_testfailover,
00222     "Test the failover mechanism",
00223     "Usage: ss7 testfailover"
00224     "       Test the failover mechanism.\n",
00225     NULL
00226   },
00227   { {"ss7", "moduletest", NULL}, cmd_moduletest,
00228     "Run a moduletest",
00229     "Usage: ss7 moduletest <no>"
00230     "       Run moduletest <no>.\n",
00231     NULL
00232   },
00233 #endif
00234 };
00235 
00236 
00237 /* Queue a request to the MTP thread. */
00238 static void mtp_enqueue_control(struct mtp_req *req) {
00239   int res;
00240 
00241   ast_mutex_lock(&mtp_control_mutex);
00242   res = lffifo_put(mtp_control_fifo, (unsigned char *)req, sizeof(struct mtp_req) + req->len);
00243   ast_mutex_unlock(&mtp_control_mutex);
00244   if(res != 0) {
00245     ast_log(LOG_WARNING, "MTP control fifo full (MTP thread hanging?).\n");
00246   }
00247 }
00248 
00249 
00250 static int start_mtp_thread(void)
00251 {
00252   return start_thread(&mtp_thread, mtp_thread_main, &mtp_thread_running, 15);
00253 }
00254 
00255 static void stop_mtp_thread(void)
00256 {
00257     mtp_thread_signal_stop();
00258     stop_thread(mtp_thread, &mtp_thread_running);
00259 }
00260 
00261 static int cmd_link_up_down(int fd, int argc, char *argv[], int updown) {
00262   static unsigned char buf[sizeof(struct mtp_req)];
00263   struct mtp_req *req = (struct mtp_req *)buf;
00264   int i;
00265 
00266   req->typ = updown;
00267   req->len = sizeof(req->link);
00268   if(argc > 3) {
00269     for (i = 3; i < argc; i++) {
00270       int link_ix = atoi(argv[i]);
00271       ast_log(LOG_DEBUG, "MPT control link %s %d\n", updown == MTP_REQ_LINK_UP ? "up" : "down", link_ix);
00272       if (link_ix >= this_hosts_linkset.n_schannels) {
00273    ast_log(LOG_ERROR, "Link index out of range %d, max %d.\n", link_ix, this_hosts_linkset.n_schannels);
00274    return RESULT_FAILURE;
00275       }
00276       req->link.link_ix = link_ix;
00277       mtp_enqueue_control(req);
00278     }
00279   }
00280   else {
00281     for (i=0; i < this_hosts_linkset.n_schannels; i++) {
00282       ast_log(LOG_DEBUG, "MTP control link %s %d\n", updown == MTP_REQ_LINK_UP ? "up" : "down", i);
00283       req->link.link_ix = i;
00284       mtp_enqueue_control(req);
00285     }
00286   }
00287   return RESULT_SUCCESS;
00288 }
00289 
00290 
00291 static int cmd_link_down(int fd, int argc, char *argv[]) {
00292   return cmd_link_up_down(fd, argc, argv, MTP_REQ_LINK_DOWN);
00293 }
00294 
00295 
00296 static int cmd_link_up(int fd, int argc, char *argv[]) {
00297   return cmd_link_up_down(fd, argc, argv, MTP_REQ_LINK_UP);
00298 }
00299 
00300 
00301 static int cmd_link_status(int fd, int argc, char *argv[]) {
00302   char buff[256];
00303   int i;
00304 
00305   for (i = 0; i < this_hosts_linkset.n_schannels; i++) {
00306     if (this_hosts_linkset.schannels[i]->enabled) {
00307       if (mtp_cmd_linkstatus(buff, i) == 0)
00308    ast_cli(fd, buff);
00309     }
00310   }
00311   return RESULT_SUCCESS;
00312 }
00313 
00314 
00315 static char *complete_generic(char *word, int state, char **options, int entries) {
00316   int which = 0;
00317   int i;
00318 
00319   for(i = 0; i < entries; i++) {
00320     if(0 == strncasecmp(word, options[i], strlen(word))) {
00321       if(++which > state) {
00322         return strdup(options[i]);
00323       }
00324     }
00325   }
00326   return NULL;
00327 }
00328 
00329 static char *dir_options[] = { "in", "out", "both", };
00330 static char *filter_options[] = { "fisu", "lssu", "msu", };
00331 
00332 static char *complete_dump_start(char *line, char *word, int pos, int state) {
00333   if(pos == 4) {
00334     return complete_generic(word, state, dir_options,
00335                             sizeof(dir_options)/sizeof(dir_options[0]));
00336   } else if(pos > 4) {
00337     return complete_generic(word, state, filter_options,
00338                             sizeof(filter_options)/sizeof(filter_options[0]));
00339   } else {
00340     /* We won't attempt to complete file names, that's not worth it. */
00341     return NULL;
00342   }
00343 }
00344 
00345 static char *complete_dump_stop(char *line, char *word, int pos, int state) {
00346   if(pos == 3) {
00347     return complete_generic(word, state, dir_options,
00348                             sizeof(dir_options)/sizeof(dir_options[0]));
00349   } else {
00350     return NULL;
00351   }
00352 }
00353 
00354 static int cmd_dump_start(int fd, int argc, char *argv[]) {
00355   int in, out;
00356   int i;
00357   int fisu,lssu,msu;
00358   FILE *fh;
00359 
00360   if(argc < 4) {
00361     return RESULT_SHOWUSAGE;
00362   }
00363 
00364   if(argc == 4) {
00365     in = 1;
00366     out = 1;
00367   } else {
00368     if(0 == strcasecmp(argv[4], "in")) {
00369       in = 1;
00370       out = 0;
00371     } else if(0 == strcasecmp(argv[4], "out")) {
00372       in = 0;
00373       out = 1;
00374     } else if(0 == strcasecmp(argv[4], "both")) {
00375       in = 1;
00376       out = 1;
00377     } else {
00378       return RESULT_SHOWUSAGE;
00379     }
00380   }
00381 
00382   ast_mutex_lock(&dump_mutex);
00383   if((in && dump_in_fh != NULL) || (out && dump_out_fh != NULL)) {
00384     ast_cli(fd, "Dump already running, must be stopped (with 'ss7 stop dump') "
00385             "before new can be started.\n");
00386     ast_mutex_unlock(&dump_mutex);
00387     return RESULT_FAILURE;
00388   }
00389 
00390   if(argc <= 5) {
00391     fisu = 0;
00392     lssu = 0;
00393     msu = 1;
00394   } else {
00395     fisu = 0;
00396     lssu = 0;
00397     msu = 0;
00398     for(i = 5; i < argc; i++) {
00399       if(0 == strcasecmp(argv[i], "fisu")) {
00400         fisu = 1;
00401       } else if(0 == strcasecmp(argv[i], "lssu")) {
00402         lssu = 1;
00403       } else if(0 == strcasecmp(argv[i], "msu")) {
00404         msu = 1;
00405       } else {
00406         ast_mutex_unlock(&dump_mutex);
00407         return RESULT_SHOWUSAGE;
00408       }
00409     }
00410   }
00411 
00412   fh = fopen(argv[3], "w");
00413   if(fh == NULL) {
00414     ast_cli(fd, "Error opening file '%s': %s.\n", argv[3], strerror(errno));
00415     ast_mutex_unlock(&dump_mutex);
00416     return RESULT_FAILURE;
00417   }
00418 
00419   if(in) {
00420     dump_in_fh = fh;
00421   }
00422   if(out) {
00423     dump_out_fh = fh;
00424   }
00425   dump_do_fisu = fisu;
00426   dump_do_lssu = lssu;
00427   dump_do_msu = msu;
00428 
00429   ast_mutex_unlock(&dump_mutex);
00430   return RESULT_SUCCESS;
00431 }
00432 
00433 static int cmd_dump_stop(int fd, int argc, char *argv[]) {
00434   int in, out;
00435 
00436   if(argc == 3) {
00437     in = 1;
00438     out = 1;
00439   } else if(argc == 4) {
00440     if(0 == strcasecmp(argv[3], "in")) {
00441       in = 1;
00442       out = 0;
00443     } else if(0 == strcasecmp(argv[3], "out")) {
00444       in = 0;
00445       out = 1;
00446     } else if(0 == strcasecmp(argv[3], "both")) {
00447       in = 1;
00448       out = 1;
00449     } else {
00450       return RESULT_SHOWUSAGE;
00451     }
00452   } else {
00453     return RESULT_SHOWUSAGE;
00454   }
00455 
00456   ast_mutex_lock(&dump_mutex);
00457 
00458   if((in && !out && dump_in_fh == NULL) ||
00459      (out && !in && dump_out_fh == NULL) ||
00460      (in && out && dump_in_fh == NULL && dump_out_fh == NULL)) {
00461     ast_cli(fd, "No dump running.\n");
00462     ast_mutex_unlock(&dump_mutex);
00463     return RESULT_SUCCESS;
00464   }
00465 
00466   if(in && dump_in_fh != NULL) {
00467     if(dump_out_fh == dump_in_fh) {
00468       /* Avoid closing it twice. */
00469       dump_out_fh = NULL;
00470     }
00471     fclose(dump_in_fh);
00472     dump_in_fh = NULL;
00473   }
00474   if(out && dump_out_fh != NULL) {
00475     fclose(dump_out_fh);
00476     dump_out_fh = NULL;
00477   }
00478 
00479   ast_mutex_unlock(&dump_mutex);
00480   return RESULT_SUCCESS;
00481 }
00482 
00483 static int cmd_dump_status(int fd, int argc, char *argv[]) {
00484   ast_mutex_lock(&dump_mutex);
00485 
00486   /* ToDo: This doesn't seem to work, the output is getting lost somehow.
00487      Not sure why, but could be related to ast_carefulwrite() called in
00488      ast_cli(). */
00489   ast_cli(fd, "Yuck! what is going on here?!?\n");
00490   if(dump_in_fh != NULL) {
00491     ast_cli(fd, "Dump of incoming frames is running.\n");
00492   }
00493   if(dump_out_fh != NULL) {
00494     ast_cli(fd, "Dump of outgoing frames is running.\n");
00495   }
00496   if(dump_in_fh != NULL || dump_out_fh != NULL) {
00497     ast_cli(fd, "Filter:%s%s%s.\n",
00498             (dump_do_fisu ? " fisu" : ""),
00499             (dump_do_lssu ? " lssu" : ""),
00500             (dump_do_msu ? " msu" : ""));
00501   }
00502 
00503   ast_mutex_unlock(&dump_mutex);
00504   return RESULT_SUCCESS;
00505 }
00506 
00507 
00508 static int cmd_version(int fd, int argc, char *argv[]) {
00509 
00510   ast_cli(fd, "chan_ss7 version %s\n", CHAN_SS7_VERSION);
00511 
00512   return RESULT_SUCCESS;
00513 }
00514 
00515 
00516 /* Monitor thread main loop.
00517    Monitor reads events from the realtime MTP thread, and processes them at
00518    non-realtime priority. It also handles timers for ISUP etc.
00519 */
00520 static void *monitor_main(void *data) {
00521   int res;
00522   struct pollfd fds[1];
00523   struct lffifo *receive_fifo = mtp_get_receive_fifo();
00524   FILE *dump_fh;
00525   int i;
00526 
00527   ast_verbose(VERBOSE_PREFIX_3 "Starting monitor thread, pid=%d.\n", getpid());
00528 
00529   fds[0].fd = mtp_get_receive_pipe();
00530   fds[0].events = POLLIN;
00531 
00532   while(monitor_running) {
00533     int timeout = timers_wait();
00534     fds[0].revents = 0;
00535 
00536     res = poll(fds, 1, timeout);
00537     if(res < 0) {
00538       if(errno == EINTR) {
00539         /* Just try again. */
00540       } else {
00541         ast_log(LOG_ERROR, "poll() failure, errno=%d: %s\n",
00542                 errno, strerror(errno));
00543       }
00544     } else if(res > 0) {
00545       /* Events waiting in the receive buffer. */
00546       unsigned char dummy[512];
00547       unsigned char eventbuf[MTP_EVENT_MAX_SIZE];
00548       struct mtp_event *event;
00549 
00550       /* Empty the pipe before pulling from fifo. This way the race
00551          condition between mtp and monitor threads may cause spurious
00552          wakeups, but not loss/delay of messages. */
00553       read(fds[0].fd, dummy, sizeof(dummy));
00554 
00555       /* Process all available events. */
00556       while((res = lffifo_get(receive_fifo, eventbuf, sizeof(eventbuf))) != 0) {
00557         if(res < 0) {
00558           ast_log(LOG_ERROR, "Yuck! oversized frame in receive fifo, bailing out.\n");
00559           return NULL;
00560         }
00561         event = (struct mtp_event *)eventbuf;
00562         switch(event->typ) {
00563      case MTP_EVENT_ISUP:
00564        l4isup_event(event);
00565             break;
00566      case MTP_EVENT_SCCP:
00567 #ifdef SCCP
00568        l4sccp_event(event);
00569 #endif
00570             break;
00571        
00572      case MTP_EVENT_LOG:
00573             ast_log(event->log.level, event->log.file, event->log.line,
00574                     event->log.function, "%s", event->buf);
00575             break;
00576 
00577           case MTP_EVENT_DUMP:
00578             ast_mutex_lock(&dump_mutex);
00579 
00580             if(event->dump.out) {
00581               dump_fh = dump_out_fh;
00582             } else {
00583               dump_fh = dump_in_fh;
00584             }
00585             if(dump_fh != NULL) {
00586               if(event->len < 3 ||
00587                  ( !(event->buf[2] == 0 && !dump_do_fisu) &&
00588                    !((event->buf[2] == 1 || event->buf[2] == 2) && !dump_do_lssu) &&
00589                    !(event->buf[2] > 2 && !dump_do_msu))) {
00590                 fprintf(dump_fh, "%.6f 0%s", event->dump.position/8000,
00591                         event->dump.out ? "\t\t" : "");
00592                 for(i=0; i < event->len; i++) {
00593                   fprintf(dump_fh, " %02x", event->buf[i]);
00594                 }
00595                 fprintf(dump_fh, "\n");
00596       fflush(dump_fh);
00597               }
00598             }
00599 
00600             ast_mutex_unlock(&dump_mutex);
00601             break;
00602 
00603           case MTP_EVENT_RAWDUMP:
00604 #if 0
00605             /* ToDo: This may be useful for debugging in a pinch, but is not
00606                production quality. */
00607             {
00608               FILE * f = fopen(event->rawdump.out ? "/tmp/out" : "/tmp/in", "ab");
00609               if(f) {
00610                 fwrite(event->buf, 1, event->len, f);
00611                 fclose(f);
00612               } else {
00613                 ast_log(LOG_WARNING, "Error opening raw dump output: %s.\n",
00614                         strerror(errno));
00615               }
00616             }
00617 #endif
00618             break;
00619 
00620           case MTP_EVENT_STATUS:
00621        {
00622          struct link* link = event->status.link;
00623          char* name = link ? link->name : "(peer)";
00624          switch(event->status.link_state) {
00625               case MTP_EVENT_STATUS_LINK_UP:
00626       l4isup_link_status_change(link, 1);
00627 #ifdef SCCP
00628       l4sccp_link_status_change(link, 1);
00629 #endif
00630                 ast_log(LOG_WARNING, "MTP is now UP on link '%s'.\n", name);
00631                 break;
00632               case MTP_EVENT_STATUS_LINK_DOWN:
00633       l4isup_link_status_change(link, 0);
00634 #ifdef SCCP
00635       l4sccp_link_status_change(link, 0);
00636 #endif
00637                 ast_log(LOG_WARNING, "MTP is now DOWN on link '%s'.\n", name);
00638                 break;
00639               case MTP_EVENT_STATUS_INSERVICE:
00640                 ast_log(LOG_WARNING, "MTP is now INSERVICE for linkset '%s'.\n", link->linkset->name);
00641       l4isup_inservice(link);
00642 #ifdef SCCP
00643       l4sccp_inservice(link);
00644 #endif
00645       break;
00646               default:
00647                 ast_log(LOG_NOTICE, "Unknown event type STATUS (%d), "
00648                         "not processed.\n", event->status.link_state);
00649          }
00650        }
00651             break;
00652 
00653           default:
00654             ast_log(LOG_NOTICE, "Unexpected mtp event type %d.\n", event->typ);
00655         }
00656       }
00657     }
00658 
00659     /* We need to lock the global glock mutex around ast_sched_runq() so that
00660        we avoid a race with ss7_hangup. With the lock, invalidating the
00661        channel in ss7_hangup() and removing associated monitor_sched entries
00662        is an atomic operation, so that we avoid calling timer handlers with
00663        references to invalidated channels. */
00664     run_timers();
00665   }
00666   return NULL;
00667 }
00668 
00669 
00670 static void stop_monitor(void) {
00671   if(monitor_running) {
00672     monitor_running = 0;
00673     /* Monitor wakes up every 1/2 sec, so no need to signal it explicitly. */
00674     pthread_join(monitor_thread, NULL);
00675   }
00676 }
00677 
00678 static int load_module(void)
00679 {
00680   int i;
00681 
00682   if(load_config(0)) {
00683     return AST_MODULE_LOAD_DECLINE;
00684   }
00685 
00686   if (timers_init()) {
00687     ast_log(LOG_ERROR, "Unable to initialize timres.\n");
00688     return AST_MODULE_LOAD_FAILURE;
00689   }
00690   isup_init();
00691 #ifdef SCCP
00692   sccp_init();
00693 #endif
00694 
00695   if(mtp_init()) {
00696     ast_log(LOG_ERROR, "Unable to initialize MTP.\n");
00697     return AST_MODULE_LOAD_FAILURE;
00698   }
00699   if(start_mtp_thread()) {
00700     ast_log(LOG_ERROR, "Unable to start MTP thread.\n");
00701     return AST_MODULE_LOAD_FAILURE;
00702   }
00703   mtp_control_fifo = mtp_get_control_fifo();
00704 
00705   monitor_running = 1;          /* Otherwise there is a race, and
00706                                    monitor may exit immediately */
00707   if(ast_pthread_create(&monitor_thread, NULL, monitor_main, NULL) < 0) {
00708     ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
00709     monitor_running = 0;
00710     return AST_MODULE_LOAD_FAILURE;
00711   }
00712 
00713 
00714   ast_cli_register_multiple(my_clis, sizeof(my_clis)/ sizeof(my_clis[0]));
00715 
00716   ast_verbose(VERBOSE_PREFIX_3 "SS7 channel loaded successfully.\n");
00717   return AST_MODULE_LOAD_SUCCESS;
00718 }
00719 
00720 static int unload_module(void)
00721 {
00722   ast_cli_unregister_multiple(my_clis, sizeof(my_clis)/ sizeof(my_clis[0]));
00723 
00724 #ifdef SCCP
00725   sccp_cleanup();
00726 #endif
00727   isup_cleanup();
00728 
00729   ast_mutex_lock(&dump_mutex);
00730   if(dump_in_fh != NULL) {
00731     if(dump_in_fh == dump_out_fh) {
00732       dump_out_fh = NULL;
00733     }
00734     fclose(dump_in_fh);
00735     dump_in_fh = NULL;
00736   }
00737   if(dump_out_fh != NULL) {
00738     fclose(dump_out_fh);
00739     dump_out_fh = NULL;
00740   }
00741   ast_mutex_unlock(&dump_mutex);
00742 
00743   if(monitor_running) {
00744     stop_monitor();
00745   }
00746   stop_mtp_thread();
00747   mtp_cleanup();
00748   timers_cleanup();
00749 
00750 
00751   destroy_config();
00752   ast_verbose(VERBOSE_PREFIX_3 "SS7 channel unloaded.\n");
00753   return 0;
00754 }
00755 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, desc);
00756 

Generated on Mon May 14 04:42:54 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1