📄 chan_iax2.c
字号:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2006, Digium, Inc. * * Mark Spencer <markster@digium.com> * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. *//*! \file * * \brief Implementation of Inter-Asterisk eXchange Version 2 * * \author Mark Spencer <markster@digium.com> * * \par See also * \arg \ref Config_iax * * \ingroup channel_drivers *//*** MODULEINFO <use>dahdi</use> <depend>res_features</depend> ***/#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 140605 $")#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <sys/mman.h>#include <dirent.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <sys/time.h>#include <sys/signal.h>#include <signal.h>#include <string.h>#include <strings.h>#include <errno.h>#include <unistd.h>#include <netdb.h>#include <fcntl.h>#include <sys/stat.h>#include <regex.h>#if defined(HAVE_ZAPTEL) || defined (HAVE_DAHDI)#include <sys/ioctl.h>#include "asterisk/dahdi_compat.h"#endif#include "asterisk/lock.h"#include "asterisk/frame.h" #include "asterisk/channel.h"#include "asterisk/logger.h"#include "asterisk/module.h"#include "asterisk/pbx.h"#include "asterisk/sched.h"#include "asterisk/io.h"#include "asterisk/config.h"#include "asterisk/options.h"#include "asterisk/cli.h"#include "asterisk/translate.h"#include "asterisk/md5.h"#include "asterisk/cdr.h"#include "asterisk/crypto.h"#include "asterisk/acl.h"#include "asterisk/manager.h"#include "asterisk/callerid.h"#include "asterisk/app.h"#include "asterisk/astdb.h"#include "asterisk/musiconhold.h"#include "asterisk/features.h"#include "asterisk/utils.h"#include "asterisk/causes.h"#include "asterisk/localtime.h"#include "asterisk/aes.h"#include "asterisk/dnsmgr.h"#include "asterisk/devicestate.h"#include "asterisk/netsock.h"#include "asterisk/stringfields.h"#include "asterisk/linkedlists.h"#include "asterisk/astobj2.h"#include "iax2.h"#include "iax2-parser.h"#include "iax2-provision.h"#include "jitterbuf.h"/* Define SCHED_MULTITHREADED to run the scheduler in a special multithreaded mode. */#define SCHED_MULTITHREADED/* Define DEBUG_SCHED_MULTITHREADED to keep track of where each thread is actually doing. */#define DEBUG_SCHED_MULTITHREAD#ifndef IPTOS_MINCOST#define IPTOS_MINCOST 0x02#endif#ifdef SO_NO_CHECKstatic int nochecksums = 0;#endif#define PTR_TO_CALLNO(a) ((unsigned short)(unsigned long)(a))#define CALLNO_TO_PTR(a) ((void *)(unsigned long)(a))#define DEFAULT_THREAD_COUNT 10#define DEFAULT_MAX_THREAD_COUNT 100#define DEFAULT_RETRY_TIME 1000#define MEMORY_SIZE 100#define DEFAULT_DROP 3#define DEBUG_SUPPORT#define MIN_REUSE_TIME 60 /* Don't reuse a call number within 60 seconds *//* Sample over last 100 units to determine historic jitter */#define GAMMA (0.01)static struct ast_codec_pref prefs;static const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)";static char context[80] = "default";static char language[MAX_LANGUAGE] = "";static char regcontext[AST_MAX_CONTEXT] = "";static int maxauthreq = 3;static int max_retries = 4;static int ping_time = 21;static int lagrq_time = 10;static int maxjitterbuffer=1000;static int resyncthreshold=1000;static int maxjitterinterps=10;static int trunkfreq = 20;static int authdebug = 1;static int autokill = 0;static int iaxcompat = 0;static int iaxdefaultdpcache=10 * 60; /* Cache dialplan entries for 10 minutes by default */static int iaxdefaulttimeout = 5; /* Default to wait no more than 5 seconds for a reply to come back */static unsigned int tos = 0;static int min_reg_expire;static int max_reg_expire;static int timingfd = -1; /* Timing file descriptor */static struct ast_netsock_list *netsock;static struct ast_netsock_list *outsock; /*!< used if sourceaddress specified and bindaddr == INADDR_ANY */static int defaultsockfd = -1;int (*iax2_regfunk)(const char *username, int onoff) = NULL;/* Ethernet, etc */#define IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF/* T1, maybe ISDN */#define IAX_CAPABILITY_MEDBANDWIDTH (IAX_CAPABILITY_FULLBANDWIDTH & \ ~AST_FORMAT_SLINEAR & \ ~AST_FORMAT_ULAW & \ ~AST_FORMAT_ALAW & \ ~AST_FORMAT_G722) /* A modem */#define IAX_CAPABILITY_LOWBANDWIDTH (IAX_CAPABILITY_MEDBANDWIDTH & \ ~AST_FORMAT_G726 & \ ~AST_FORMAT_G726_AAL2 & \ ~AST_FORMAT_ADPCM)#define IAX_CAPABILITY_LOWFREE (IAX_CAPABILITY_LOWBANDWIDTH & \ ~AST_FORMAT_G723_1)#define DEFAULT_MAXMS 2000 /* Must be faster than 2 seconds by default */#define DEFAULT_FREQ_OK 60 * 1000 /* How often to check for the host to be up */#define DEFAULT_FREQ_NOTOK 10 * 1000 /* How often to check, if the host is down... */static struct io_context *io;static struct sched_context *sched;static int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH;static int iaxdebug = 0;static int iaxtrunkdebug = 0;static int test_losspct = 0;#ifdef IAXTESTSstatic int test_late = 0;static int test_resync = 0;static int test_jit = 0;static int test_jitpct = 0;#endif /* IAXTESTS */static char accountcode[AST_MAX_ACCOUNT_CODE];static char mohinterpret[MAX_MUSICCLASS];static char mohsuggest[MAX_MUSICCLASS];static int amaflags = 0;static int adsi = 0;static int delayreject = 0;static int iax2_encryption = 0;static struct ast_flags globalflags = { 0 };static pthread_t netthreadid = AST_PTHREADT_NULL;static pthread_t schedthreadid = AST_PTHREADT_NULL;AST_MUTEX_DEFINE_STATIC(sched_lock);static ast_cond_t sched_cond;enum { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2), IAX_STATE_UNCHANGED = (1 << 3),} iax2_state;struct iax2_context { char context[AST_MAX_CONTEXT]; struct iax2_context *next;};enum { IAX_HASCALLERID = (1 << 0), /*!< CallerID has been specified */ IAX_DELME = (1 << 1), /*!< Needs to be deleted */ IAX_TEMPONLY = (1 << 2), /*!< Temporary (realtime) */ IAX_TRUNK = (1 << 3), /*!< Treat as a trunk */ IAX_NOTRANSFER = (1 << 4), /*!< Don't native bridge */ IAX_USEJITTERBUF = (1 << 5), /*!< Use jitter buffer */ IAX_DYNAMIC = (1 << 6), /*!< dynamic peer */ IAX_SENDANI = (1 << 7), /*!< Send ANI along with CallerID */ /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */ IAX_ALREADYGONE = (1 << 9), /*!< Already disconnected */ IAX_PROVISION = (1 << 10), /*!< This is a provisioning request */ IAX_QUELCH = (1 << 11), /*!< Whether or not we quelch audio */ IAX_ENCRYPTED = (1 << 12), /*!< Whether we should assume encrypted tx/rx */ IAX_KEYPOPULATED = (1 << 13), /*!< Whether we have a key populated */ IAX_CODEC_USER_FIRST = (1 << 14), /*!< are we willing to let the other guy choose the codec? */ IAX_CODEC_NOPREFS = (1 << 15), /*!< Force old behaviour by turning off prefs */ IAX_CODEC_NOCAP = (1 << 16), /*!< only consider requested format and ignore capabilities*/ IAX_RTCACHEFRIENDS = (1 << 17), /*!< let realtime stay till your reload */ IAX_RTUPDATE = (1 << 18), /*!< Send a realtime update */ IAX_RTAUTOCLEAR = (1 << 19), /*!< erase me on expire */ IAX_FORCEJITTERBUF = (1 << 20), /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */ IAX_RTIGNOREREGEXPIRE = (1 << 21), /*!< When using realtime, ignore registration expiration */ IAX_TRUNKTIMESTAMPS = (1 << 22), /*!< Send trunk timestamps */ IAX_TRANSFERMEDIA = (1 << 23), /*!< When doing IAX2 transfers, transfer media only */ IAX_MAXAUTHREQ = (1 << 24), /*!< Maximum outstanding AUTHREQ restriction is in place */ IAX_DELAYPBXSTART = (1 << 25), /*!< Don't start a PBX on the channel until the peer sends us a response, so that we've achieved a three-way handshake with them before sending voice or anything else*/ IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */} iax2_flags;static int global_rtautoclear = 120;static int reload_config(void);static int iax2_reload(int fd, int argc, char *argv[]);struct iax2_user { AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(name); AST_STRING_FIELD(secret); AST_STRING_FIELD(dbsecret); AST_STRING_FIELD(accountcode); AST_STRING_FIELD(mohinterpret); AST_STRING_FIELD(mohsuggest); AST_STRING_FIELD(inkeys); /*!< Key(s) this user can use to authenticate to us */ AST_STRING_FIELD(language); AST_STRING_FIELD(cid_num); AST_STRING_FIELD(cid_name); ); int authmethods; int encmethods; int amaflags; int adsi; unsigned int flags; int capability; int maxauthreq; /*!< Maximum allowed outstanding AUTHREQs */ int curauthreq; /*!< Current number of outstanding AUTHREQs */ struct ast_codec_pref prefs; struct ast_ha *ha; struct iax2_context *contexts; struct ast_variable *vars;};struct iax2_peer { AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(name); AST_STRING_FIELD(username); AST_STRING_FIELD(secret); AST_STRING_FIELD(dbsecret); AST_STRING_FIELD(outkey); /*!< What key we use to talk to this peer */ AST_STRING_FIELD(regexten); /*!< Extension to register (if regcontext is used) */ AST_STRING_FIELD(context); /*!< For transfers only */ AST_STRING_FIELD(peercontext); /*!< Context to pass to peer */ AST_STRING_FIELD(mailbox); /*!< Mailbox */ AST_STRING_FIELD(mohinterpret); AST_STRING_FIELD(mohsuggest); AST_STRING_FIELD(inkeys); /*!< Key(s) this peer can use to authenticate to us */ /* Suggested caller id if registering */ AST_STRING_FIELD(cid_num); /*!< Default context (for transfer really) */ AST_STRING_FIELD(cid_name); /*!< Default context (for transfer really) */ AST_STRING_FIELD(zonetag); /*!< Time Zone */ ); struct ast_codec_pref prefs; struct ast_dnsmgr_entry *dnsmgr; /*!< DNS refresh manager */ struct sockaddr_in addr; int formats; int sockfd; /*!< Socket to use for transmission */ struct in_addr mask; int adsi; unsigned int flags; /* Dynamic Registration fields */ struct sockaddr_in defaddr; /*!< Default address if there is one */ int authmethods; /*!< Authentication methods (IAX_AUTH_*) */ int encmethods; /*!< Encryption methods (IAX_ENCRYPT_*) */ int expire; /*!< Schedule entry for expiry */ int expiry; /*!< How soon to expire */ int capability; /*!< Capability */ /* Qualification */ int callno; /*!< Call number of POKE request */ int pokeexpire; /*!< Scheduled qualification-related task (ie iax2_poke_peer_s or iax2_poke_noanswer) */ int lastms; /*!< How long last response took (in ms), or -1 for no response */ int maxms; /*!< Max ms we will accept for the host to be up, 0 to not monitor */ int pokefreqok; /*!< How often to check if the host is up */ int pokefreqnotok; /*!< How often to check when the host has been determined to be down */ int historicms; /*!< How long recent average responses took */ int smoothing; /*!< Sample over how many units to determine historic ms */ struct ast_ha *ha;};#define IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr))static struct iax2_trunk_peer { ast_mutex_t lock; int sockfd; struct sockaddr_in addr; struct timeval txtrunktime; /*!< Transmit trunktime */ struct timeval rxtrunktime; /*!< Receive trunktime */ struct timeval lasttxtime; /*!< Last transmitted trunktime */ struct timeval trunkact; /*!< Last trunk activity */ unsigned int lastsent; /*!< Last sent time */ /* Trunk data and length */ unsigned char *trunkdata; unsigned int trunkdatalen; unsigned int trunkdataalloc; struct iax2_trunk_peer *next; int trunkerror; int calls;} *tpeers = NULL;AST_MUTEX_DEFINE_STATIC(tpeerlock);struct iax_firmware { struct iax_firmware *next; int fd; int mmaplen; int dead; struct ast_iax2_firmware_header *fwh; unsigned char *buf;};enum iax_reg_state { REG_STATE_UNREGISTERED = 0, REG_STATE_REGSENT, REG_STATE_AUTHSENT, REG_STATE_REGISTERED, REG_STATE_REJECTED, REG_STATE_TIMEOUT, REG_STATE_NOAUTH};enum iax_transfer_state { TRANSFER_NONE = 0, TRANSFER_BEGIN, TRANSFER_READY, TRANSFER_RELEASED, TRANSFER_PASSTHROUGH, TRANSFER_MBEGIN, TRANSFER_MREADY, TRANSFER_MRELEASED, TRANSFER_MPASSTHROUGH, TRANSFER_MEDIA, TRANSFER_MEDIAPASS};struct iax2_registry { struct sockaddr_in addr; /*!< Who we connect to for registration purposes */ char username[80]; char secret[80]; /*!< Password or key name in []'s */ char random[80]; int expire; /*!< Sched ID of expiration */ int refresh; /*!< How often to refresh */ enum iax_reg_state regstate; int messages; /*!< Message count, low 8 bits = new, high 8 bits = old */ int callno; /*!< Associated call number if applicable */ struct sockaddr_in us; /*!< Who the server thinks we are */ struct ast_dnsmgr_entry *dnsmgr; /*!< DNS refresh manager */ AST_LIST_ENTRY(iax2_registry) entry;};static AST_LIST_HEAD_STATIC(registrations, iax2_registry);/* Don't retry more frequently than every 10 ms, or less frequently than every 5 seconds */#define MIN_RETRY_TIME 100#define MAX_RETRY_TIME 10000#define MAX_JITTER_BUFFER 50#define MIN_JITTER_BUFFER 10#define DEFAULT_TRUNKDATA 640 * 10 /*!< 40ms, uncompressed linear * 10 channels */#define MAX_TRUNKDATA 640 * 200 /*!< 40ms, uncompressed linear * 200 channels */#define MAX_TIMESTAMP_SKEW 160 /*!< maximum difference between actual and predicted ts for sending *//* If consecutive voice frame timestamps jump by more than this many milliseconds, then jitter buffer will resync */#define TS_GAP_FOR_JB_RESYNC 5000static int iaxthreadcount = DEFAULT_THREAD_COUNT;static int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT;static int iaxdynamicthreadcount = 0;static int iaxdynamicthreadnum = 0;static int iaxactivethreadcount = 0;struct iax_rr { int jitter; int losspct; int losscnt; int packets; int delay;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -