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

📄 l4isup.c

📁 asterisk 的7号信令处理模块
💻 C
📖 第 1 页 / 共 5 页
字号:
  isup_msg_add_variable(msg, sizeof(msg), &varptr, &current, &param[1], res);  isup_msg_start_optional_part(msg, sizeof(msg), &varptr, &current);  isup_msg_end_optional_part(msg, sizeof(msg), &current);  mtp_enqueue_isup(pvt, msg, current);  return 0;}static int isup_send_iam(struct ast_channel *chan, char *addr, char *rdni, char *dni, int dnilimit) {  struct ss7_chan *pvt = chan->tech_pvt;  unsigned char msg[MTP_MAX_PCK_SIZE];  unsigned char param[2 + PHONENUM_MAX];  int current, varptr;  char dnicpy[100];   int pres_restr;  int res;  isup_msg_init(msg, sizeof(msg), this_host->opc, peerpc(pvt), pvt->cic, ISUP_IAM, &current);  /* Nature of connection indicators Q.763 (3.35). */  param[0] = 0x00; /* No sattelite, no continuity check, no echo control */  isup_msg_add_fixed(msg, sizeof(msg), &current, param, 1);  /* Forward call indicator Q.763 (3.23). */  param[0] = 0x60; /* No end-to-end method , no interworking, no end-to-end                      info, ISDN all the way, ISDN not required */  param[1] = 0x01; /* Originating access ISDN, no SCCP indication */  isup_msg_add_fixed(msg, sizeof(msg), &current, param, 2);  /* Calling party's category Q.763 (3.11). */  param[0] = 0x0a; /* Ordinary calling subscriber */  isup_msg_add_fixed(msg, sizeof(msg), &current, param, 1);  /* Transmission medium requirement Q.763 (3.54). */  param[0] = 0x00; /* Speech */  isup_msg_add_fixed(msg, sizeof(msg), &current, param, 1);  /* Called party number Q.763 (3.9). */  isup_msg_start_variable_part(msg, sizeof(msg), &varptr, &current, 1, 1);  if (dnilimit > 0 && strlen(dni) > dnilimit) {    /* Make part of dni */    strncpy(dnicpy, dni, dnilimit);    dnicpy[dnilimit] = '\0';    res = isup_called_party_num_encode_no_st(dnicpy, param, sizeof(param));  } else {    res = isup_called_party_num_encode(dni, param, sizeof(param));  }  if(res < 0) {    ast_log(LOG_NOTICE, "Invalid format for phonenumber '%s'.\n", dni);    request_hangup(chan, AST_CAUSE_INVALID_NUMBER_FORMAT);    ast_mutex_unlock(&pvt->lock);    return -1;  }  isup_msg_add_variable(msg, sizeof(msg), &varptr, &current, param, res);  isup_msg_start_optional_part(msg, sizeof(msg), &varptr, &current);  /* Calling partys number Q.763 (3.10). */  if((chan->cid.cid_pres & AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED) {    pres_restr = 1;  } else {    pres_restr = 0;  }  res = isup_calling_party_num_encode(chan->cid.cid_num, pres_restr,                                      param, sizeof(param));  if(res < 0) {    ast_log(LOG_DEBUG, "Invalid format for calling number, dropped.\n");  } else {    isup_msg_add_optional(msg, sizeof(msg), &current, IP_CALLING_PARTY_NUMBER,                          param, res);  }  if (*rdni) {    /* ToDo: Pass on RDNIS (and redirection cause when we implement that) as       ISUP parameters? */    /* Q.763 3.45 */    res = isup_calling_party_num_encode(rdni, pres_restr, param, sizeof(param));    isup_msg_add_optional(msg, sizeof(msg), &current, IP_REDIRECTING_NUMBER, param, res);    param[0] = 0x04; /* redirecting indicator: call diverted, all redirection information presentation restricted,			original redirection reason: unknown */			    param[1] = 0x31; /* reredicting counter: 1			redirection reason: unconditional */			    isup_msg_add_optional(msg, sizeof(msg), &current, IP_REDIRECTION_INFORMATION, param, 2);  }  /* End and send the message. */  isup_msg_end_optional_part(msg, sizeof(msg), &current);  mtp_enqueue_isup(pvt, msg, current);  ast_verbose(VERBOSE_PREFIX_3 "Sent IAM CIC=%-3d  ANI=%s DNI=%s RNI=%s\n", pvt->cic,	  pres_restr ? "*****" : chan->cid.cid_num,          dni,          rdni);  return 0;}/* Assume that we are called with chan->lock held (as ast_call() does). */static int ss7_call(struct ast_channel *chan, char *addr, int timeout) {  struct ss7_chan *pvt = chan->tech_pvt;  char *sep = strchr(addr, '/');  char rdni[100];  char dnicpy[100];  char dni[100];  int chunk_limit, chunk_sofar=0;  int res;  ast_mutex_lock(&pvt->lock);  ast_log(LOG_DEBUG, "SS7 call, addr=%s, cid=%s(0x%x/%s) CIC=%d. linkset '%s'\n",          (addr ? addr : "<NULL>"),          (chan->cid.cid_num ? chan->cid.cid_num : "<NULL>"),          chan->cid.cid_pres,          ast_describe_caller_presentation(chan->cid.cid_pres),	  pvt->cic, pvt->link->linkset->name);  pvt->addr = addr;  pvt->attempts = 1;  if (sep)    addr = sep+1;  strcpy(dni, addr);  strcpy(rdni, chan->cid.cid_rdnis ? chan->cid.cid_rdnis : "");  sep = strchr(dni, ':');  if (sep) {    *sep = '\0';    strcpy(rdni, sep+1);  }  chunk_limit = pvt->link->linkset->dni_chunk_limit;  pvt->link->linkset->outgoing_calls++;  res = isup_send_iam(chan, addr, rdni, dni, chunk_limit);  if (res < 0)    return res;  if (chunk_limit > 0 && strlen(dni) > chunk_limit) {    while(chunk_sofar < strlen(dni)) {      strncpy(dnicpy, &dni[chunk_sofar], chunk_limit);      chunk_sofar += chunk_limit;      dnicpy[chunk_sofar] = '\0';      isup_send_sam(pvt, dnicpy, 1);    }  }  pvt->state = ST_SENT_IAM;  t7_start(chan);  ast_mutex_unlock(&pvt->lock);  return 0;}static int ss7_hangup(struct ast_channel *chan) {  struct ss7_chan *pvt = chan->tech_pvt;  if (!pvt || pvt->cic == -1) {    decr_usecount();    ast_update_use_count();    return 0;  }  ast_verbose( VERBOSE_PREFIX_3 "SS7 hangup '%s' CIC=%d Cause=%d (state=%d)\n",               chan->name, pvt->cic, chan->hangupcause, pvt->state);  /* Digium insists that ss7_hangup() must be called with chan->lock() held,     even though it is the wrong thing to do (bug 5051). So we have to unlock     it on entry and re-lock it on exit to get sane locking semantics. */  ast_mutex_unlock(&chan->lock);  /* First remove us from the global circuit list. */  lock_global();  ast_mutex_lock(&pvt->lock);  decr_usecount();  ast_log(LOG_DEBUG, "SS7 hangup '%s' CIC=%d (state=%d), chan=0x%08lx\n",	  chan->name, pvt->cic, pvt->state, (unsigned long) chan);  chan->tech_pvt = NULL;  pvt->owner = NULL;  /* Clear all the timers that may hold on to references to chan. This must be     done while global lock is held to prevent races. */  t1_clear(pvt);  t2_clear(pvt);  t5_clear(pvt);  t6_clear(pvt);  t7_clear(pvt);  t9_clear(pvt);  t16_clear(pvt);  t17_clear(pvt);  t18_clear(pvt);  t19_clear(pvt);  t20_clear(pvt);  t21_clear(pvt);  t35_clear(pvt);  if(pvt->state == ST_GOT_REL) {    isup_send_rlc(pvt);    ast_setstate(chan, AST_STATE_DOWN);    free_cic(pvt);  }  else if(pvt->state == ST_SENT_REL) {    t1_start(pvt);    t5_start(pvt);  } else if(pvt->state != ST_IDLE) {    ast_log(LOG_DEBUG, "SS7 hangup '%s' CIC=%d cause=%d\n", chan->name, pvt->cic, chan->hangupcause);    initiate_release_circuit(pvt, chan->hangupcause);  }  if (pvt->echocancel) {    io_disable_echo_cancellation(pvt->zaptel_fd, pvt->cic);    pvt->echocancel = 0;  }  ast_mutex_unlock(&pvt->lock);  unlock_global();  ast_update_use_count();  ast_mutex_lock(&chan->lock);  /* See above */  return 0;}static int ss7_answer(struct ast_channel *chan) {  struct ss7_chan *pvt = chan->tech_pvt;  unsigned char msg[MTP_MAX_PCK_SIZE];  int current, varptr;  unsigned char param[2];  ast_mutex_lock(&pvt->lock);  ast_log(LOG_DEBUG, "SS7 answer CIC=%d, pvt->state=%d.\n", pvt->cic, pvt->state);  /* Send ANM instead of CON if previously sent ACM. */  if (pvt->state == ST_SENT_ACM) {    isup_msg_init(msg, sizeof(msg), this_host->opc, peerpc(pvt), pvt->cic, ISUP_ANM, &current);    param[0] = 0x14;  /* Subscriber free, ordinary subscriber, no end-to-end */    param[1] = 0x14;  /* No interworking, no end-to-end, ISDN all the way, no			 hold, terminating access ISDN, no echo control */    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, 2);    isup_msg_end_optional_part(msg, sizeof(msg), &current);    mtp_enqueue_isup(pvt, msg, current);  } else if (pvt->state == ST_GOT_IAM) {    isup_msg_init(msg, sizeof(msg), this_host->opc, peerpc(pvt), pvt->cic, ISUP_CON, &current);    param[0] = 0x14;  /* Subscriber free, ordinary subscriber, no end-to-end */    param[1] = 0x14;  /* No interworking, no end-to-end, ISDN all the way, no			 hold, terminating access ISDN, no echo control */    isup_msg_add_fixed(msg, sizeof(msg), &current, param, 2);    isup_msg_start_variable_part(msg, sizeof(msg), &varptr, &current, 0, 1);    mtp_enqueue_isup(pvt, msg, current);  }  /* else: already connected */  pvt->state = ST_CONNECTED;  ast_setstate(chan, AST_STATE_UP);  /* Start echo-cancelling if required */  if (pvt->echocan_start) {    if (!io_enable_echo_cancellation(pvt->zaptel_fd, pvt->cic, pvt->link->echocan_taps, pvt->link->echocan_train))      pvt->echocancel = 1;    pvt->echocan_start = 0;  }  ast_mutex_unlock(&pvt->lock);  return 0;}static void ss7_handle_event(struct ss7_chan *pvt, int event) {  int res, doing_dtmf;  switch(event) {  case ZT_EVENT_DIALCOMPLETE:    /* Chech if still doing DTMF sending. If not, set flag to start       outputting audio again. */    res = ioctl(pvt->zaptel_fd, ZT_DIALING, &doing_dtmf);    if(res < 0) {      ast_log(LOG_WARNING, "Error querying zaptel for ZT_DIALING on cic=%d: %s.\n",	      pvt->cic, strerror(errno));      /* Better start the audio, don't want to permanently disable it. */      pvt->sending_dtmf = 0;    } else if(!doing_dtmf) {      /* Now we can start sending normal audio again. */      pvt->sending_dtmf = 0;    }    break;  default:    ast_log(LOG_NOTICE, "Unhandled zaptel event 0x%x on CIC=%d.\n",	    event, pvt->cic);  }}static void get_zaptel_event(struct ss7_chan* pvt){  int res, event;  /* While these should really be handled in ss7_exception(), they can     also occur here, probably because of a race between the zaptel     driver and the channel poll() loop. */  res = io_get_zaptel_event(pvt->zaptel_fd, &event);  if(res < 0) {    ast_mutex_unlock(&pvt->lock);    ast_log(LOG_WARNING, "Error reading zaptel event for CIC=%d: %s.\n",	    pvt->cic, strerror(errno));    return;  } else {    ast_log(LOG_DEBUG, "Got event %d for CIC=%d, handling.\n",	    event, pvt->cic);    ss7_handle_event(pvt, event);  }}/* ast_read() calls us with chan->lock held, so we assume that this is   always the case. */static struct ast_frame *ss7_read(struct ast_channel * chan) {  struct ss7_chan *pvt = chan->tech_pvt;  static struct ast_frame null_frame = { AST_FRAME_NULL };  struct ast_frame *processed_frame;  int res, sofar;  if (pvt->dohangup) {    chan->hangupcause = pvt->dohangup;    return NULL;  }  ast_mutex_lock(&pvt->lock);  memset(&pvt->frame, 0, sizeof(pvt->frame));  pvt->frame.frametype = AST_FRAME_VOICE;  pvt->frame.subclass = AST_FORMAT_ALAW;  pvt->frame.datalen = AUDIO_READSIZE;  pvt->frame.samples = AUDIO_READSIZE;  pvt->frame.mallocd = 0;  pvt->frame.offset = AST_FRIENDLY_OFFSET;  pvt->frame.src = NULL;  pvt->frame.data = &(pvt->buffer[AST_FRIENDLY_OFFSET]);  memset(pvt->buffer, 0, sizeof(pvt->buffer));  sofar = 0;  while(sofar < AUDIO_READSIZE) {    res = read(pvt->zaptel_fd, &(pvt->buffer[AST_FRIENDLY_OFFSET + sofar]),               AUDIO_READSIZE - sofar);    if(res < 0) {      if(errno == EINTR) {        /* Interrupted syscall, try again. */      } else if(errno == EAGAIN || errno == EWOULDBLOCK) {	static struct timeval lastreport = {0, 0};	static int supress = 0;	struct timeval now;	gettimeofday(&now, NULL);	if (now.tv_sec - lastreport.tv_sec > 10) {	  ast_log(LOG_NOTICE, "Short read on CIC=%d (read only %d of %d) errno=%d (%s) (supressed %d).\n",		  pvt->cic, sofar, AUDIO_READSIZE, errno, strerror(errno), supress);	  lastreport = now;	  supress = 0;	}	else	  supress++;        break;      } else if(errno == ELAST) {	struct pollfd fds[1];	get_zaptel_event(pvt);	fds[0].fd = pvt->zaptel_fd;	fds[0].events = POLLIN;	/* we are trying to read data, wait up to 20 msec for next frame */	res = poll(fds, 1, 20);      } else {        ast_mutex_unlock(&pvt->lock);        ast_log(LOG_WARNING, "Read error on CIC=%d: %s.\n", pvt->cic, strerror(errno));        return NULL;      }    } else if(res == 0) {      ast_mutex_unlock(&pvt->lock);      ast_log(LOG_WARNING, "EOF on zaptel device CIC=%d?!?\n", pvt->cic);      return NULL;    } else {      sofar += res;    }  }  if(sofar == 0) {    ast_mutex_unlock(&pvt->lock);    return &null_frame;  }#ifndef xxxxx  {    int msecs = sofar / 8;    struct timeval now;    static struct timeval lastreport = {0, 0};    static int supress = 0;    int tdiff;//xxx        gettimeofday(&now, NULL);    if (pvt->lastread.tv_sec) {      tdiff = (now.tv_sec - pvt->lastread.tv_sec) * 1000000 + (now.tv_usec - pvt->lastread.tv_usec);      if (tdiff/1000 > msecs + 100) {	if (now.tv_sec - lastreport.tv_sec > 10) {	  ast_log(LOG_NOTICE, "Audio buffer underrun, data %d msecs, real time: %d msecs! (supressed %d)\n", msecs, tdiff / 1000, supress);	  lastreport = now;	  supress = 0;	}	else	  supress++;      }    }    pvt->lastread = now;  }#endif  processed_frame = ast_dsp_process(chan, pvt->dsp, &pvt->frame);  ast_mutex_unlock(&pvt->lock);  return processed_frame;}static int ss7_write(struct ast_channel *

⌨️ 快捷键说明

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