📄 chan_iax2.c
字号:
int dropped; int ooo;};struct chan_iax2_pvt { /*! Socket to send/receive on for this call */ int sockfd; /*! Last received voice format */ int voiceformat; /*! Last received video format */ int videoformat; /*! Last sent voice format */ int svoiceformat; /*! Last sent video format */ int svideoformat; /*! What we are capable of sending */ int capability; /*! Last received timestamp */ unsigned int last; /*! Last sent timestamp - never send the same timestamp twice in a single call */ unsigned int lastsent; /*! Timestamp of the last video frame sent */ unsigned int lastvsent; /*! Next outgoing timestamp if everything is good */ unsigned int nextpred; /*! True if the last voice we transmitted was not silence/CNG */ int notsilenttx; /*! Ping time */ unsigned int pingtime; /*! Max time for initial response */ int maxtime; /*! Peer Address */ struct sockaddr_in addr; /*! Actual used codec preferences */ struct ast_codec_pref prefs; /*! Requested codec preferences */ struct ast_codec_pref rprefs; /*! Our call number */ unsigned short callno; /*! Peer callno */ unsigned short peercallno; /*! Negotiated format, this is only used to remember what format was chosen for an unauthenticated call so that the channel can get created later using the right format */ int chosenformat; /*! Peer selected format */ int peerformat; /*! Peer capability */ int peercapability; /*! timeval that we base our transmission on */ struct timeval offset; /*! timeval that we base our delivery on */ struct timeval rxcore; /*! The jitterbuffer */ jitterbuf *jb; /*! active jb read scheduler id */ int jbid; /*! LAG */ int lag; /*! Error, as discovered by the manager */ int error; /*! Owner if we have one */ struct ast_channel *owner; /*! What's our state? */ struct ast_flags state; /*! Expiry (optional) */ int expiry; /*! Next outgoing sequence number */ unsigned char oseqno; /*! Next sequence number they have not yet acknowledged */ unsigned char rseqno; /*! Next incoming sequence number */ unsigned char iseqno; /*! Last incoming sequence number we have acknowledged */ unsigned char aseqno; AST_DECLARE_STRING_FIELDS( /*! Peer name */ AST_STRING_FIELD(peer); /*! Default Context */ AST_STRING_FIELD(context); /*! Caller ID if available */ AST_STRING_FIELD(cid_num); AST_STRING_FIELD(cid_name); /*! Hidden Caller ID (i.e. ANI) if appropriate */ AST_STRING_FIELD(ani); /*! DNID */ AST_STRING_FIELD(dnid); /*! RDNIS */ AST_STRING_FIELD(rdnis); /*! Requested Extension */ AST_STRING_FIELD(exten); /*! Expected Username */ AST_STRING_FIELD(username); /*! Expected Secret */ AST_STRING_FIELD(secret); /*! MD5 challenge */ AST_STRING_FIELD(challenge); /*! Public keys permitted keys for incoming authentication */ AST_STRING_FIELD(inkeys); /*! Private key for outgoing authentication */ AST_STRING_FIELD(outkey); /*! Preferred language */ AST_STRING_FIELD(language); /*! Hostname/peername for naming purposes */ AST_STRING_FIELD(host); AST_STRING_FIELD(dproot); AST_STRING_FIELD(accountcode); AST_STRING_FIELD(mohinterpret); AST_STRING_FIELD(mohsuggest); ); /*! permitted authentication methods */ int authmethods; /*! permitted encryption methods */ int encmethods; /*! Encryption AES-128 Key */ aes_encrypt_ctx ecx; /*! Decryption AES-128 Key */ aes_decrypt_ctx dcx; /*! 32 bytes of semi-random data */ unsigned char semirand[32]; /*! Associated registry */ struct iax2_registry *reg; /*! Associated peer for poking */ struct iax2_peer *peerpoke; /*! IAX_ flags */ unsigned int flags; int adsi; /*! Transferring status */ enum iax_transfer_state transferring; /*! Transfer identifier */ int transferid; /*! Who we are IAX transfering to */ struct sockaddr_in transfer; /*! What's the new call number for the transfer */ unsigned short transfercallno; /*! Transfer decrypt AES-128 Key */ aes_encrypt_ctx tdcx; /*! Status of knowledge of peer ADSI capability */ int peeradsicpe; /*! Who we are bridged to */ unsigned short bridgecallno; int pingid; /*!< Transmit PING request */ int lagid; /*!< Retransmit lag request */ int autoid; /*!< Auto hangup for Dialplan requestor */ int authid; /*!< Authentication rejection ID */ int authfail; /*!< Reason to report failure */ int initid; /*!< Initial peer auto-congest ID (based on qualified peers) */ int calling_ton; int calling_tns; int calling_pres; int amaflags; struct iax2_dpcache *dpentries; struct ast_variable *vars; /*! last received remote rr */ struct iax_rr remote_rr; /*! Current base time: (just for stats) */ int min; /*! Dropped frame count: (just for stats) */ int frames_dropped; /*! received frame count: (just for stats) */ int frames_received;};static struct ast_iax2_queue { AST_LIST_HEAD(, iax_frame) queue; int count;} iaxq;/*! * This module will get much higher performance when doing a lot of * user and peer lookups if the number of buckets is increased from 1. * However, to maintain old behavior for Asterisk 1.4, these are set to * 1 by default. When using multiple buckets, search order through these * containers is considered random, so you will not be able to depend on * the order the entires are specified in iax.conf for matching order. */#ifdef LOW_MEMORY#define MAX_PEER_BUCKETS 1/* #define MAX_PEER_BUCKETS 17 */#else#define MAX_PEER_BUCKETS 1/* #define MAX_PEER_BUCKETS 563 */#endifstatic struct ao2_container *peers;#define MAX_USER_BUCKETS MAX_PEER_BUCKETSstatic struct ao2_container *users;static struct ast_firmware_list { struct iax_firmware *wares; ast_mutex_t lock;} waresl;/*! Extension exists */#define CACHE_FLAG_EXISTS (1 << 0)/*! Extension is nonexistent */#define CACHE_FLAG_NONEXISTENT (1 << 1)/*! Extension can exist */#define CACHE_FLAG_CANEXIST (1 << 2)/*! Waiting to hear back response */#define CACHE_FLAG_PENDING (1 << 3)/*! Timed out */#define CACHE_FLAG_TIMEOUT (1 << 4)/*! Request transmitted */#define CACHE_FLAG_TRANSMITTED (1 << 5)/*! Timeout */#define CACHE_FLAG_UNKNOWN (1 << 6)/*! Matchmore */#define CACHE_FLAG_MATCHMORE (1 << 7)static struct iax2_dpcache { char peercontext[AST_MAX_CONTEXT]; char exten[AST_MAX_EXTENSION]; struct timeval orig; struct timeval expiry; int flags; unsigned short callno; int waiters[256]; struct iax2_dpcache *next; struct iax2_dpcache *peer; /*!< For linking in peers */} *dpcache;AST_MUTEX_DEFINE_STATIC(dpcache_lock);static void reg_source_db(struct iax2_peer *p);static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in *sin);static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt);#define IAX_IOSTATE_IDLE 0#define IAX_IOSTATE_READY 1#define IAX_IOSTATE_PROCESSING 2#define IAX_IOSTATE_SCHEDREADY 3#define IAX_TYPE_POOL 1#define IAX_TYPE_DYNAMIC 2struct iax2_pkt_buf { AST_LIST_ENTRY(iax2_pkt_buf) entry; size_t len; unsigned char buf[1];};struct iax2_thread { AST_LIST_ENTRY(iax2_thread) list; int type; int iostate;#ifdef SCHED_MULTITHREADED void (*schedfunc)(const void *); const void *scheddata;#endif#ifdef DEBUG_SCHED_MULTITHREAD char curfunc[80];#endif int actions; pthread_t threadid; int threadnum; struct sockaddr_in iosin; unsigned char readbuf[4096]; unsigned char *buf; ssize_t buf_len; size_t buf_size; int iofd; time_t checktime; ast_mutex_t lock; ast_cond_t cond; unsigned int ready_for_signal:1; /*! if this thread is processing a full frame, some information about that frame will be stored here, so we can avoid dispatching any more full frames for that callno to other threads */ struct { unsigned short callno; struct sockaddr_in sin; unsigned char type; unsigned char csub; } ffinfo; /*! Queued up full frames for processing. If more full frames arrive for * a call which this thread is already processing a full frame for, they * are queued up here. */ AST_LIST_HEAD_NOLOCK(, iax2_pkt_buf) full_frames;};/* Thread lists */static AST_LIST_HEAD_STATIC(idle_list, iax2_thread);static AST_LIST_HEAD_STATIC(active_list, iax2_thread);static AST_LIST_HEAD_STATIC(dynamic_list, iax2_thread);static void *iax2_process_thread(void *data);static void signal_condition(ast_mutex_t *lock, ast_cond_t *cond){ ast_mutex_lock(lock); ast_cond_signal(cond); ast_mutex_unlock(lock);}static void iax_debug_output(const char *data){ if (iaxdebug) ast_verbose("%s", data);}static void iax_error_output(const char *data){ ast_log(LOG_WARNING, "%s", data);}static void jb_error_output(const char *fmt, ...){ va_list args; char buf[1024]; va_start(args, fmt); vsnprintf(buf, 1024, fmt, args); va_end(args); ast_log(LOG_ERROR, buf);}static void jb_warning_output(const char *fmt, ...){ va_list args; char buf[1024]; va_start(args, fmt); vsnprintf(buf, 1024, fmt, args); va_end(args); ast_log(LOG_WARNING, buf);}static void jb_debug_output(const char *fmt, ...){ va_list args; char buf[1024]; va_start(args, fmt); vsnprintf(buf, 1024, fmt, args); va_end(args); ast_verbose(buf);}/* XXX We probably should use a mutex when working with this XXX */static struct chan_iax2_pvt *iaxs[IAX_MAX_CALLS];static ast_mutex_t iaxsl[ARRAY_LEN(iaxs)];static struct timeval lastused[ARRAY_LEN(iaxs)];/*! * \brief Another container of iax2_pvt structures * * Active IAX2 pvt structs are also stored in this container, if they are a part * of an active call where we know the remote side's call number. The reason * for this is that incoming media frames do not contain our call number. So, * instead of having to iterate the entire iaxs array, we use this container to * look up calls where the remote side is using a given call number. */static struct ao2_container *iax_peercallno_pvts;/* Flag to use with trunk calls, keeping these calls high up. It halves our effective use but keeps the division between trunked and non-trunked better. */#define TRUNK_CALL_START ARRAY_LEN(iaxs) / 2static int maxtrunkcall = TRUNK_CALL_START;static int maxnontrunkcall = 1;static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);static int expire_registry(const void *data);static int iax2_answer(struct ast_channel *c);static int iax2_call(struct ast_channel *c, char *dest, int timeout);static int iax2_devicestate(void *data);static int iax2_digit_begin(struct ast_channel *c, char digit);static int iax2_digit_end(struct ast_channel *c, char digit, unsigned int duration);static int iax2_do_register(struct iax2_registry *reg);static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan);static int iax2_hangup(struct ast_channel *c);static int iax2_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen);static int iax2_poke_peer(struct iax2_peer *peer, int heldcall);static int iax2_provision(struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force);static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned int ts, int seqno, int now, int transfer, int final);static int iax2_sendhtml(struct ast_channel *c, int subclass, const char *data, int datalen);static int iax2_sendimage(struct ast_channel *c, struct ast_frame *img);static int iax2_sendtext(struct ast_channel *c, const char *text);static int iax2_setoption(struct ast_channel *c, int option, void *data, int datalen);static int iax2_transfer(struct ast_channel *c, const char *dest);static int iax2_write(struct ast_channel *c, struct ast_frame *f);static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int);static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int);static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int);static int send_command_locked(unsigned short callno, char, int, unsigned int, const unsigned char *, int, int);static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int);static struct ast_channel *iax2_request(const char *type, int format, void *data, int *cause);static struct ast_frame *iax2_read(struct ast_channel *c);static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly);static struct iax2_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly);static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, time_t regtime);static void prune_peers(void);static const struct ast_channel_tech iax2_tech = { .type = "IAX2", .description = tdesc, .capabilities = IAX_CAPABILITY_FULLBANDWIDTH, .properties = AST_CHAN_TP_WANTSJITTER, .requester = iax2_request, .devicestate = iax2_devicestate, .send_digit_begin = iax2_digit_begin, .send_digit_end = iax2_digit_end, .send_text = iax2_sendtext, .send_image = iax2_sendimage, .send_html = iax2_sendhtml, .call = iax2_call, .hangup = iax2_hangup, .answer = iax2_answer, .read = iax2_read, .write = iax2_write, .write_video = iax2_write, .indicate = iax2_indicate, .setoption = iax2_setoption, .bridge = iax2_bridge, .transfer = iax2_transfer, .fixup = iax2_fixup,};/* WARNING: insert_idle_thread should only ever be called within the * context of an iax2_process_thread() thread. */static void insert_idle_thread(struct iax2_thread *thread){ if (thread->type == IAX_TYPE_DYNAMIC) { AST_LIST_LOCK(&dynamic_list); AST_LIST_INSERT_TAIL(&dynamic_list, thread, list); AST_LIST_UNLOCK(&dynamic_list); } else { AST_LIST_LOCK(&idle_list); AST_LIST_INSERT_TAIL(&idle_list, thread, list); AST_LIST_UNLOCK(&idle_list); } return;}static struct iax2_thread *find_idle_thread(void){ pthread_attr_t attr; struct iax2_thread *thread = NULL; /* Pop the head of the list off */ AST_LIST_LOCK(&idle_list); thread = AST_LIST_REMOVE_HEAD(&idle_list, list); AST_LIST_UNLOCK(&idle_list);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -