l4isup.c

来自「asterisk1.4.6版本下 7#信令驱动 源码」· C语言 代码 · 共 2,056 行 · 第 1/5 页

C
2,056
字号
  }

  ast_mutex_lock(&pvt->lock);

  chan = ss7_new(pvt, AST_STATE_DOWN, NULL, sep ? sep+1 : arg);
  if(!chan) {
    ast_mutex_unlock(&pvt->lock);
    unlock_global();
    *cause = AST_CAUSE_CONGESTION;
    ast_log(LOG_WARNING, "Unable to allocate SS7 channel structure.\n");
    return NULL;
  }

  ast_mutex_unlock(&pvt->lock);
  unlock_global();

  ast_update_use_count();

  ast_log(LOG_DEBUG, "SS7 channel %s/%s allocated successfully.\n", type, arg);
  return chan;
}

static int ss7_send_digit_begin(struct ast_channel *chan, char digit) {
  struct ss7_chan *pvt = chan->tech_pvt;

  ast_mutex_lock(&pvt->lock);
  if (!io_send_dtmf(pvt->zaptel_fd, pvt->cic, digit))
    pvt->sending_dtmf = 1;
  ast_mutex_unlock(&pvt->lock);

  return 0;
}

static int ss7_send_digit_end(struct ast_channel *chan, char digit, unsigned int duration) {
  return 0;
}


static void ss7_send_call_progress(struct ss7_chan *pvt, int value) {
  unsigned char msg[MTP_MAX_PCK_SIZE];
  int current, varptr;
  unsigned char param[1];
  unsigned char param_backward_ind[2];
  unsigned char param_opt_backw_ind[1];

  isup_msg_init(msg, sizeof(msg), variant(pvt), this_host->opc, peerpc(pvt), pvt->cic, ISUP_CPR, &current);
  param[0] = value;              /* Event information */
  param_backward_ind[0] = 0x16;  /* Charge, subscriber free, ordinary subscriber, no end-to-end */
  param_backward_ind[1] = 0x14;  /* No interworking, no end-to-end, ISDN all the way, no hold, terminating access ISDN, no echo control */

  param_opt_backw_ind[0] = 0x01;
  isup_msg_add_fixed(msg, sizeof(msg), &current, param, 1);
  isup_msg_start_variable_part(msg, sizeof(msg), &varptr, &current, 0, 1);
  isup_msg_start_optional_part(msg, sizeof(msg), &varptr, &current);
  isup_msg_add_optional(msg, sizeof(msg), &current, IP_BACKWARD_CALL_INDICATORS,
			param_backward_ind, 2);
  isup_msg_add_optional(msg, sizeof(msg), &current, IP_OPTIONAL_BACKWARD_CALL_INDICATORS,
			param_opt_backw_ind, 1);
  isup_msg_end_optional_part(msg, sizeof(msg), &current);
  mtp_enqueue_isup(pvt, msg, current);
}

#ifdef USE_ASTERISK_1_2
 static int ss7_indicate(struct ast_channel *chan, int condition) {
#else
static int ss7_indicate(struct ast_channel *chan, int condition, const void* data, size_t datalen) {
#endif
  struct ss7_chan *pvt = chan->tech_pvt;
  int res;

  ast_mutex_lock(&pvt->lock);

  ast_log(LOG_DEBUG, "SS7 indicate CIC=%d.\n", pvt->cic);
  switch(condition) {
  case AST_CONTROL_RINGING:
    ast_log(LOG_DEBUG, "Sending ALERTING call progress for CIC=%d in-band ind=%d.\n",
	    pvt->cic, pvt->has_inband_ind);
    ss7_send_call_progress(pvt, 0x01);
    ast_setstate(chan, AST_STATE_RINGING);
    res = !pvt->has_inband_ind && !pvt->is_digital; /* If there is no indication of in-band information, tell asterisk to generate ringing indication tone */
    break;

  case AST_CONTROL_PROGRESS:
    ast_log(LOG_DEBUG, "Sending in-band information available call progress for CIC=%d..\n",
	    pvt->cic);
    ss7_send_call_progress(pvt, 0x03);
    ast_playtones_stop(chan);
    res = 0;
    break;

  default:
    /* Not supported. */
    res = !pvt->has_inband_ind && !pvt->is_digital; /* If there is no indication of in-band information, tell asterisk to generate ringing indication tone */
  }

  ast_mutex_unlock(&pvt->lock);
  if (!res)
    ast_log(LOG_DEBUG, "Generating in-band indication tones for CIC=%d, condition=%d.\n", pvt->cic, condition);

  return res;
}

static int t1_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  ast_log(LOG_NOTICE, "T1 timeout (waiting for RLC) CIC=%d.\n", pvt->cic);
  isup_send_rel(pvt, pvt->hangupcause);
  return 1;                     /* Run us again the next period */
}

/* This should be called with pvt->lock held. */
static void t1_clear(struct ss7_chan *pvt) {
  if(pvt->t1 != -1) {
    stop_timer(pvt->t1);
    pvt->t1 = -1;
  }
}

/* This should be called with pvt->lock held. */
static void t1_start(struct ss7_chan *pvt) {
  t1_clear(pvt);
  pvt->t1 = start_timer(30000, t1_timeout, pvt);
}

static int t2_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  ast_log(LOG_NOTICE, "T2 timeout (waiting for RES, user) CIC=%d.\n", pvt->cic);
  isup_send_rel(pvt, AST_CAUSE_NORMAL_CLEARING); /* Q.764 2.4.3 and Annex A */
  pvt->t2 = -1;
  return 0;                     /* Remove us from sched */
}

/* This should be called with pvt->lock held. */
static void t2_clear(struct ss7_chan *pvt) {
  if(pvt->t2 != -1) {
    stop_timer(pvt->t2);
    pvt->t2 = -1;
  }
}

/* This should be called with pvt->lock held. */
static void t2_start(struct ss7_chan *pvt) {
  t2_clear(pvt);
  pvt->t2 = start_timer(180000, t2_timeout, pvt);
}


/* This should be called with pvt->lock held. */
static void t5_clear(struct ss7_chan *pvt) {
  if(pvt->t5 != -1) {
    stop_timer(pvt->t5);
    pvt->t5 = -1;
  }
}

static int t5_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  /* For the long T5 timeout, alert maintenance, and switch to sending
     "reset circuit". */
  ast_log(LOG_WARNING, "T5 timeout (No \"release complete\" from peer) CIC=%d.\n", pvt->cic);
  t1_clear(pvt);
  isup_send_rsc(pvt);
  t17_start(pvt);
  pvt->t5 = -1;
  return 0;                     /* Remove us from sched */
}

/* This should be called with pvt->lock held. */
static void t5_start(struct ss7_chan *pvt) {
  t5_clear(pvt);
  pvt->t5 = start_timer(600000, t5_timeout, pvt);
}

static int t6_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  ast_log(LOG_NOTICE, "T6 timeout (waiting for RES, network) CIC=%d.\n", pvt->cic);
  isup_send_rel(pvt, AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE);
  pvt->t6 = -1;
  return 0;                     /* Remove us from sched */
}

/* This should be called with pvt->lock held. */
static void t6_clear(struct ss7_chan *pvt) {
  if(pvt->t6 != -1) {
    stop_timer(pvt->t6);
    pvt->t6 = -1;
  }
}

/* This should be called with pvt->lock held. */
static void t6_start(struct ss7_chan *pvt) {
  t6_clear(pvt);
  pvt->t6 = start_timer(60000, t6_timeout, pvt);
}

static int t7_timeout(void *arg) {
  struct ast_channel *chan = arg;
  struct ss7_chan *pvt = chan->tech_pvt;

  ast_log(LOG_NOTICE, "T7 timeout (waiting for ACM or CON) CIC=%d.\n", pvt->cic);
  /* Q.764 2.4.3 */
  request_hangup(chan, AST_CAUSE_NORMAL_CLEARING);
  pvt->t7 = -1;
  /* asterisk sometimes fail to call ss7_hangup ... */
  return 0;                     /* Remove us from sched */
}

/* This should be called with pvt->lock held. */
static void t7_clear(struct ss7_chan *pvt) {
  if(pvt->t7 != -1) {
    stop_timer(pvt->t7);
    pvt->t7 = -1;
  }
}

/* This should be called with pvt->lock held. */
static void t7_start(struct ast_channel *chan) {
  struct ss7_chan *pvt = chan->tech_pvt;
  t7_clear(pvt);
  pvt->t7 = start_timer(25000, t7_timeout, chan);
}

static int t9_timeout(void *arg) {
  struct ast_channel *chan = arg;
  struct ss7_chan *pvt = chan->tech_pvt;

  ast_log(LOG_NOTICE, "T9 timeout (waiting for ANM).\n");
  request_hangup(chan, AST_CAUSE_NETWORK_OUT_OF_ORDER);
  pvt->t9 = -1;
  return 0;                     /* Remove us from sched */
}

/* This should be called with pvt->lock held. */
static void t9_clear(struct ss7_chan *pvt) {
  if(pvt->t9 != -1) {
    stop_timer(pvt->t9);
    pvt->t9 = -1;
  }
}

/* This should be called with pvt->lock held. */
static void t9_start(struct ast_channel *chan) {
  struct ss7_chan *pvt = chan->tech_pvt;
  t9_clear(pvt);
  pvt->t9 = start_timer(90000, t9_timeout, chan);
}

/* This should be called with pvt->lock held. */
static void t16_clear(struct ss7_chan *pvt) {
  if(pvt->t16 != -1) {
    stop_timer(pvt->t16);
    pvt->t16 = -1;
  }
}

static int t16_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  /* For the long T16 timeout, alert maintenance, and switch to sending
     "reset circuit". */
  ast_log(LOG_WARNING, "T16 timeout (No \"release complete\" from peer) CIC=%d, sent RSC.\n", pvt->cic);
  isup_send_rsc(pvt);
  return 1;                     /* Run us again the next period */
}

/* This should be called with pvt->lock held. */
static void t16_start(struct ss7_chan *pvt) {
  t16_clear(pvt);
  pvt->t16 = start_timer(30000, t16_timeout, pvt);
}

/* This should be called with pvt->lock held. */
static void t17_clear(struct ss7_chan *pvt) {
  if(pvt->t17 != -1) {
    stop_timer(pvt->t17);
    pvt->t17 = -1;
  }
}

static int t17_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  /* For the long T17 timeout, alert maintenance, and switch to sending
     "reset circuit". */
  ast_log(LOG_WARNING, "T17 timeout (No \"release complete\" from peer) CIC=%d.\n", pvt->cic);
  isup_send_rsc(pvt);
  return 1;                     /* Run us again the next period */
}

/* This should be called with pvt->lock held. */
static void t17_start(struct ss7_chan *pvt) {
  t17_clear(pvt);
  pvt->t17 = start_timer(600000, t17_timeout, pvt);
}

/* This should be called with pvt->lock held. */
static void t18_clear(struct ss7_chan *pvt) {
  if(pvt->t18 != -1) {
    stop_timer(pvt->t18);
    pvt->t18 = -1;
  }
}

static int t18_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  /* For the long T18 timeout, alert maintenance, and switch to sending
     "reset circuit". */
  ast_log(LOG_WARNING, "T18 timeout (No \"circuit group blocking acknowledge\" from peer) CIC=%d.\n", pvt->cic);
  isup_send_cgb(pvt, pvt->cgb_mask);
  pvt->t18 = -1;
  t19_start(pvt);
  return 0;                     /* Remove us from sched */
}

/* This should be called with pvt->lock held. */
static void t18_start(struct ss7_chan *pvt) {
  t18_clear(pvt);
  pvt->t18 = start_timer(30000, t18_timeout, pvt);
}

/* This should be called with pvt->lock held. */
static void t19_clear(struct ss7_chan *pvt) {
  if(pvt->t19 != -1) {
    stop_timer(pvt->t19);
    pvt->t19 = -1;
  }
}

static int t19_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  /* For the long T19 timeout, alert maintenance, and switch to sending
     "reset circuit". */
  ast_log(LOG_WARNING, "T19 timeout (No \"circuit group blocking acknowledge\" from peer) CIC=%d.\n", pvt->cic);
  isup_send_cgb(pvt, pvt->cgb_mask);
  return 1;                     /* Run us again the next period */
}

/* This should be called with pvt->lock held. */
static void t19_start(struct ss7_chan *pvt) {
  t19_clear(pvt);
  pvt->t19 = start_timer(600000, t19_timeout, pvt);
}

/* This should be called with pvt->lock held. */
static void t20_clear(struct ss7_chan *pvt) {
  if(pvt->t20 != -1) {
    stop_timer(pvt->t20);
    pvt->t20 = -1;
  }
}

static int t20_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  /* For the long T20 timeout, alert maintenance, and switch to sending
     "reset circuit". */
  ast_log(LOG_WARNING, "T20 timeout (No \"circuit group unblocking acknowledge\" from peer) CIC=%d.\n", pvt->cic);
  isup_send_cgu(pvt, pvt->cgb_mask);
  pvt->t20 = -1;
  t21_start(pvt);
  return 0;                     /* Remove us from sched */
}

/* This should be called with pvt->lock held. */
static void t20_start(struct ss7_chan *pvt) {
  t20_clear(pvt);
  pvt->t20 = start_timer(30000, t20_timeout, pvt);
}

/* This should be called with pvt->lock held. */
static void t21_clear(struct ss7_chan *pvt) {
  if(pvt->t21 != -1) {
    stop_timer(pvt->t21);
    pvt->t21 = -1;
  }
}

static int t21_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  /* For the long T21 timeout, alert maintenance, and switch to sending
     "reset circuit". */
  ast_log(LOG_WARNING, "T21 timeout (No \"circuit group blocking acknowledge\" from peer) CIC=%d.\n", pvt->cic);
  isup_send_cgu(pvt, pvt->cgb_mask);
  return 1;                     /* Run us again the next period */
}

/* This should be called with pvt->lock held. */
static void t21_start(struct ss7_chan *pvt) {
  t21_clear(pvt);
  pvt->t21 = start_timer(600000, t21_timeout, pvt);
}

/* This should be called with pvt->lock held. */
static void t22_clear(struct ss7_chan *pvt) {
  if(pvt->t22 != -1) {
    stop_timer(pvt->t22);
    pvt->t22 = -1;
  }
}

static int t22_timeout(void *arg) {
  struct ss7_chan *pvt = arg;

  ast_log(LOG_NOTICE, "T22 timeout (No \"circuit group reset acknowledge\" from peer) CIC=%d.\n", pvt->cic);
  isup_send_grs(pvt, pvt->grs_count, 0);
  return 1;                     /* Run us again the next period */

⌨️ 快捷键说明

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