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

📄 l4isup.c

📁 asterisk 的7号信令处理模块
💻 C
📖 第 1 页 / 共 5 页
字号:
/* l4isup.c - ISUP protocol * * Copyright (C) 2006, Sifira A/S. * * Author: Anders Baekgaard <ab@sifira.dk> *         Anders Baekgaard <ab@dicea.dk> * Based on work by: Kristian Nielsen <kn@sifira.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 <errno.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <time.h>#include <sys/param.h>#include <sys/socket.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 "asterisk/logger.h"#include "asterisk/options.h"#include "asterisk/channel.h"#include "asterisk/frame.h"#include "asterisk/utils.h"#include "asterisk/sched.h"#include "asterisk/cli.h"#include "asterisk/lock.h"#include "asterisk/causes.h"#include "asterisk/pbx.h"#include "asterisk/dsp.h"#include "asterisk/callerid.h"#include "asterisk/indications.h"#include "asterisk/module.h"#include "zaptel.h"#include "astversion.h"#include "config.h"#include "lffifo.h"#include "utils.h"#include "mtp.h"#include "transport.h"#include "isup.h"#include "l4isup.h"#include "cluster.h"#include "mtp3io.h"#ifdef MODULETEST#include "moduletest.h"#endifenum circuit_states {  /* Circuit idle, ready to accept or initiate calls. */  ST_IDLE,  /* An IAM has been received, but no ACM or CON has been sent back yet. */  ST_GOT_IAM,  /* An IAM has been sent to initiate a call, but no ACM or CON has been     received back yet. */  ST_SENT_IAM,  /* We have sent an ACM and have to send an ANM now */  ST_SENT_ACM,  /* We have sent IAM and received ACM, so waiting for ANM. */  ST_GOT_ACM,  /* A call is connected (incoming or outgoing). */  ST_CONNECTED,  /* A continuity check is ongoing */  ST_CONCHECK,  /* A REL message has been received, but RLC has not been sent     yet. ast_softhangup() has been called on the channel.*/  ST_GOT_REL,  /* A REL has been sent (from ss7_hangup), and so the struct ast_channel *     has been deallocated, but the circuit is still waiting for RLC to be     received before being able to initiate new calls. If timer T16 or T17     is running, this state instead means that a "circuit reset" has been     sent, and we are waiting for RLC. If a REL is received in this state,     send RLC and stay in this state, still waiting for RLC */  ST_SENT_REL,};struct ss7_chan {  /* The first few fields of this struct are protected by the global lock     mutex, not by the ss7_chan->lock mutex embedded in the struct. This is     necessary to preserve locking order and avoid deadlocks. */  struct ast_channel *owner;  struct ss7_chan *next_idle;   /* Linked list of idle CICs */  struct link* link;		/* Link carrying circuit */  int cic;  int reset_done;               /* False until circuit has been init reset */  int hangupcause;  int dohangup;  int has_inband_ind;  /* Circuit blocking status: {local,remote} {maintenance,hardware}. */  enum { BL_LM=1, BL_LH=2, BL_RM=4, BL_RH=8, BL_UNEQUIPPED=0x10, BL_LINKDOWN=0x20 } blocked;  /* Circuit equipped */  int equipped;  ast_mutex_t lock;             /* Protects rest of this struct */  enum circuit_states state;  int zaptel_fd;  int t1;  int t2;  int t5;  int t6;  int t7;  int t9;  int t16;  int t17;  int t18;  int t19;  int t20;  int t21;  int t22;  int t23;  int t35;  int t36;  struct iam iam;		/* Last incoming IAM parameters */  char* addr;			/* called addr */  int attempts;			/* Number of outgoing call attempts on addr */  int echocan_start;  int echocancel;  struct timeval lastread;  unsigned char buffer[AST_FRIENDLY_OFFSET + AUDIO_READSIZE];  struct ast_frame frame;  int sending_dtmf;  struct ast_dsp *dsp;  int grs_count;                /* Count of CICs in ISUP GRS message */  int cgb_mask;                 /* Mask of CICs in ISUP CGB message */  char context[AST_MAX_CONTEXT];  char language[MAX_LANGUAGE];};/*   Locking order (deadlock avoidance): global lock, chan->lock, pvt->lock*//* Global list of idle CICs, sorted in order of "time free". Linked through   the ss7_chan->next_idle pointers. Protected by global lock. */static struct timeval now;static struct timeval mtp_fifo_full_report;/* used by moduletest.c */int isup_called_party_num_encode(char *number, unsigned char *param, int plen);int isup_called_party_num_encode_no_st(char *number, unsigned char *param, int plen);int isup_calling_party_num_encode(char *number, int pres_restr, unsigned char *param, int plen);static pthread_t continuity_check_thread = AST_PTHREADT_NULL;static int continuity_check_thread_running = 0;AST_MUTEX_DEFINE_STATIC(continuity_check_lock);static int continuity_check_changes = 0;static int must_stop_continuity_check_thread = 0;static struct ss7_chan dummy_pvt;static void isup_send_grs(struct ss7_chan *pvt, int count, int do_timers);static struct ast_channel *ss7_requester(const char *type, int format,                                         void *data, int *cause);static int ss7_send_digit_begin(struct ast_channel *chan, char digit);static int ss7_send_digit_end(struct ast_channel *chan, char digit, unsigned int duration);static int ss7_call(struct ast_channel *chan, char *addr, int timeout);static int ss7_hangup(struct ast_channel *chan);static int ss7_answer(struct ast_channel *chan);static struct ast_frame *ss7_read(struct ast_channel * chan);static int ss7_write(struct ast_channel * chan, struct ast_frame *frame);static struct ast_frame *ss7_exception(struct ast_channel *chan);static int ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);#ifdef USE_ASTERISK_1_2static 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);#endifstatic void t7_clear(struct ss7_chan *pvt);static void t1_start(struct ss7_chan *pvt);static void t5_start(struct ss7_chan *pvt);static void t16_start(struct ss7_chan *pvt);static void t16_clear(struct ss7_chan *pvt);static void t17_start(struct ss7_chan *pvt);static void t19_start(struct ss7_chan *pvt);static void t21_start(struct ss7_chan *pvt);static int do_group_circuit_block_unblock(struct linkset* linkset, int firstcic, unsigned long cgb_mask, int sup_type_ind, int own_cics_only, int do_timers, int do_block);static struct ss7_chan* reattempt_call(struct ss7_chan *pvt);static void *continuity_check_thread_main(void *data);static void handle_complete_address(struct ss7_chan *pvt);static const char type[] = "SS7";static const char tdesc[] = "SS7 Protocol Driver";static const struct ast_channel_tech ss7_tech = {  .type = type,  .description = tdesc,  .capabilities = AST_FORMAT_ALAW,  .requester = ss7_requester,#ifdef USE_ASTERISK_1_2  .send_digit = ss7_send_digit_begin,#else  .send_digit_begin = ss7_send_digit_begin,  .send_digit_end = ss7_send_digit_end,#endif  .call = ss7_call,  .hangup = ss7_hangup,  .answer = ss7_answer,  .read = ss7_read,  .write = ss7_write,  .exception = ss7_exception,  .fixup = ss7_fixup,  .indicate = ss7_indicate,};/* Send fifo for sending protocol requests to the MTP thread.   The fifo is lock-free (one thread may put and another get simultaneously),   but multiple threads doing put must be serialized with this mutex. */AST_MUTEX_DEFINE_STATIC(mtp_send_mutex);static struct lffifo **mtp_send_fifo;#ifdef USE_ASTERISK_1_2#define ast_channel_lock(chan) ast_mutex_lock(&chan->lock)#define ast_channel_unlock(chan) ast_mutex_unlock(&chan->lock)#define ast_strdup(s) strdup(s)#define ast_malloc(d) malloc(d)#endif  static int usecnt = 0;#ifdef USE_ASTERISK_1_2AST_MUTEX_DEFINE_STATIC(usecnt_lock);int usecount(void);static void incr_usecount(void){  ast_mutex_lock(&usecnt_lock);  usecnt++;  ast_mutex_unlock(&usecnt_lock);}static void decr_usecount(void){  ast_mutex_lock(&usecnt_lock);  usecnt--;  if (usecnt < 0)    ast_log(LOG_WARNING, "Usecnt < 0???\n");  ast_mutex_unlock(&usecnt_lock);}int usecount(void){  int res;  ast_mutex_lock(&usecnt_lock);  res = usecnt;  ast_mutex_unlock(&usecnt_lock);  return res;}#elsestatic void incr_usecount(void){  ast_atomic_fetchadd_int(&usecnt, 1);  ast_update_use_count();}static void decr_usecount(void){  ast_atomic_fetchadd_int(&usecnt, -1);  ast_update_use_count();  if (usecnt < 0)    ast_log(LOG_WARNING, "Usecnt < 0???\n");}#endifstatic void request_hangup(struct ast_channel* chan, int hangupcause){  chan->hangupcause = hangupcause;  ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);}/* Lookup DPC for circuit */static inline int peerpc(struct ss7_chan* pvt){  return pvt->link->linkset->dpc;}static void mtp_enqueue_isup_packet(struct link* link, int cic, unsigned char *msg, int msglen, int reqtyp){  int res;  unsigned char req_buf[MTP_REQ_MAX_SIZE];  struct mtp_req *req = (struct mtp_req *)req_buf;  struct linkset* linkset = link->linkset;  struct link* slink = NULL;  int lsi = link->linkset->lsi;  if(sizeof(struct mtp_req) + msglen > sizeof(req_buf)) {    ast_log(LOG_ERROR, "Attempt to send oversized ISUP message of len "            "%d > %d.\n", msglen, sizeof(req_buf) - sizeof(struct mtp_req));    return;  }  switch (link->linkset->loadshare) {  case LOADSHARE_NONE:    if (link->schannel != -1)      slink = link;    break;  case LOADSHARE_LINKSET:    if (linkset->n_schannels)      slink = linkset->schannels[cic % linkset->n_schannels];    break;  case LOADSHARE_COMBINED_LINKSET:    {      int n_schannels = 0;      int schannel;      for (lsi = 0; lsi < n_linksets; lsi++)	if (linksets[lsi].enabled)	  if (&linksets[lsi] == linkset || 	      (is_combined_linkset(linkset, &linksets[lsi])))	    n_schannels += linksets[lsi].n_schannels;      if (n_schannels) {	schannel = cic % n_schannels;	n_schannels = 0;	for (lsi = 0; lsi < n_linksets; lsi++)	  if (linksets[lsi].enabled)	    if (&linksets[lsi] == linkset || 		(is_combined_linkset(linkset, &linksets[lsi]))) {	      if (schannel - n_schannels < linksets[lsi].n_schannels) {		slink = linksets[lsi].schannels[schannel - n_schannels];		break;	      }	      n_schannels += linksets[lsi].n_schannels;	    }      }    }    break;  }  if (slink)    lsi = slink->linkset->lsi;  else    lsi = linkset->lsi;  req->typ = reqtyp;  req->isup.slink = slink;  req->isup.link = link;  req->isup.slinkix = slink ? slink->linkix : 0;  req->len = msglen;  memcpy(req->buf, msg, msglen);  if(slink && slink->mtp3fd > -1) {    res = mtp3_send(slink->mtp3fd, (unsigned char *)req, sizeof(struct mtp_req) + req->len);    if (res < 0) {      close(slink->mtp3fd);      slink->mtp3fd = -1;    }    return;  }  ast_mutex_lock(&mtp_send_mutex);  if (!mtp_send_fifo || !mtp_send_fifo[lsi]) {    if (cluster_receivers_alive(linkset)) {      ast_log(LOG_DEBUG, "MTP send fifo not ready, forwarding to cluster.\n");      cluster_mtp_forward(req);    }    else      ast_log(LOG_WARNING, "MTP send fifo not ready.\n");    ast_mutex_unlock(&mtp_send_mutex);    return;  }  ast_log(LOG_DEBUG, "Queue packet CIC=%d, len=%d, linkset='%s', link='%s', slinkset='%s', slink='%s'\n", cic, msglen, linkset->name, link->name, linksets[lsi].name, slink ? slink->name : "(none)");  res = lffifo_put(mtp_send_fifo[lsi], (unsigned char *)req, sizeof(struct mtp_req) + req->len);  ast_mutex_unlock(&mtp_send_mutex);  if(res != 0) {    gettimeofday(&now, NULL);    if (timediff_msec(now, mtp_fifo_full_report) > 30000) {      ast_log(LOG_WARNING, "MTP send fifo full (MTP thread blocked?).\n");      gettimeofday(&mtp_fifo_full_report, NULL);    }  }}static void mtp_enqueue_isup(struct ss7_chan* pvt, unsigned char *msg, int msglen){  mtp_enqueue_isup_packet(pvt->link, pvt->cic, msg, msglen, MTP_REQ_ISUP);}static void mtp_enqueue_isup_forward(struct ss7_chan* pvt, unsigned char *msg, int msglen){  mtp_enqueue_isup_packet(pvt->link, pvt->cic, msg, msglen, MTP_REQ_ISUP_FORWARD);}static struct ss7_chan* find_pvt(struct link* slink, int cic){  struct linkset* ls;  int lsi;  ls = slink->linkset;  if (ls->cic_list[cic])    return ls->cic_list[cic];  for (lsi = 0; lsi < n_linksets; lsi++)    if (is_combined_linkset(ls, &linksets[lsi]))      if (linksets[lsi].cic_list[cic])	return linksets[lsi].cic_list[cic];  return NULL;}/* This function must be called with the global lock mutex held. */static void remove_from_idlelist(struct ss7_chan *pvt) {  struct linkset* linkset = pvt->link->linkset;  struct ss7_chan *prev, *cur;

⌨️ 快捷键说明

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