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

📄 mtp.c

📁 asterisk1.4.6版本下 7#信令驱动 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  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_DUMPS
static 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

static int t17_timeout(void *data) {
  mtp2_t *m = data;
  fifo_log(m, LOG_DEBUG, "link %s\n", m->name);
  m->mtp3_t17 = -1;
  start_initial_alignment(m, "t17_timeout");
  return 0;                     /* Do not re-schedule */
}

static void t17_stop(mtp2_t *m) {
  if(m->mtp3_t17 != -1) {
    mtp_sched_del(mtp2_sched, m->mtp3_t17);
    m->mtp3_t17 = -1;
  }
}

static void t17_start(mtp2_t *m) {
  t17_stop(m);
  m->mtp3_t17 = mtp_sched_add(mtp2_sched, 1200, t17_timeout, m);
}

static int t1_timeout(void *data) {
  mtp2_t *m = data;
  fifo_log(m, LOG_WARNING, "MTP2 timer T1 timeout (peer failed to complete "
	   "initial alignment), initial alignment failed on link '%s'.\n", m->name);
  m->mtp2_t1 = -1;
  abort_initial_alignment(m);
  return 0;                     /* Do not re-schedule */
}

static void t1_stop(mtp2_t *m) {
  if(m->mtp2_t1 != -1) {
    mtp_sched_del(mtp2_sched, m->mtp2_t1);
    m->mtp2_t1 = -1;
  }
}

static void t1_start(mtp2_t *m) {
  t1_stop(m);
  m->mtp2_t1 = mtp_sched_add(mtp2_sched, 45000, t1_timeout, m);
}

static int t2_timeout(void *data) {
  mtp2_t *m = data;
  fifo_log(m, LOG_WARNING, "MTP2 timer T2 timeout (failed to receive 'O', 'N', "
	   "or 'E' after sending 'O'), initial alignment failed on link '%s'.\n", m->name);
  m->mtp2_t2 = -1;
  abort_initial_alignment(m);
  return 0;                     /* Do not re-schedule */
}

static void t2_stop(mtp2_t *m) {
  if(m->mtp2_t2 != -1) {
    mtp_sched_del(mtp2_sched, m->mtp2_t2);
    m->mtp2_t2 = -1;
  }
}

static void t2_start(mtp2_t *m) {
  t2_stop(m);
  m->mtp2_t2 = mtp_sched_add(mtp2_sched, 75000, t2_timeout, m);
}

static int t3_timeout(void *data) {
  mtp2_t *m = data;
  fifo_log(m, LOG_WARNING, "MTP2 timer T3 timeout (failed to receive 'N', "
	   "or 'E' after sending 'O'), initial alignment failed on link '%s'.\n", m->name);
  m->mtp2_t3 = -1;
  abort_initial_alignment(m);
  return 0;                     /* Do not re-schedule */
}

static void t3_stop(mtp2_t *m) {
  if(m->mtp2_t3 != -1) {
    mtp_sched_del(mtp2_sched, m->mtp2_t3);
    m->mtp2_t3 = -1;
  }
}

static void t3_start(mtp2_t *m) {
  t3_stop(m);
  m->mtp2_t3 = mtp_sched_add(mtp2_sched, 1500, t3_timeout, m);
}

static int t4_timeout(void *data) {
  mtp2_t *m = data;
  fifo_log(m, LOG_DEBUG, "Proving successful on link '%s'.\n", m->name);
  m->state = MTP2_READY;
  m->mtp2_t4 = -1;
  t1_start(m);
  return 0;                     /* Do not re-schedule */
}

static void t4_stop(mtp2_t *m) {
  if(m->mtp2_t4 != -1) {
    mtp_sched_del(mtp2_sched, m->mtp2_t4);
    m->mtp2_t4 = -1;
  }
}

static void t4_start(mtp2_t *m) {
  t4_stop(m);
  m->mtp2_t4 = mtp_sched_add(mtp2_sched, 500, t4_timeout, m);
}

static struct mtp2_state* get_inservice_schannel(struct link* link)
{
  int i;
   for (i = 0; i < this_host->n_schannels; i++) {
    struct mtp2_state* m = &mtp2_state[i];
    if (m->state == MTP2_INSERVICE) {
      struct link* slink = m->link;
      if (link->linkset == slink->linkset ||
	  is_combined_linkset(link->linkset, slink->linkset))
	return m;
    }
  }
  return NULL;
}

int mtp_has_inservice_schannels(struct link* link)
{
  return (get_inservice_schannel(link) != NULL);
}


static mtp2_t* find_alternative_slink(mtp2_t* m)
{
  struct mtp2_state* newm = NULL;
  struct mtp2_state* alt_newm = NULL;
  int i;
 
  for (i = 0; i < this_host->n_schannels; i++) {
    if (&mtp2_state[i] == m)
      continue;
    if (mtp2_state[i].state != MTP2_INSERVICE)
      continue;
    if (m->link->linkset == mtp2_state[i].link->linkset) {
      newm = &mtp2_state[i];
      break;
    }
    if (is_combined_linkset(m->link->linkset, mtp2_state[i].link->linkset))
      alt_newm = &mtp2_state[i];
  }
  if (!newm)
    newm = alt_newm;
  return newm;
}

/* Flush MTP transmit buffer to other link or host */
static void mtp_changeover(mtp2_t *m) {
  struct mtp2_state* newm = NULL;
  int i;
  int do_forward = 1;

  for (i = 0; i < this_host->n_schannels; i++) {
    struct mtp2_state* newm = &mtp2_state[i];
    if (&mtp2_state[i] == m)
      continue;
    if (m->link->linkset != newm->link->linkset)
      continue;
    if (mtp2_state[i].state == MTP2_INSERVICE) {
      newm = &mtp2_state[i];
      break;
    }
  }
  if (!newm) {
    fifo_log(m, LOG_NOTICE, "MTP changeover last_ack=%d, last_sent=%d, from schannel %d, no INSERVICE schannel found\n", m->retrans_last_acked, m->retrans_last_sent, m->schannel);
    if (this_host->has_signalling_receivers)
      fifo_log(m, LOG_NOTICE, "Failover, using another host for signalling.\n");
    if (!cluster_receivers_alive(m->link->linkset)) {
      fifo_log(m, LOG_NOTICE, "Failover not possible, no other signalling link and no other host available.\n");
#if 1
      /* Remove all MSU's - the user parts must deal with lost PDU's */
      m->retrans_last_acked = MTP_NEXT_SEQ(m->retrans_last_sent);
      m->retrans_seq = -1;
#endif
      return;
    }
  }
  fifo_log(m, LOG_NOTICE, "MTP changeover last_ack=%d, last_sent=%d, from schannel %d, to schannel %d\n", m->retrans_last_acked, m->retrans_last_sent, m->schannel, newm ? newm->schannel : -1);
  i = MTP_NEXT_SEQ(m->retrans_last_acked);
  while (i != MTP_NEXT_SEQ(m->retrans_last_sent)) {
    int sio = m->retrans_buf[i].buf[3];
    int len = m->retrans_buf[i].len-4;
    unsigned char* buf = &m->retrans_buf[i].buf[4];
    fifo_log(m, LOG_DEBUG, "MTP changeover seqno=%d, sio=%d, len=%d, is_moved=%d\n", i, sio, len, (sio & 0xf) > 3);
    if (do_forward && ((sio & 0xf) >= 3)) { /* User and application parts */
      if (newm) {
	mtp2_queue_msu(newm, sio, buf, len);
      }
      else {
	if ((sio & 0xf) == 0x5 /* ISUP */) {
	  unsigned char reqbuf[MTP_REQ_MAX_SIZE];
	  struct mtp_req *req = (struct mtp_req*) &reqbuf;
	  memcpy(req->buf, buf, len);
	  req->len = len;
	  req->typ = MTP_REQ_ISUP;
	  cluster_mtp_forward(req);
	}
      }
      m->retrans_buf[i].buf[3] = 0;
      m->retrans_buf[i].len = 5; /* Is now a LSSU */
      m->retrans_buf[i].buf[3] = 2;
      i = MTP_NEXT_SEQ(i);
    }
  }
}

/* Called on link errors that occur during initial alignment (before the link
   is in service), and which should cause initial alignment to be aborted. The
   initial alignment to be re-tried after a short delay (MTP3 T17). */
static void abort_initial_alignment(mtp2_t *m)
{
  mtp2_cleanup(m);
  m->state = MTP2_DOWN;
  /* Retry the initial alignment after a small delay. */
  t17_start(m);
  fifo_log(m, LOG_DEBUG, "Aborted initial alignment on link '%s'.\n", m->name);
}

/* Called on link errors that occur after the link is brought into service and
   which must cause the link to be brought out of service. This entails
   notifying user-parts of the failure and initiating MTP3 link failover, when
   that is implemented. */
static void mtp3_link_fail(mtp2_t *m, int down) {
  struct mtp_event link_up_event;
  int old_state = m->state;

  mtp2_cleanup(m);

  /* Notify user-parts. */
  if(old_state == MTP2_INSERVICE) {
    link_up_event.typ = MTP_EVENT_STATUS;
    link_up_event.status.link_state = MTP_EVENT_STATUS_LINK_DOWN;
    link_up_event.status.link = m->link;
    link_up_event.len = 0;
    mtp_put(m, &link_up_event);
    mtp_changeover(m);
  }

  /* For now, restart initial alignment after a small delay. */
  if (down) {
    m->state = MTP2_DOWN;
    t17_start(m);
  }
  else
    m->state = MTP2_NOT_ALIGNED;

  l4down(m);
  fifo_log(m, LOG_DEBUG, "Fail on link '%s'.\n", m->name);
}

static void start_initial_alignment(mtp2_t *m, char* reason) {
  m->state = MTP2_NOT_ALIGNED;
  m->send_fib = 1;
  m->send_bsn = 0x7f;
  m->send_bib = 1;
  m->tx_len = 0;
  m->tx_sofar = 0;
  m->retrans_seq = -1;
  m->retrans_last_acked = 0x7f;
  m->retrans_last_sent = 0x7f;
  m->error_rate_mon = 0;
  m->emon_dcount = 0;
  m->emon_ncount = 0;
  m->bsn_errors = 0;

  fifo_log(m, LOG_DEBUG, "Starting initial alignment on link '%s', reason: %s.\n", m->name, reason);
  t2_start(m);
}

static void t7_stop(mtp2_t *m) {
  if(m->mtp2_t7 != -1) {
    mtp_sched_del(mtp2_sched, m->mtp2_t7);
    m->mtp2_t7 = -1;
  }
}

static void mtp2_cleanup(mtp2_t *m) {
  /* Stop SLTA response timeout. */
  if(m->sltm_t1 != -1) {
    mtp_sched_del(mtp2_sched, m->sltm_t1);
    m->sltm_t1 = -1;
  }

  /* Stop sending SLTM. */
  if(m->sltm_t2 != -1) {
    mtp_sched_del(mtp2_sched, m->sltm_t2);
    m->sltm_t2 = -1;
  }

  t1_stop(m);
  t2_stop(m);
  t3_stop(m);
  t4_stop(m);
  t7_stop(m);

  t17_stop(m);
}

static void deliver_l4(mtp2_t *m, unsigned char *sif, int len, int sio) {
  unsigned char ebuf[MTP_EVENT_MAX_SIZE];
  struct mtp_event *event = (struct mtp_event *)ebuf;

  if (sio == MTP_EVENT_ISUP) {
    event->isup.link = NULL;
    event->isup.slink = m->link;
    event->isup.slinkix = m->link->linkix;
  }
  else{
    event->sccp.slink = m->link;
    event->sccp.slinkix = m->link->linkix;
  }
  event->typ = sio;
  event->len = len;
  memcpy(event->buf, sif, len);
  mtp_put(m, event);
}

static int timeout_t7(void *data) {
  mtp2_t *m = data;

  m->mtp2_t7 = -1;
  fifo_log(m, LOG_WARNING, "T7 timeout (excessive delay of acknowledgement) on link '%s', state=%d.\n", m->name, m->state);
  mtp3_link_fail(m, 1);

  return 0;                     /* Do not schedule us again. */
}

static void mtp2_t7_start(mtp2_t *m) {
  t7_stop(m);
  m->mtp2_t7 = mtp_sched_add(mtp2_sched, 1500, timeout_t7, m);
}

/* Signal unit error rate monitor (Q.703 (10.2)) */
static void mtp2_error_mon_count_frame(mtp2_t *m) {
  if(m->state == MTP2_READY || m->state == MTP2_INSERVICE) {
    m->emon_dcount = (m->emon_dcount + 1) % 256;
    if(m->emon_dcount == 0 && m->error_rate_mon > 0) {
      (m->error_rate_mon)--;
    }
  }
}

static void mtp2_octet_counting(mtp2_t *m) {
  m->emon_ncount = 0;
}

static void mtp2_emon_count_error(mtp2_t *m) {
  if(m->state == MTP2_READY || m->state == MTP2_INSERVICE) {
    if(m->error_rate_mon < 64) {
      (m->error_rate_mon)++;
      if(m->error_rate_mon == 64) {
        fifo_log(m, LOG_WARNING, "Excessive errors detected in signalling unit "
		 "error rate monitor, link failed on link '%s'.\n", m->name);
        mtp3_link_fail(m, 0);
      }
    }
  } else if(m->state == MTP2_PROVING) {
    (m->error_rate_mon)++;
    /* ToDo: For now we are always in emergency, but for non
       emergency, proving is not aborted until error_rate_mon reaches
       the value of 4 (Q.703 (10.3.4)). */
    if(m->error_rate_mon >= 1) {
      fifo_log(m, LOG_WARNING, "Excessive errors detected in alignment "
	       "error rate monitor, link failed on link '%s'.\n", m->name);

⌨️ 快捷键说明

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