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

📄 l4isup.c

📁 asterisk 的7号信令处理模块
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* This should be called with pvt->lock held. */static void t36_clear(struct ss7_chan *pvt) {  if(pvt->t36 != -1) {    stop_timer(pvt->t36);    pvt->t36 = -1;  }}/* This should be called with pvt->lock held. */static void t36_start(struct ss7_chan* pvt){  t36_clear(pvt);  pvt->t36 = start_timer(12000, t36_timeout, pvt);}static void isup_send_grs(struct ss7_chan *pvt, int count, int do_timers) {  unsigned char msg[MTP_MAX_PCK_SIZE];  int current, varptr;  unsigned char param[1];  if(pvt == NULL) {    ast_log(LOG_NOTICE, "Error: NULL pvt passed in?!?.\n");    return;  }  if(count < 2) {    ast_log(LOG_NOTICE, "Error (CIC=%d), cannot send group reset for %d "            "circuits (need at least 2).\n", pvt->cic, count);    return;  }  isup_msg_init(msg, sizeof(msg), this_host->opc, peerpc(pvt), pvt->cic, ISUP_GRS, &current);  isup_msg_start_variable_part(msg, sizeof(msg), &varptr, &current, 1, 0);  param[0] = count - 1;  isup_msg_add_variable(msg, sizeof(msg), &varptr, &current, param, 1);  mtp_enqueue_isup(pvt, msg, current);  if(do_timers) {    t22_start(pvt);    t23_start(pvt);  }}/* At startup, send an initial GRS to reset all circuits, and setup a timer   to wait for the ack. */static void send_init_grs(struct linkset* linkset) {  int i;  int first_equipped;           /* Left end of a range in CIC scan. */  int range;  ast_log(LOG_DEBUG, "Sending GROUP RESET messages on linkset '%s'.\n", linkset->name);  lock_global();  /* Send a GRS for each continuous range of circuits. */  first_equipped = -1;  for(i = linkset->first_cic; i <= linkset->last_cic; i++) {    if(linkset->cic_list[i] && linkset->cic_list[i]->equipped) {      /* Clear the blocked status for the circuits; any remote blocking will be         reported by the peer. */      linkset->cic_list[i]->blocked = 0;      /* Look for the start of a range. */      if(first_equipped == -1) {        first_equipped = i;      }    }    /* Look for the end of a range. */    if(first_equipped != -1 &&       (i == linkset->last_cic || !(linkset->cic_list[i+1] && linkset->cic_list[i+1]->equipped) || first_equipped + 31 == i)) {      range = i - first_equipped;      if(range == 0) {	struct ss7_chan *pvt = linkset->cic_list[first_equipped];	ast_mutex_lock(&pvt->lock);	pvt->state = ST_SENT_REL;	isup_send_rsc(pvt); 	t16_start(pvt);	ast_mutex_unlock(&pvt->lock);	first_equipped = -1;      } else {        linkset->cic_list[first_equipped]->grs_count = range + 1;        isup_send_grs(linkset->cic_list[first_equipped], range + 1, 1);      }      ast_log(LOG_DEBUG, "Group reset first %d, range %d \n", first_equipped, range);      first_equipped = -1;    }  }  unlock_global();  /* When the reset acknowledge arrives, the pvt->reset_done is set true for     all affected circuits. Until then, messages for that circuit are     discarded. */}/* Release circuit after receiving GRS */static void release_circuit(struct ss7_chan* pvt){  struct ast_channel *chan = pvt->owner;  if(chan != NULL) {    ast_mutex_lock(&chan->lock);  }  ast_mutex_lock(&pvt->lock);  if(pvt->state != ST_IDLE) {    pvt->state = ST_IDLE;    if(chan != NULL) {      request_hangup(chan, AST_CAUSE_NETWORK_OUT_OF_ORDER);    } else {      /* Channel already hung up */    }  }  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);  ast_mutex_unlock(&pvt->lock);  if(chan != NULL) {    ast_mutex_unlock(&chan->lock);  }}static void free_cic(struct ss7_chan* pvt){  pvt->state = ST_IDLE;  pvt->hangupcause = 0;  pvt->dohangup = 0;  pvt->has_inband_ind = 0;  pvt->owner = NULL;  add_to_idlelist(pvt);}static void handle_complete_address(struct ss7_chan *pvt){  int res;  struct iam* iam = &pvt->iam;  struct ast_channel *chan = ss7_new(pvt, AST_STATE_RING, iam->ani.present ? iam->ani.num : NULL, iam->dni.num);  if(chan == NULL) {    ast_log(LOG_WARNING, "Failed to allocate struct ast_channel * "	    "for CIC=%d.\n", pvt->cic);    /* Q.764 2.2 c) Initiate release procedure */    initiate_release_circuit(pvt, AST_CAUSE_NORMAL_CLEARING);    return;  }#ifdef USE_ASTERISK_1_2  ast_copy_string(chan->exten, iam->dni.num, sizeof(chan->exten));  ast_copy_string(chan->context, pvt->context, sizeof(chan->context));  ast_copy_string(chan->language, pvt->language, sizeof(chan->language));#else  ast_string_field_set(chan, language, pvt->language);#endif  if(iam->ani.present) {    chan->cid.cid_num = strdup(iam->ani.num);    /* ToDo: Handle screening. */    if(iam->ani.restricted) {      chan->cid.cid_pres = AST_PRES_PROHIB_NETWORK_NUMBER;    } else {      chan->cid.cid_pres = AST_PRES_ALLOWED_NETWORK_NUMBER;    }  }  if(iam->rni.present) {    /* ToDo: implement redirection reason in Asterisk, and handle it here. */    chan->cid.cid_rdnis = strdup(iam->rni.num);  }  if(iam->redir_inf.is_redirect) {    char *string_reason;    /* The names here are taken to match with those used in chan_zap.c       redirectingreason2str(). */    switch(iam->redir_inf.reason) {    case 1:      string_reason = "BUSY";      break;    case 2:      /* Cause 4 "deflection during alerting"; not sure, but it seems to be	 more or less equivalent to "no reply".*/    case 4:      string_reason = "NO_REPLY";      break;    case 3:      /* Cause 5 "deflection immediate response"; not sure, but it seems to	 be more or less equivalent to "unconditional".*/    case 5:      string_reason = "UNCONDITIONAL";      break;    case 6:      string_reason = "UNREACHABLE";      break;    default:      string_reason = "UNKNOWN";      break;    }    /* Use underscore variable to make it inherit like other callerid info. */    pbx_builtin_setvar_helper(chan, "__PRIREDIRECTREASON", string_reason);  }  if (!pvt->link->linkset->use_connect) {    isup_send_acm(pvt);    pvt->state = ST_SENT_ACM;  }  res = ast_pbx_start(chan);  if(res != 0) {    ast_log(LOG_WARNING, "Unable to start PBX for incoming call on CIC=%d.\n",            pvt->cic);    ast_hangup(chan);  }}static void check_iam_sam(struct ss7_chan* pvt){  int complete = (pvt->link->linkset->enable_st && pvt->iam.dni.complete) ||    ast_exists_extension(pvt->owner, pvt->context, pvt->iam.dni.num, 1, pvt->iam.rni.num);  if (complete) {    pvt->iam.dni.complete = 1;    ast_log(LOG_DEBUG, "Setting iam.dni.complete\n");    handle_complete_address(pvt);  } else {    if (ast_canmatch_extension(pvt->owner, pvt->context, pvt->iam.dni.num, 1, pvt->iam.rni.num) != 0) {      ast_log(LOG_DEBUG, "Processing addr %s, incomplete, starting T35\n", pvt->iam.dni.num);      t35_start(pvt);    }    else {      ast_log(LOG_DEBUG, "Unable to match extension, context: %s, dni: %s, rni: %s\n", pvt->context, pvt->iam.dni.num, pvt->iam.rni.num);      initiate_release_circuit(pvt, AST_CAUSE_UNALLOCATED);    }  }}static void check_obci(struct ss7_chan* pvt, int obci){  struct ast_channel* chan = pvt->owner;  if ((obci & 0x1) == 1) {    if (!pvt->has_inband_ind) {      ast_log(LOG_DEBUG, "Got optional backward call indicator, queueing PROGRESS (Inband-information available) indication for Asterisk, CIC=%d.\n", pvt->cic);      ast_queue_control(chan, AST_CONTROL_PROGRESS);      pvt->has_inband_ind = 1;    }  }}static int isup_phonenum_check(char **number, int *nlen,                               int *is_international) {  if(*number == NULL) {    ast_log(LOG_DEBUG, "NULL phonenumber, encoding failed.\n");    return -1;  }  *nlen = strlen(*number);  if(*nlen == 0) {    ast_log(LOG_DEBUG, "Empty phonenumber, encoding failed.\n");    return -1;  }  /* Handle both '00' and '+' as international prefix. */  if(strncmp(*number, "00", 2) == 0) {    *is_international = 1;    *number += 2;    *nlen -= 2;  } else if(strncmp(*number, "+", 1) == 0) {    *is_international = 1;    *number += 1;    *nlen -= 1;  } else {    *is_international = 0;  }  return 0;                     /* Success */}static int isup_phonenum_digits(char *number, int add_st,				int nlen, unsigned char *param) {  int i, d;  for(i = 0; i <= nlen; i++) {    if(i == nlen) {      if(add_st) {        d = 0xf;                /* Digit "ST", meaning "number complete" */      } else {        break;      }    } else {      if ((number[i] >= '0') && (number[i] <= '9'))	d = number[i] - '0';      else if ((number[i] == 'b') || (number[i] == 'B'))	d = 0x0b;      else if ((number[i] == 'c') || (number[i] == 'C'))	d = 0x0c;      else {	ast_log(LOG_DEBUG, "Invalid digit '%c' in phonenumber.\n", number[i]);	return -1;      }    }    if((i % 2) == 0) {      param[2 + i/2] = d;    } else {      param[2 + (i - 1)/2] |= d << 4;    }  }  return 0;}/* Encode a phone number in ISUP "Called Party Number" format. (Q.763 (3.9))   Returns encoded length on success, -1 on error. */int isup_called_party_num_encode(char *number, unsigned char *param,				 int plen) {  int nlen;  int is_odd;  int is_international;  int result_len;  if(isup_phonenum_check(&number, &nlen, &is_international) == -1) {    return -1;  }  /* We terminate the number with ST to signify that the number is complete     (no overlapped dialing). Hence length is one more than nlen. */  is_odd = (nlen + 1) % 2;  /* Need room for two header bytes + all of the (nlen + 1) digits. */  result_len = 2 + (nlen + 2)/2;  if(result_len > plen) {    ast_log(LOG_DEBUG, "Phonenumber too large to fit in parameter, "            "len %d < %d.\n", plen, result_len);    return -1;  }  param[0] = (is_odd << 7) | (is_international ? 4 : 3);  param[1] = 0x10; /* Internal routing allowed, ISDN number plan */  if(isup_phonenum_digits(number, 1, nlen, param) == -1) {    return -1;  }  return result_len;            /* Success */}/* Encode a phone number in ISUP "Called Party Number" format. (Q.763 (3.9))   Returns encoded length on success, -1 on error. */int isup_called_party_num_encode_no_st(char *number, unsigned char *param,				       int plen) {  int nlen;  int is_odd;  int is_international;  int result_len;  if(isup_phonenum_check(&number, &nlen, &is_international) == -1) {    return -1;  }  /* We do not termminate the number with ST to signify that the number is incomplete     (overlapped dialing). */  is_odd = (nlen) % 2;  /* Need room for two header bytes + all of the (nlen) digits. */  result_len = 2 + (nlen + 1)/2;  if(result_len > plen) {    ast_log(LOG_DEBUG, "Phonenumber too large to fit in parameter, "            "len %d < %d.\n", plen, result_len);    return -1;  }  param[0] = (is_odd << 7) | (is_international ? 4 : 3);  param[1] = 0x10; /* Internal routing allowed, ISDN number plan */  if(isup_phonenum_digits(number, 0, nlen, param) == -1) {    return -1;  }  return result_len;            /* Success */}/* Encode a phone number in ISUP "Calling Party Number" format. (Q.763 (3.10))   Returns encoded length on success, -1 on error. */int isup_calling_party_num_encode(char *number, int pres_restr,				  unsigned char *param, int plen) {  int nlen;  int is_odd;  int is_international;  int result_len;  if(isup_phonenum_check(&number, &nlen, &is_international) == -1) {    return -1;  }  is_odd = nlen % 2;  /* Need room for two header bytes + all of the nlen digits. */  result_len = 2 + (nlen + 1)/2;  if(result_len > plen) {    ast_log(LOG_DEBUG, "Phonenumber too large to fit in parameter, "            "len %d < %d.\n", plen, result_len);    return -1;  }  param[0] = (is_odd << 7) | (is_international ? 4 : 3);  param[1] = 0x11; /* Number complete; ISDN number plan; user provided,                      verified and passed */  if(pres_restr) {    param[1] |= (0x1 << 2);  }  if(isup_phonenum_digits(number, 0, nlen, param) == -1) {    return -1;  }  return result_len;            /* Success */}static int isup_send_sam(struct ss7_chan *pvt, char* addr, int complete){  unsigned char msg[MTP_MAX_PCK_SIZE];  int current, varptr;  unsigned char param[2 + PHONENUM_MAX];  int res;  isup_msg_init(msg, sizeof(msg), this_host->opc, peerpc(pvt), pvt->cic, ISUP_SAM, &current);  if (complete)    res = isup_called_party_num_encode(addr, param, sizeof(param));  else    res = isup_called_party_num_encode_no_st(addr, param, sizeof(param));  isup_msg_start_variable_part(msg, sizeof(msg), &varptr, &current, 1, 0);  /* Param index 1 not used with SAM, change it */  param[1] = param[0]; res--;

⌨️ 快捷键说明

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