⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chan_ss7.c

📁 asterisk1.4.6版本下 7#信令驱动 源码
💻 C
📖 第 1 页 / 共 2 页
字号:

  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 + -