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

📄 mtp.c

📁 asterisk 中国七号驱动修改代码可以在ASTERISIK-1。4上编译pa
💻 C
📖 第 1 页 / 共 5 页
字号:
/* mtp.c - MTP2 and MTP3 functionality. * * Copyright (C) 2005-2006, Sifira A/S. * * Author: Kristian Nielsen <kn@sifira.dk> *         Anders Baekgaard <ab@sifira.dk> *         Anders Baekgaard <ab@dicea.dk> * * This file is part of chan_ss7. * * chan_ss7 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * chan_ss7 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with chan_ss7; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */#include <stdarg.h>#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <netdb.h>#include <netinet/in.h>#include <pthread.h>#include <signal.h>#include <sys/poll.h>#include <sys/ioctl.h>#include <sys/time.h>#include "zaptel.h"#define FAST_HDLC_NEED_TABLES#include "fasthdlc.h"#include "config.h"#include "mtp.h"#include "transport.h"#include "lffifo.h"#include "cluster.h"#include "utils.h"#ifdef MTP_STANDALONE#include "aststubs.h"#define cluster_mtp_received(link, event) {}#define cluster_mtp_forward(req) {}#define cluster_receivers_alive(linkset) (0)#else#include "asterisk/options.h"#include "asterisk/logger.h"#include "asterisk/sched.h"#define mtp_sched_add ast_sched_add#define mtp_sched_del ast_sched_del#define mtp_sched_runq ast_sched_runq#define mtp_sched_context_create sched_context_create#define mtp_sched_context_destroy sched_context_destroy#endif/* NOTE: most of this code is run in the MTP thread, and has realtime   constraints because of the need to constantly feed/read the   signalling link with low latence and no frame drop.   The thread runs with high realtime priority, and any kind of   locking should generally be avoided. This includes ast_log() (use   fifo_log() instead), and malloc()/free()!*//* For testing failover mechanism */int testfailover = 0;/* #define DROP_PACKETS_PCT 66 *//* #define DO_RAW_DUMPS *//* Scheduling context for MTP2. *//* This should ONLY be used by the MTP2 thread, otherwise the locking done   by the sched operations may fatally delay the MTP2 thread because of   priority inversion. */static struct sched_context *mtp2_sched = NULL;/* Set true to ask mtp thread to stop */static int stop_mtp_thread;static int receivepipe[2];/* Lock-free FIFOs for communication with the MTP thread.   The sendbuf is polled by the MTP thread whenever the link is ready to   transmit data (every 2msec). It contains struct mtp_req entries for   the higher level protocol layers (currently only ISUP).   The receivebuf has an associated event pipe, and the MTP thread do   non-blocking dummy writes to it whenever blocks are put in the buffer.   The SS7 monitor thread can then wait for new data in poll(). The   receivebuf contains struct mtp_event entries.   The controlbuf is polled by the MTP thread, it contains struct mtp_req   entries for control purposes only. */struct lffifo *sendbuf[MAX_LINKSETS];struct lffifo *receivebuf;struct lffifo *controlbuf;typedef struct mtp2_state {  /* MTP2 stuff. */  enum {    /* Link is stopped by management command, will not go up until       started explicitly. */    MTP2_DOWN,    /* Initial alignment has started, link is transmitting 'O', but no 'O',       'N', or 'E' has been received. */    MTP2_NOT_ALIGNED,    /* 'O' has been received, 'N' or 'E' is transmitted. */    MTP2_ALIGNED,    /* 'N' or 'E' is transmitted and received. Runs for the duration of T4 to       check that the link is of sufficient quality in terms of error rate. */    MTP2_PROVING,    /* Local T4 expired, and we are sending FISU, but remote is still       proving. */    MTP2_READY,    /* The link is active sending and receiving FISU and MSU. */    MTP2_INSERVICE,  } state;  /* Counts of raw bytes read and written, used to timestamp raw dumps.     Make them double to avoid overflow for quite a while. */  double readcount, writecount;  /* Sequence numbers and indicator bits to be sent in signalling units. */  int send_fib;  int send_bsn, send_bib;  /* Send initial SLTM? */  int send_sltm;  /* Timeslot for signalling channel */  int schannel;  int slinkno;  struct link* link;  int sls;  int subservice;  /* logical link name */  char* name;  /* Open fd for signalling link zaptel device. */  int fd;  /* Receive buffer. */  unsigned char rx_buf[272 + 7];  int rx_len;  unsigned short rx_crc;  /* Transmit buffer. */  unsigned char tx_buffer[272 + 7 + 5];  int tx_len;  int tx_sofar;  int tx_do_crc;                /* Flag used to handle writing CRC bytes */  unsigned short tx_crc;  /* Zaptel transmit buffer. */  unsigned char zap_buf[ZAP_BUF_SIZE];  int zap_buf_full;  /* HDLC encoding and decoding state. */  struct fasthdlc_state h_rx;  struct fasthdlc_state h_tx;  /* Last few raw bytes received, for debugging link errors. */  unsigned char backbuf[36];  int backbuf_idx;  /* Retransmit buffer. */  struct { int len; unsigned char buf[MTP_MAX_PCK_SIZE]; } retrans_buf[128];  /* Retransmit counter; if this is != -1, it means that retransmission is     taking place, with this being the next sequence number to retransmit. */  int retrans_seq;  /* Last sequence number ACK'ed by peer. */  int retrans_last_acked;  /* Last sequence number sent to peer. */  int retrans_last_sent;  /* Counter for signal unit/alignment error rate monitors (Q.703 (10)). */  int error_rate_mon;  /* Counters matching the D and N values of the error rate monitors. */  int emon_ncount, emon_dcount;  /* Counter for bad BSN */  int bsn_errors;  /* Q.703 timer T1 "alignment ready" (waiting for peer to end initial     alignment after we are done). */  int mtp2_t1;  /* Q.703 timer T2 "not aligned" (waiting to receive O, E, or N after sending     O). */  int mtp2_t2;  /* Q.703 timer T3 "aligned" (waiting to receive E or N after sending E or     N). */  int mtp2_t3;  /* Q.703 timer T4 "proving period" - proving time before ending own initial     alignment. */  int mtp2_t4;  /* Q.703 timer T7 "excessive delay of acknowledgement" . */  int mtp2_t7;  /* Set true when SLTA is received and User Parts (ie. ISUP) is notified that     the link is now in service. */  int level4_up;  /* Hm, the rest is actually MTP3 state. Move to other structure, or     rename this structure. */  int sltm_t1;                  /* Timer T1 for SLTM (Q.707) */  int sltm_t2;                  /* Timer T2 for SLTM (Q.707) */  int sltm_tries;               /* For SLTM retry (Q.707 (2.2)) */  /* Q.704 timer T17, "initial alignment restart delay". */  int mtp3_t17;} mtp2_t;/* ToDo: Support more than one signalling link ... *//* ToDo: Need real initialization, that doesn't depend on linker. */mtp2_t mtp2_state[MAX_SCHANNELS];/* Get the next sequence number, modulo 128. */#define MTP_NEXT_SEQ(x) (((x) + 1) % 128)/* Forward declaration, needed because of cyclic reference graph. */static mtp2_t* find_alternative_slink(mtp2_t* m);static void start_initial_alignment(mtp2_t *m, char* reason);static void abort_initial_alignment(mtp2_t *m);static void mtp2_cleanup(mtp2_t *m);static void mtp2_queue_msu(mtp2_t *m, int sio, unsigned char *sif, int len);static void deliver_l4(mtp2_t *m, unsigned char *sif, int len, int sio);static void l4up(mtp2_t* m);static void l4down(mtp2_t* m);static void t7_stop(mtp2_t *m);static void fifo_log(mtp2_t *m, int level, const char *file, int line,		     const char *function, const char *format, ...)     __attribute__ ((format (printf, 6, 7)));static void process_msu(struct mtp2_state* m, unsigned char* buf, int len);int mtp2_slink_inservice(int ix) {  struct mtp2_state* m = &mtp2_state[ix];  return m->state == MTP2_INSERVICE;}int mtp_cmd_linkstatus(char* buff, int slinkno){  char* format = "linkset %s, link %s, schannel %d, sls %d, %s, rx: %d, tx: %d/%d, sentseq/lastack: %d/%d, total %9llu, %9llu\n";  char* s = "?";  if (slinkno >= this_host->n_schannels)    return -1;  /* Todo: when more than one signalling link supported, check against that */  struct mtp2_state* m = &mtp2_state[slinkno];  switch (m->state) {  case MTP2_DOWN: s = "DOWN"; break;  case MTP2_NOT_ALIGNED: s = "NOT_ALIGNED"; break;  case MTP2_ALIGNED: s = "ALIGNED"; break;  case MTP2_PROVING: s = "PROVING"; break;  case MTP2_READY: s = "READY"; break;  case MTP2_INSERVICE: s = "INSERVICE"; break;  default: s = "UNKNOWN";  }  sprintf(buff, format, m->link->linkset->name, m->link->name, m->schannel, m->sls, s, m->rx_len, m->tx_sofar, m->tx_len, m->retrans_last_sent, m->retrans_last_acked, (long long) m->readcount, (long long) m->writecount);  return 0;}int mtp_cmd_data(int fd, int argc, char *argv[]){  unsigned char buf[MTP_EVENT_MAX_SIZE];  int len = 0;  int i;  mtp2_t* m = &mtp2_state[0];  for (i = 3; i < argc; i++) {    char* p = argv[i];    while (*p) {      char b[3];      unsigned int v;      if (*p == ' ') {	p++;	continue;      }      b[0] = *p++;      b[1] = *p++;      b[2] = 0;      sscanf(b, "%x", &v);      buf[len++] = v;    }  }  mtp2_queue_msu(m, 3, buf, len);  deliver_l4(m, &buf[0], len, MTP_EVENT_SCCP);  return 0;}static inline int peerpc(mtp2_t* m){  return m->link->linkset->dpc;}static inline int linkpeerpc(mtp2_t* m){  if (m->link->dpc)    return m->link->dpc;  return m->link->linkset->dpc;}static mtp2_t* findtargetslink(mtp2_t *originalm, int sls){  int i;  struct link* link = originalm->link;  struct mtp2_state* bestm = NULL;  for (i = 0; i < this_host->n_schannels; i++) {    struct mtp2_state* m = &mtp2_state[i];    struct link* slink = m->link;    if (m->sls == sls) {      if (link->linkset == slink->linkset) {	fifo_log(m, LOG_DEBUG, "Target slink %s %d -> %s\n", originalm->name, sls, m->name);        return m;      }      if (is_combined_linkset(link->linkset, slink->linkset))        bestm = m;    }  }  fifo_log(originalm, LOG_DEBUG, "Target slink %s %d -> %s\n", originalm->name, sls, bestm ? bestm->name : "(none)");  return bestm;}static void mtp_put(mtp2_t *m, struct mtp_event *event) {  static int log_safe_count = 0;  int res;  res = lffifo_put(receivebuf, (unsigned char *)event,                   sizeof(*event) + event->len);  if(res) {    /* Can't fifo_log() here, or we would get an infinite loop. */    /* Still, avoid excessive logging if the other thread gets long behind. */    if(log_safe_count == 0) {      ast_log(LOG_NOTICE, "Full MTP receivebuf, event lost, type=%d.\n", event->typ);      log_safe_count = 2000;    }  } else {    /* Wake up the other end. */    write(receivepipe[1], "\0", 1);  }  if ((event->typ == MTP_EVENT_ISUP) || (event->typ == MTP_EVENT_STATUS)) {    cluster_mtp_received(m ? m->link : NULL, event);  }  if(log_safe_count > 0) {    log_safe_count--;  }}/* Use this instead of ast_log() in the MTP thread, to avoid locking   issues interupting the link timing.   Note that LOG_WHATEVER includes all of (level, file, line, function), thanks   to #define trickery in asterisk/logger.h! *//* Grmble... stupid GCC allows the __attribute__ only in a   declaration, not definition. */static void fifo_log(mtp2_t *m, int level, const char *file, int line,		     const char *function, const char *format, ...){  va_list arg;  unsigned char buf[MTP_EVENT_MAX_SIZE];  struct mtp_event *event = (struct mtp_event *)buf;  event->typ = MTP_EVENT_LOG;  event->log.level = level;  event->log.file = file;  event->log.line = line;  event->log.function = function;  va_start(arg, format);  vsnprintf((char*)event->buf, sizeof(buf) - sizeof(struct mtp_event), format, arg);  va_end(arg);  event->len = strlen((char*)event->buf) + 1;  mtp_put(m, event);}static void log_frame(mtp2_t *m, int out, unsigned char *buf, int len) {  unsigned char ebuf[MTP_EVENT_MAX_SIZE];  struct mtp_event *event = (struct mtp_event *)ebuf;  event->typ = MTP_EVENT_DUMP;  event->dump.out = out;  gettimeofday(&event->dump.stamp, NULL);  event->dump.slinkno = m->slinkno;  if(sizeof(struct mtp_event) + len > MTP_MAX_PCK_SIZE) {    len = MTP_MAX_PCK_SIZE - sizeof(struct mtp_event);  }  event->len = len;  memcpy(event->buf, buf, len);  mtp_put(m, event);}#ifdef DO_RAW_DUMPSstatic void mtp2_dump_raw(mtp2_t *m, unsigned char *buf, int len, int out) {  unsigned char ebuf[MTP_EVENT_MAX_SIZE];  struct mtp_event *event = (struct mtp_event *)ebuf;  event->typ = MTP_EVENT_RAWDUMP;  event->rawdump.out = out;  if(sizeof(struct mtp_event) + len > MTP_MAX_PCK_SIZE) {    len = MTP_MAX_PCK_SIZE - sizeof(struct mtp_event);  }  event->len = len;  memcpy(event->buf, buf, len);  mtp_put(m, event);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -