Implementation of Inter-Asterisk eXchange Version 2. More...
#include "asterisk.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 <strings.h>#include <netdb.h>#include <fcntl.h>#include <sys/stat.h>#include <regex.h>#include "asterisk/paths.h"#include "asterisk/lock.h"#include "asterisk/frame.h"#include "asterisk/channel.h"#include "asterisk/module.h"#include "asterisk/pbx.h"#include "asterisk/sched.h"#include "asterisk/io.h"#include "asterisk/config.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/event.h"#include "asterisk/astobj2.h"#include "asterisk/timing.h"#include "iax2.h"#include "iax2-parser.h"#include "iax2-provision.h"#include "jitterbuf.h"Go to the source code of this file.
Data Structures | |
| struct | active_list |
| struct | addr_range |
| struct | callno_entry |
| struct | chan_iax2_pvt |
| struct | create_addr_info |
| struct | dpcache |
| struct | dpreq_data |
| struct | dynamic_list |
| struct | firmwares |
| struct | frame_queue |
| a list of frames that may need to be retransmitted More... | |
| struct | iax2_context |
| struct | iax2_dpcache |
| struct | iax2_peer |
| struct | iax2_pkt_buf |
| struct | iax2_registry |
| struct | iax2_thread |
| struct | iax2_trunk_peer |
| struct | iax2_user |
| struct | iax_dual |
| struct | iax_firmware |
| struct | iax_rr |
| struct | idle_list |
| struct | parsed_dial_string |
| struct | peercnt |
| struct | registrations |
| struct | tpeers |
Defines | |
| #define | ACN_FORMAT1 "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n" |
| #define | ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n" |
| #define | CALLNO_TO_PTR(a) ((void *)(unsigned long)(a)) |
| #define | CALLTOKEN_HASH_FORMAT "%s%d%u%d" |
| #define | CALLTOKEN_IE_FORMAT "%u?%s" |
| #define | DEBUG_SCHED_MULTITHREAD |
| #define | DEBUG_SUPPORT |
| #define | DEFAULT_CONTEXT "default" |
| #define | DEFAULT_DROP 3 |
| #define | DEFAULT_FREQ_NOTOK 10 * 1000 |
| #define | DEFAULT_FREQ_OK 60 * 1000 |
| #define | DEFAULT_MAX_THREAD_COUNT 100 |
| #define | DEFAULT_MAXMS 2000 |
| #define | DEFAULT_RETRY_TIME 1000 |
| #define | DEFAULT_THREAD_COUNT 10 |
| #define | DEFAULT_TRUNKDATA 640 * 10 |
| #define | FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s %s%s %3s%s\n" |
| #define | FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
| #define | FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" |
| #define | FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" |
| #define | FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s %s %9s\n" |
| #define | FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
| #define | FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" |
| #define | FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" |
| #define | FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" |
| #define | GAMMA (0.01) |
| #define | IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) |
| #define | IAX_CALLENCRYPTED(pvt) (ast_test_flag(pvt, IAX_ENCRYPTED) && ast_test_flag(pvt, IAX_KEYPOPULATED)) |
| #define | IAX_CAPABILITY_FULLBANDWIDTH (0xFFFF & ~AST_FORMAT_AUDIO_UNDEFINED) |
| #define | IAX_CAPABILITY_LOWBANDWIDTH |
| #define | IAX_CAPABILITY_LOWFREE |
| #define | IAX_CAPABILITY_MEDBANDWIDTH |
| #define | IAX_DEBUGDIGEST(msg, key) |
| #define | MARK_IAX_SUBCLASS_TX 0x8000 |
| #define | MAX_JITTER_BUFFER 50 |
| #define | MAX_PEER_BUCKETS 563 |
| #define | MAX_RETRY_TIME 10000 |
| #define | MAX_TIMESTAMP_SKEW 160 |
| #define | MAX_TRUNK_MTU 1240 |
| Maximum transmission unit for the UDP packet in the trunk not to be fragmented. This is based on 1516 - ethernet - ip - udp - iax minus one g711 frame = 1240. | |
| #define | MAX_TRUNKDATA 640 * 200 |
| #define | MAX_USER_BUCKETS MAX_PEER_BUCKETS |
| #define | MEMORY_SIZE 100 |
| #define | MIN_JITTER_BUFFER 10 |
| #define | MIN_RETRY_TIME 100 |
| #define | MIN_REUSE_TIME 60 |
| #define | PTR_TO_CALLNO(a) ((unsigned short)(unsigned long)(a)) |
| #define | SCHED_MULTITHREADED |
| #define | schedule_action(func, data) __schedule_action(func, data, __PRETTY_FUNCTION__) |
| #define | TRUNK_CALL_START ARRAY_LEN(iaxs) / 2 |
| #define | TS_GAP_FOR_JB_RESYNC 5000 |
Enumerations | |
| enum | { CACHE_FLAG_EXISTS = (1 << 0), CACHE_FLAG_NONEXISTENT = (1 << 1), CACHE_FLAG_CANEXIST = (1 << 2), CACHE_FLAG_PENDING = (1 << 3), CACHE_FLAG_TIMEOUT = (1 << 4), CACHE_FLAG_TRANSMITTED = (1 << 5), CACHE_FLAG_UNKNOWN = (1 << 6), CACHE_FLAG_MATCHMORE = (1 << 7) } |
| enum | { NEW_PREVENT = 0, NEW_ALLOW = 1, NEW_FORCE = 2, NEW_ALLOW_CALLTOKEN_VALIDATED = 3 } |
| enum | calltoken_peer_enum { CALLTOKEN_DEFAULT = 0, CALLTOKEN_YES = 1, CALLTOKEN_AUTO = 2, CALLTOKEN_NO = 3 } |
Call token validation settings. More... | |
| enum | iax2_flags { IAX_HASCALLERID = (1 << 0), IAX_DELME = (1 << 1), IAX_TEMPONLY = (1 << 2), IAX_TRUNK = (1 << 3), IAX_NOTRANSFER = (1 << 4), IAX_USEJITTERBUF = (1 << 5), IAX_DYNAMIC = (1 << 6), IAX_SENDANI = (1 << 7), IAX_ALREADYGONE = (1 << 9), IAX_PROVISION = (1 << 10), IAX_QUELCH = (1 << 11), IAX_ENCRYPTED = (1 << 12), IAX_KEYPOPULATED = (1 << 13), IAX_CODEC_USER_FIRST = (1 << 14), IAX_CODEC_NOPREFS = (1 << 15), IAX_CODEC_NOCAP = (1 << 16), IAX_RTCACHEFRIENDS = (1 << 17), IAX_RTUPDATE = (1 << 18), IAX_RTAUTOCLEAR = (1 << 19), IAX_FORCEJITTERBUF = (1 << 20), IAX_RTIGNOREREGEXPIRE = (1 << 21), IAX_TRUNKTIMESTAMPS = (1 << 22), IAX_TRANSFERMEDIA = (1 << 23), IAX_MAXAUTHREQ = (1 << 24), IAX_DELAYPBXSTART = (1 << 25), IAX_ALLOWFWDOWNLOAD = (1 << 26) } |
| enum | iax2_state { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2) } |
| enum | iax2_thread_iostate { IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, IAX_IOSTATE_PROCESSING, IAX_IOSTATE_SCHEDREADY } |
| enum | iax2_thread_type { IAX_THREAD_TYPE_POOL, IAX_THREAD_TYPE_DYNAMIC } |
| 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 } |
Functions | |
| static void | __attempt_transmit (const void *data) |
| static void | __auth_reject (const void *nothing) |
| static void | __auto_congest (const void *nothing) |
| static void | __auto_hangup (const void *nothing) |
| static int | __do_deliver (void *data) |
| static void | __expire_registry (const void *data) |
| static int | __find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int return_locked, int check_dcallno) |
| static void | __get_from_jb (const void *p) |
| static void | __iax2_do_register_s (const void *data) |
| static void | __iax2_poke_noanswer (const void *data) |
| static void | __iax2_poke_peer_s (const void *data) |
| static int | __iax2_show_peers (int manager, int fd, struct mansession *s, int argc, char *argv[]) |
| static void | __reg_module (void) |
| static int | __schedule_action (void(*func)(const void *data), const void *data, const char *funcname) |
| static int | __send_command (struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const unsigned char *data, int datalen, int seqno, int now, int transfer, int final) |
| static void | __send_lagrq (const void *data) |
| static void | __send_ping (const void *data) |
| static int | __unload_module (void) |
| static void | __unreg_module (void) |
| static int | acf_channel_read (struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen) |
| static int | acf_channel_write (struct ast_channel *chan, const char *function, char *data, const char *value) |
| static int | acf_iaxvar_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| static int | acf_iaxvar_write (struct ast_channel *chan, const char *cmd, char *data, const char *value) |
| static int | add_calltoken_ignore (const char *addr) |
| static void | add_empty_calltoken_ie (struct chan_iax2_pvt *pvt, struct iax_ie_data *ied) |
| static int | addr_range_cmp_cb (void *obj, void *arg, int flags) |
| static int | addr_range_delme_cb (void *obj, void *arg, int flags) |
| static int | addr_range_hash_cb (const void *obj, const int flags) |
| static int | addr_range_match_address_cb (void *obj, void *arg, int flags) |
| static int | apply_context (struct iax2_context *con, const char *context) |
| static int | ast_cli_netstats (struct mansession *s, int fd, int limit_fmt) |
| static struct ast_channel * | ast_iax2_new (int callno, int state, int capability) |
| Create new call, interface with the PBX core. | |
| static int | attempt_transmit (const void *data) |
| static int | auth_fail (int callno, int failcode) |
| static int | auth_reject (const void *data) |
| static int | authenticate (const char *challenge, const char *secret, const char *keyn, int authmethods, struct iax_ie_data *ied, struct sockaddr_in *sin, struct chan_iax2_pvt *pvt) |
| static int | authenticate_reply (struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, const char *override, const char *okey) |
| static int | authenticate_request (int call_num) |
| static int | authenticate_verify (struct chan_iax2_pvt *p, struct iax_ies *ies) |
| static int | auto_congest (const void *data) |
| static int | auto_hangup (const void *data) |
| static void | build_callno_limits (struct ast_variable *v) |
| static struct iax2_context * | build_context (const char *context) |
| static void | build_ecx_key (const unsigned char *digest, struct chan_iax2_pvt *pvt) |
| static void | build_encryption_keys (const unsigned char *digest, struct chan_iax2_pvt *pvt) |
| static struct iax2_peer * | build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly) |
| Create peer structure based on configuration. | |
| static void | build_rand_pad (unsigned char *buf, ssize_t len) |
| static struct iax2_user * | build_user (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly) |
| Create in-memory user structure from configuration. | |
| static int | cache_get_callno_locked (const char *data) |
| static unsigned int | calc_rxstamp (struct chan_iax2_pvt *p, unsigned int offset) |
| static unsigned int | calc_timestamp (struct chan_iax2_pvt *p, unsigned int ts, struct ast_frame *f) |
| static unsigned int | calc_txpeerstamp (struct iax2_trunk_peer *tpeer, int sampms, struct timeval *now) |
| static int | callno_hash (const void *obj, const int flags) |
| static int | calltoken_required (struct sockaddr_in *sin, const char *name, int subclass) |
| static int | check_access (int callno, struct sockaddr_in *sin, struct iax_ies *ies) |
| static int | check_provisioning (struct sockaddr_in *sin, int sockfd, char *si, unsigned int ver) |
| static int | check_srcaddr (struct sockaddr *sa, socklen_t salen) |
| Check if address can be used as packet source. | |
| static int | complete_dpreply (struct chan_iax2_pvt *pvt, struct iax_ies *ies) |
| static char * | complete_iax2_peers (const char *line, const char *word, int pos, int state) |
| static char * | complete_iax2_unregister (const char *line, const char *word, int pos, int state) |
| static int | complete_transfer (int callno, struct iax_ies *ies) |
| static unsigned char | compress_subclass (int subclass) |
| static void | construct_rr (struct chan_iax2_pvt *pvt, struct iax_ie_data *iep) |
| static int | create_addr (const char *peername, struct ast_channel *c, struct sockaddr_in *sin, struct create_addr_info *cai) |
| static int | create_callno_pools (void) |
| static int | decode_frame (ast_aes_decrypt_key *dcx, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen) |
| static int | decrypt_frame (int callno, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen) |
| static void | defer_full_frame (struct iax2_thread *from_here, struct iax2_thread *to_here) |
| Queue the last read full frame for processing by a certain thread. | |
| static void | delete_users (void) |
| static void | destroy_firmware (struct iax_firmware *cur) |
| static void | dp_lookup (int callno, const char *context, const char *callednum, const char *callerid, int skiplock) |
| static void * | dp_lookup_thread (void *data) |
| static int | encrypt_frame (ast_aes_encrypt_key *ecx, struct ast_iax2_full_hdr *fh, unsigned char *poo, int *datalen) |
| static int | expire_registry (const void *data) |
| static struct iax2_dpcache * | find_cache (struct ast_channel *chan, const char *data, const char *context, const char *exten, int priority) |
| static int | find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int full_frame) |
| static int | find_callno_locked (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int full_frame) |
| static struct iax2_thread * | find_idle_thread (void) |
| static struct iax2_peer * | find_peer (const char *name, int realtime) |
| static struct iax2_trunk_peer * | find_tpeer (struct sockaddr_in *sin, int fd) |
| static struct iax2_user * | find_user (const char *name) |
| static unsigned int | fix_peerts (struct timeval *rxtrunktime, int callno, unsigned int ts) |
| static void | free_context (struct iax2_context *con) |
| static int | function_iaxpeer (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| static int | get_auth_methods (const char *value) |
| static int | get_encrypt_methods (const char *s) |
| static int | get_from_jb (const void *p) |
| static struct callno_entry * | get_unused_callno (int trunk, int validated) |
| static int | handle_call_token (struct ast_iax2_full_hdr *fh, struct iax_ies *ies, struct sockaddr_in *sin, int fd) |
| static char * | handle_cli_iax2_provision (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_prune_realtime (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_set_debug_jb (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_set_debug_trunk (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_set_mtu (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Set trunk MTU from CLI. | |
| static char * | handle_cli_iax2_show_cache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_show_callno_limits (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_show_firmware (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_show_netstats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_show_peer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show one peer in detail. | |
| static char * | handle_cli_iax2_show_peers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_show_registry (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_show_threads (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_test_losspct (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_iax2_unregister (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static void | handle_deferred_full_frames (struct iax2_thread *thread) |
| Handle any deferred full frames for this thread. | |
| static int | handle_error (void) |
| static int | iax2_ack_registry (struct iax_ies *ies, struct sockaddr_in *sin, int callno) |
| Acknowledgment received for OUR registration. | |
| static int attribute_pure | iax2_allow_new (int frametype, int subclass, int inbound) |
| static void | iax2_ami_channelupdate (struct chan_iax2_pvt *pvt) |
| Send manager event at call setup to link between Asterisk channel name and IAX2 call identifiers. | |
| static int | iax2_answer (struct ast_channel *c) |
| static int | iax2_append_register (const char *hostname, const char *username, const char *secret, const char *porta) |
| 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 | iax2_call (struct ast_channel *c, char *dest, int timeout) |
| static int | iax2_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| part of the IAX2 dial plan switch interface | |
| static unsigned int | iax2_datetime (const char *tz) |
| static void | iax2_destroy (int callno) |
| static void | iax2_destroy_helper (struct chan_iax2_pvt *pvt) |
| static int | iax2_devicestate (void *data) |
| Part of the device state notification system ---. | |
| 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_do_register_s (const void *data) |
| static void | iax2_dprequest (struct iax2_dpcache *dp, int callno) |
| static void * | iax2_dup_variable_datastore (void *) |
| static int | iax2_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| Execute IAX2 dialplan switch. | |
| static int | iax2_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| Part of the IAX2 switch interface. | |
| static int | iax2_fixup (struct ast_channel *oldchannel, struct ast_channel *newchan) |
| static void | iax2_frame_free (struct iax_frame *fr) |
| static void | iax2_free_variable_datastore (void *) |
| static int | iax2_getpeername (struct sockaddr_in sin, char *host, int len) |
| static int | iax2_getpeertrunk (struct sockaddr_in sin) |
| 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_key_rotate (const void *vpvt) |
| static int | iax2_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| Part of the IAX2 Switch interface. | |
| static int | iax2_poke_noanswer (const void *data) |
| static int | iax2_poke_peer (struct iax2_peer *peer, int heldcall) |
| static int | iax2_poke_peer_cb (void *obj, void *arg, int flags) |
| static int | iax2_poke_peer_s (const void *data) |
| static int | iax2_predestroy (int callno) |
| static void * | iax2_process_thread (void *data) |
| static void | iax2_process_thread_cleanup (void *data) |
| static int | iax2_prov_app (struct ast_channel *chan, void *data) |
| static int | iax2_provision (struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force) |
| static int | iax2_queue_control_data (int callno, enum ast_control_frame_type control, const void *data, size_t datalen) |
| Queue a control frame on the ast_channel owner. | |
| static int | iax2_queue_frame (int callno, struct ast_frame *f) |
| Queue a frame to a call's owning asterisk channel. | |
| static int | iax2_queue_hangup (int callno) |
| Queue a hangup frame on the ast_channel owner. | |
| static struct ast_frame * | iax2_read (struct ast_channel *c) |
| static int | iax2_register (const char *value, int lineno) |
| static struct ast_channel * | iax2_request (const char *type, int format, void *data, int *cause) |
| static int | iax2_sched_add (struct sched_context *con, int when, ast_sched_cb callback, const void *data) |
| static int | iax2_sched_replace (int id, struct sched_context *con, int when, ast_sched_cb callback, const void *data) |
| 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_start_transfer (unsigned short callno0, unsigned short callno1, int mediaonly) |
| static int | iax2_transfer (struct ast_channel *c, const char *dest) |
| static int | iax2_transmit (struct iax_frame *fr) |
| static int | iax2_trunk_expired (struct iax2_trunk_peer *tpeer, struct timeval *now) |
| static int | iax2_trunk_queue (struct chan_iax2_pvt *pvt, struct iax_frame *fr) |
| static int | iax2_vnak (int callno) |
| static int | iax2_write (struct ast_channel *c, struct ast_frame *f) |
| static int | iax_check_version (char *dev) |
| static void | iax_debug_output (const char *data) |
| static void | iax_error_output (const char *data) |
| static int | iax_firmware_append (struct iax_ie_data *ied, const unsigned char *dev, unsigned int desc) |
| static void | iax_outputframe (struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen) |
| static int | iax_park (struct ast_channel *chan1, struct ast_channel *chan2) |
| static void * | iax_park_thread (void *stuff) |
| static struct iax_frame * | iaxfrdup2 (struct iax_frame *fr) |
| static void | insert_idle_thread (struct iax2_thread *thread) |
| static void | jb_debug_output (const char *fmt,...) |
| static void | jb_error_output (const char *fmt,...) |
| static void | jb_warning_output (const char *fmt,...) |
| static int | load_module (void) |
| Load IAX2 module, load configuraiton ---. | |
| static int | load_objects (void) |
| static void | lock_both (unsigned short callno0, unsigned short callno1) |
| static void | log_jitterstats (unsigned short callno) |
| static int | make_trunk (unsigned short callno, int locked) |
| static int | manager_iax2_show_netstats (struct mansession *s, const struct message *m) |
| static int | manager_iax2_show_peer_list (struct mansession *s, const struct message *m) |
| callback to display iax peers in manager format | |
| static int | manager_iax2_show_peers (struct mansession *s, const struct message *m) |
| callback to display iax peers in manager | |
| static int | match (struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno) |
| static void | memcpy_decrypt (unsigned char *dst, const unsigned char *src, int len, ast_aes_decrypt_key *dcx) |
| static void | memcpy_encrypt (unsigned char *dst, const unsigned char *src, int len, ast_aes_encrypt_key *ecx) |
| static void | merge_encryption (struct chan_iax2_pvt *p, unsigned int enc) |
| static void | mwi_event_cb (const struct ast_event *event, void *userdata) |
| static void * | network_thread (void *ignore) |
| static struct chan_iax2_pvt * | new_iax (struct sockaddr_in *sin, const char *host) |
| static void | parse_dial_string (char *data, struct parsed_dial_string *pds) |
| Parses an IAX dial string into its component parts. | |
| static int | peer_cmp_cb (void *obj, void *arg, int flags) |
| static int | peer_delme_cb (void *obj, void *arg, int flags) |
| static void | peer_destructor (void *obj) |
| static int | peer_hash_cb (const void *obj, const int flags) |
| static struct iax2_peer * | peer_ref (struct iax2_peer *peer) |
| static int | peer_set_sock_cb (void *obj, void *arg, int flags) |
| static int | peer_set_srcaddr (struct iax2_peer *peer, const char *srcaddr) |
| Parse the "sourceaddress" value, lookup in netsock list and set peer's sockfd. Defaults to defaultsockfd if not found. | |
| static int | peer_status (struct iax2_peer *peer, char *status, int statuslen) |
| peer_status: Report Peer status in character string | |
| static struct iax2_peer * | peer_unref (struct iax2_peer *peer) |
| static int | peercnt_add (struct sockaddr_in *sin) |
| static int | peercnt_cmp_cb (void *obj, void *arg, int flags) |
| static int | peercnt_hash_cb (const void *obj, const int flags) |
| static void | peercnt_modify (unsigned char reg, uint16_t limit, struct sockaddr_in *sin) |
| static void | peercnt_remove (struct peercnt *peercnt) |
| static int | peercnt_remove_by_addr (struct sockaddr_in *sin) |
| static int | peercnt_remove_cb (const void *obj) |
| static void | poke_all_peers (void) |
| static int | prune_addr_range_cb (void *obj, void *arg, int flags) |
| static void | prune_peers (void) |
| static void | prune_users (void) |
| static int | pvt_cmp_cb (void *obj, void *arg, int flags) |
| static void | pvt_destructor (void *obj) |
| static int | pvt_hash_cb (const void *obj, const int flags) |
| static int | raw_hangup (struct sockaddr_in *sin, unsigned short src, unsigned short dst, int sockfd) |
| static struct iax2_peer * | realtime_peer (const char *peername, struct sockaddr_in *sin) |
| static void | realtime_update_peer (const char *peername, struct sockaddr_in *sin, time_t regtime) |
| static struct iax2_user * | realtime_user (const char *username, struct sockaddr_in *sin) |
| static void | reg_source_db (struct iax2_peer *p) |
| static void | register_peer_exten (struct iax2_peer *peer, int onoff) |
| static int | register_verify (int callno, struct sockaddr_in *sin, struct iax_ies *ies) |
| Verify inbound registration. | |
| static int | registry_authrequest (int callno) |
| static int | registry_rerequest (struct iax_ies *ies, int callno, struct sockaddr_in *sin) |
| static char * | regstate2str (int regstate) |
| static int | reload (void) |
| static int | reload_config (void) |
| static void | reload_firmware (int unload) |
| static void | remove_by_peercallno (struct chan_iax2_pvt *pvt) |
| static void | remove_by_transfercallno (struct chan_iax2_pvt *pvt) |
| static int | replace_callno (const void *obj) |
| static void | requirecalltoken_mark_auto (const char *name, int subclass) |
| static void | resend_with_token (int callno, struct iax_frame *f, const char *newtoken) |
| static void | save_osptoken (struct iax_frame *fr, struct iax_ies *ies) |
| static void | save_rr (struct iax_frame *fr, struct iax_ies *ies) |
| static void | sched_delay_remove (struct sockaddr_in *sin, struct callno_entry *callno_entry) |
| static void * | sched_thread (void *ignore) |
| static int | schedule_delivery (struct iax_frame *fr, int updatehistory, int fromtrunk, unsigned int *tsout) |
| static int | scheduled_destroy (const void *vid) |
| static int | send_apathetic_reply (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int command, int ts, unsigned char seqno, int sockfd, struct iax_ie_data *ied) |
| 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 int | send_lagrq (const void *data) |
| static int | send_packet (struct iax_frame *f) |
| static int | send_ping (const void *data) |
| static int | send_trunk (struct iax2_trunk_peer *tpeer, struct timeval *now) |
| static int | set_config (const char *config_file, int reload) |
| Load configuration. | |
| static void | set_config_destroy (void) |
| static void | set_peercnt_limit (struct peercnt *peercnt) |
| static int | set_peercnt_limit_all_cb (void *obj, void *arg, int flags) |
| static void | signal_condition (ast_mutex_t *lock, ast_cond_t *cond) |
| static int | socket_process (struct iax2_thread *thread) |
| static int | socket_process_meta (int packet_len, struct ast_iax2_meta_hdr *meta, struct sockaddr_in *sin, int sockfd, struct iax_frame *fr) |
| static int | socket_read (int *id, int fd, short events, void *cbdata) |
| static void | spawn_dp_lookup (int callno, const char *context, const char *callednum, const char *callerid) |
| static int | start_network_thread (void) |
| static void | stop_stuff (int callno) |
| static void | store_by_peercallno (struct chan_iax2_pvt *pvt) |
| static void | store_by_transfercallno (struct chan_iax2_pvt *pvt) |
| static int | timing_read (int *id, int fd, short events, void *cbdata) |
| static int | transfercallno_pvt_cmp_cb (void *obj, void *arg, int flags) |
| static int | transfercallno_pvt_hash_cb (const void *obj, const int flags) |
| static int | transmit_trunk (struct iax_frame *f, struct sockaddr_in *sin, int sockfd) |
| static int | try_firmware (char *s) |
| static int | try_transfer (struct chan_iax2_pvt *pvt, struct iax_ies *ies) |
| static int | uncompress_subclass (unsigned char csub) |
| static void | unlink_peer (struct iax2_peer *peer) |
| static int | unload_module (void) |
| static void | unlock_both (unsigned short callno0, unsigned short callno1) |
| static void | unwrap_timestamp (struct iax_frame *fr) |
| static void | update_jbsched (struct chan_iax2_pvt *pvt) |
| static void | update_max_nontrunk (void) |
| static void | update_max_trunk (void) |
| static int | update_packet (struct iax_frame *f) |
| static int | update_registry (struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh) |
| static int | user_cmp_cb (void *obj, void *arg, int flags) |
| static int | user_delme_cb (void *obj, void *arg, int flags) |
| static void | user_destructor (void *obj) |
| static int | user_hash_cb (const void *obj, const int flags) |
| static struct iax2_user * | user_ref (struct iax2_user *user) |
| static struct iax2_user * | user_unref (struct iax2_user *user) |
| static void | vnak_retransmit (int callno, int last) |
| static int | wait_for_peercallno (struct chan_iax2_pvt *pvt) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Inter Asterisk eXchange (Ver 2)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
| static char | accountcode [AST_MAX_ACCOUNT_CODE] |
| static int | adsi = 0 |
| static int | amaflags = 0 |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static int | authdebug = 1 |
| static int | autokill = 0 |
| static struct ao2_container * | callno_limits |
| static struct ao2_container * | callno_pool |
| static const unsigned int | CALLNO_POOL_BUCKETS = 2699 |
| static struct ao2_container * | callno_pool_trunk |
| static struct ao2_container * | calltoken_ignores |
| static struct ast_cli_entry | cli_iax2 [] |
| static struct sockaddr_in | debugaddr |
| static uint16_t | DEFAULT_MAXCALLNO_LIMIT = 2048 |
| static uint16_t | DEFAULT_MAXCALLNO_LIMIT_NONVAL = 8192 |
| static char | default_parkinglot [AST_MAX_CONTEXT] |
| static int | defaultsockfd = -1 |
| static int | delayreject = 0 |
| static int | global_max_trunk_mtu |
| static uint16_t | global_maxcallno |
| static uint16_t | global_maxcallno_nonval |
| static int | global_rtautoclear = 120 |
| static struct ast_flags | globalflags = { 0 } |
| static int | iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH |
| static int | iax2_encryption = 0 |
| int(* | iax2_regfunk )(const char *username, int onoff) = NULL |
| static struct ast_switch | iax2_switch |
| static struct ast_channel_tech | iax2_tech |
| static struct ast_datastore_info | iax2_variable_datastore_info |
| static struct ao2_container * | iax_peercallno_pvts |
| Another container of iax2_pvt structures. | |
| static struct ao2_container * | iax_transfercallno_pvts |
| Another container of iax2_pvt structures. | |
| static int | iaxactivethreadcount = 0 |
| static int | iaxcompat = 0 |
| static int | iaxdebug = 0 |
| static int | iaxdefaultdpcache = 10 * 60 |
| static int | iaxdefaulttimeout = 5 |
| static int | iaxdynamicthreadcount = 0 |
| static int | iaxdynamicthreadnum = 0 |
| static int | iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT |
| struct ast_custom_function | iaxpeer_function |
| static struct chan_iax2_pvt * | iaxs [IAX_MAX_CALLS] |
| an array of iax2 pvt structures | |
| static ast_mutex_t | iaxsl [ARRAY_LEN(iaxs)] |
| chan_iax2_pvt structure locks | |
| static int | iaxthreadcount = DEFAULT_THREAD_COUNT |
| static int | iaxtrunkdebug = 0 |
| static struct ast_custom_function | iaxvar_function |
| static struct io_context * | io |
| static int | jittertargetextra = 40 |
| static int | lagrq_time = 10 |
| static char | language [MAX_LANGUAGE] = "" |
| static int | last_authmethod = 0 |
| static const time_t | MAX_CALLTOKEN_DELAY = 10 |
| static int | max_reg_expire |
| static int | max_retries = 4 |
| static int | maxauthreq = 3 |
| static int | maxjitterbuffer = 1000 |
| static int | maxjitterinterps = 10 |
| static int | maxnontrunkcall = 1 |
| static int | maxtrunkcall = TRUNK_CALL_START |
| static int | min_reg_expire |
| static char | mohinterpret [MAX_MUSICCLASS] |
| static char | mohsuggest [MAX_MUSICCLASS] |
| static struct ast_netsock_list * | netsock |
| static pthread_t | netthreadid = AST_PTHREADT_NULL |
| static struct ast_netsock_list * | outsock |
| static char * | papp = "IAX2Provision" |
| static char * | pdescrip |
| static struct ao2_container * | peercnts |
| static struct ao2_container * | peers |
| static int | ping_time = 21 |
| static struct ast_codec_pref | prefs |
| static char * | psyn = "Provision a calling IAXy with a given template" |
| struct { | |
| unsigned int cos | |
| unsigned int tos | |
| } | qos |
| static int | randomcalltokendata |
| static char | regcontext [AST_MAX_CONTEXT] = "" |
| static int | resyncthreshold = 1000 |
| static struct sched_context * | sched |
| static ast_cond_t | sched_cond |
| static ast_mutex_t | sched_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static pthread_t | schedthreadid = AST_PTHREADT_NULL |
| static int | srvlookup = 0 |
| static const char | tdesc [] = "Inter Asterisk eXchange Driver (Ver 2)" |
| static int | test_losspct = 0 |
| static struct ast_timer * | timer |
| static uint16_t | total_nonval_callno_used = 0 |
| static int | trunk_maxmtu |
| static int | trunk_nmaxmtu |
| static int | trunk_timed |
| static int | trunk_untimed |
| static int | trunkfreq = 20 |
| static int | trunkmaxsize = MAX_TRUNKDATA |
| static struct ao2_container * | users |
Implementation of Inter-Asterisk eXchange Version 2.
Definition in file chan_iax2.c.
| #define ACN_FORMAT1 "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n" |
Referenced by ast_cli_netstats().
| #define ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n" |
Referenced by ast_cli_netstats().
| #define CALLNO_TO_PTR | ( | a | ) | ((void *)(unsigned long)(a)) |
Definition at line 111 of file chan_iax2.c.
Referenced by ast_iax2_new(), iax2_call(), iax2_hangup(), and update_jbsched().
| #define CALLTOKEN_HASH_FORMAT "%s%d%u%d" |
Referenced by handle_call_token().
| #define CALLTOKEN_IE_FORMAT "%u?%s" |
Referenced by handle_call_token().
| #define DEBUG_SCHED_MULTITHREAD |
Definition at line 103 of file chan_iax2.c.
| #define DEBUG_SUPPORT |
Definition at line 119 of file chan_iax2.c.
| #define DEFAULT_CONTEXT "default" |
Definition at line 138 of file chan_iax2.c.
Referenced by check_access(), handle_cli_iax2_show_users(), and reload_config().
| #define DEFAULT_DROP 3 |
Definition at line 117 of file chan_iax2.c.
| #define DEFAULT_FREQ_NOTOK 10 * 1000 |
Definition at line 207 of file chan_iax2.c.
Referenced by build_peer(), handle_response_peerpoke(), and sip_poke_noanswer().
| #define DEFAULT_FREQ_OK 60 * 1000 |
Definition at line 206 of file chan_iax2.c.
Referenced by build_peer().
| #define DEFAULT_MAX_THREAD_COUNT 100 |
Definition at line 114 of file chan_iax2.c.
| #define DEFAULT_MAXMS 2000 |
Definition at line 205 of file chan_iax2.c.
| #define DEFAULT_RETRY_TIME 1000 |
Definition at line 115 of file chan_iax2.c.
Referenced by __find_callno(), and complete_transfer().
| #define DEFAULT_THREAD_COUNT 10 |
Definition at line 113 of file chan_iax2.c.
| #define DEFAULT_TRUNKDATA 640 * 10 |
40ms, uncompressed linear * 10 channels
Definition at line 486 of file chan_iax2.c.
Referenced by iax2_trunk_queue().
| #define FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s %s%s %3s%s\n" |
| #define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
| #define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" |
| #define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" |
| #define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s %s %9s\n" |
| #define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
| #define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" |
| #define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" |
| #define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" |
| #define GAMMA (0.01) |
Definition at line 124 of file chan_iax2.c.
| #define IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) |
Definition at line 407 of file chan_iax2.c.
Referenced by iax2_trunk_queue().
| #define IAX_CALLENCRYPTED | ( | pvt | ) | (ast_test_flag(pvt, IAX_ENCRYPTED) && ast_test_flag(pvt, IAX_KEYPOPULATED)) |
Definition at line 210 of file chan_iax2.c.
Referenced by iax2_send(), iax2_start_transfer(), and socket_process().
| #define IAX_CAPABILITY_FULLBANDWIDTH (0xFFFF & ~AST_FORMAT_AUDIO_UNDEFINED) |
Definition at line 187 of file chan_iax2.c.
Referenced by cache_get_callno_locked(), and set_config().
| #define IAX_CAPABILITY_LOWBANDWIDTH |
(IAX_CAPABILITY_MEDBANDWIDTH & \ ~AST_FORMAT_G726 & \ ~AST_FORMAT_G726_AAL2 & \ ~AST_FORMAT_ADPCM)
Definition at line 196 of file chan_iax2.c.
Referenced by set_config().
| #define IAX_CAPABILITY_LOWFREE |
Definition at line 201 of file chan_iax2.c.
| #define IAX_CAPABILITY_MEDBANDWIDTH |
Definition at line 189 of file chan_iax2.c.
Referenced by set_config().
| #define IAX_DEBUGDIGEST | ( | msg, | |||
| key | ) |
Definition at line 213 of file chan_iax2.c.
Referenced by iax2_key_rotate(), and socket_process().
| #define MARK_IAX_SUBCLASS_TX 0x8000 |
Definition at line 494 of file chan_iax2.c.
Referenced by ast_cli_netstats(), handle_cli_iax2_show_channels(), and iax2_send().
| #define MAX_JITTER_BUFFER 50 |
Definition at line 483 of file chan_iax2.c.
| #define MAX_PEER_BUCKETS 563 |
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.
Definition at line 732 of file chan_iax2.c.
Referenced by load_objects().
| #define MAX_RETRY_TIME 10000 |
Definition at line 481 of file chan_iax2.c.
Referenced by __attempt_transmit(), and iax2_send().
| #define MAX_TIMESTAMP_SKEW 160 |
maximum difference between actual and predicted ts for sending
Definition at line 488 of file chan_iax2.c.
| #define MAX_TRUNK_MTU 1240 |
Maximum transmission unit for the UDP packet in the trunk not to be fragmented. This is based on 1516 - ethernet - ip - udp - iax minus one g711 frame = 1240.
Definition at line 133 of file chan_iax2.c.
Referenced by handle_cli_iax2_set_mtu(), and set_config().
| #define MAX_TRUNKDATA 640 * 200 |
40ms, uncompressed linear * 200 channels
Definition at line 154 of file chan_iax2.c.
Referenced by set_config(), and set_config_destroy().
| #define MAX_USER_BUCKETS MAX_PEER_BUCKETS |
Definition at line 736 of file chan_iax2.c.
Referenced by load_module(), and load_objects().
| #define MEMORY_SIZE 100 |
Definition at line 116 of file chan_iax2.c.
| #define MIN_JITTER_BUFFER 10 |
Definition at line 484 of file chan_iax2.c.
| #define MIN_RETRY_TIME 100 |
Definition at line 480 of file chan_iax2.c.
Referenced by iax2_send().
| #define MIN_REUSE_TIME 60 |
Definition at line 121 of file chan_iax2.c.
Referenced by make_trunk(), and sched_delay_remove().
| #define PTR_TO_CALLNO | ( | a | ) | ((unsigned short)(unsigned long)(a)) |
Definition at line 110 of file chan_iax2.c.
Referenced by __auto_congest(), __get_from_jb(), acf_channel_read(), acf_channel_write(), function_iaxpeer(), iax2_answer(), iax2_bridge(), iax2_call(), iax2_digit_begin(), iax2_digit_end(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_prov_app(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), iax2_transfer(), iax2_write(), and scheduled_destroy().
| #define SCHED_MULTITHREADED |
Definition at line 99 of file chan_iax2.c.
| #define schedule_action | ( | func, | |||
| data | ) | __schedule_action(func, data, __PRETTY_FUNCTION__) |
Definition at line 1260 of file chan_iax2.c.
Referenced by attempt_transmit(), auth_reject(), auto_congest(), auto_hangup(), expire_registry(), get_from_jb(), iax2_do_register_s(), iax2_poke_noanswer(), iax2_poke_peer_s(), send_lagrq(), and send_ping().
| #define TRUNK_CALL_START ARRAY_LEN(iaxs) / 2 |
Definition at line 945 of file chan_iax2.c.
Referenced by __find_callno(), create_callno_pools(), make_trunk(), replace_callno(), update_max_nontrunk(), and update_max_trunk().
| #define TS_GAP_FOR_JB_RESYNC 5000 |
Definition at line 491 of file chan_iax2.c.
| anonymous enum |
Definition at line 792 of file chan_iax2.c.
00792 { 00793 /*! Extension exists */ 00794 CACHE_FLAG_EXISTS = (1 << 0), 00795 /*! Extension is nonexistent */ 00796 CACHE_FLAG_NONEXISTENT = (1 << 1), 00797 /*! Extension can exist */ 00798 CACHE_FLAG_CANEXIST = (1 << 2), 00799 /*! Waiting to hear back response */ 00800 CACHE_FLAG_PENDING = (1 << 3), 00801 /*! Timed out */ 00802 CACHE_FLAG_TIMEOUT = (1 << 4), 00803 /*! Request transmitted */ 00804 CACHE_FLAG_TRANSMITTED = (1 << 5), 00805 /*! Timeout */ 00806 CACHE_FLAG_UNKNOWN = (1 << 6), 00807 /*! Matchmore */ 00808 CACHE_FLAG_MATCHMORE = (1 << 7), 00809 };
| anonymous enum |
Definition at line 1663 of file chan_iax2.c.
01663 { 01664 /* do not allow a new call number, only search ones in use for match */ 01665 NEW_PREVENT = 0, 01666 /* search for match first, then allow a new one to be allocated */ 01667 NEW_ALLOW = 1, 01668 /* do not search for match, force a new call number */ 01669 NEW_FORCE = 2, 01670 /* do not search for match, force a new call number. Signifies call number 01671 * has been calltoken validated */ 01672 NEW_ALLOW_CALLTOKEN_VALIDATED = 3, 01673 };
| enum calltoken_peer_enum |
Call token validation settings.
Definition at line 308 of file chan_iax2.c.
00308 { 00309 /*! \brief Default calltoken required unless the ip is in the ignorelist */ 00310 CALLTOKEN_DEFAULT = 0, 00311 /*! \brief Require call token validation. */ 00312 CALLTOKEN_YES = 1, 00313 /*! \brief Require call token validation after a successful registration 00314 * using call token validation occurs. */ 00315 CALLTOKEN_AUTO = 2, 00316 /*! \brief Do not require call token validation. */ 00317 CALLTOKEN_NO = 3, 00318 };
| enum iax2_flags |
Definition at line 269 of file chan_iax2.c.
00269 { 00270 IAX_HASCALLERID = (1 << 0), /*!< CallerID has been specified */ 00271 IAX_DELME = (1 << 1), /*!< Needs to be deleted */ 00272 IAX_TEMPONLY = (1 << 2), /*!< Temporary (realtime) */ 00273 IAX_TRUNK = (1 << 3), /*!< Treat as a trunk */ 00274 IAX_NOTRANSFER = (1 << 4), /*!< Don't native bridge */ 00275 IAX_USEJITTERBUF = (1 << 5), /*!< Use jitter buffer */ 00276 IAX_DYNAMIC = (1 << 6), /*!< dynamic peer */ 00277 IAX_SENDANI = (1 << 7), /*!< Send ANI along with CallerID */ 00278 /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */ 00279 IAX_ALREADYGONE = (1 << 9), /*!< Already disconnected */ 00280 IAX_PROVISION = (1 << 10), /*!< This is a provisioning request */ 00281 IAX_QUELCH = (1 << 11), /*!< Whether or not we quelch audio */ 00282 IAX_ENCRYPTED = (1 << 12), /*!< Whether we should assume encrypted tx/rx */ 00283 IAX_KEYPOPULATED = (1 << 13), /*!< Whether we have a key populated */ 00284 IAX_CODEC_USER_FIRST = (1 << 14), /*!< are we willing to let the other guy choose the codec? */ 00285 IAX_CODEC_NOPREFS = (1 << 15), /*!< Force old behaviour by turning off prefs */ 00286 IAX_CODEC_NOCAP = (1 << 16), /*!< only consider requested format and ignore capabilities*/ 00287 IAX_RTCACHEFRIENDS = (1 << 17), /*!< let realtime stay till your reload */ 00288 IAX_RTUPDATE = (1 << 18), /*!< Send a realtime update */ 00289 IAX_RTAUTOCLEAR = (1 << 19), /*!< erase me on expire */ 00290 IAX_FORCEJITTERBUF = (1 << 20), /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */ 00291 IAX_RTIGNOREREGEXPIRE = (1 << 21), /*!< When using realtime, ignore registration expiration */ 00292 IAX_TRUNKTIMESTAMPS = (1 << 22), /*!< Send trunk timestamps */ 00293 IAX_TRANSFERMEDIA = (1 << 23), /*!< When doing IAX2 transfers, transfer media only */ 00294 IAX_MAXAUTHREQ = (1 << 24), /*!< Maximum outstanding AUTHREQ restriction is in place */ 00295 IAX_DELAYPBXSTART = (1 << 25), /*!< Don't start a PBX on the channel until the peer sends us a 00296 response, so that we've achieved a three-way handshake with 00297 them before sending voice or anything else*/ 00298 IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */ 00299 };
| enum iax2_state |
Definition at line 258 of file chan_iax2.c.
00258 { 00259 IAX_STATE_STARTED = (1 << 0), 00260 IAX_STATE_AUTHENTICATED = (1 << 1), 00261 IAX_STATE_TBD = (1 << 2), 00262 };
| enum iax2_thread_iostate |
Definition at line 832 of file chan_iax2.c.
00832 { 00833 IAX_IOSTATE_IDLE, 00834 IAX_IOSTATE_READY, 00835 IAX_IOSTATE_PROCESSING, 00836 IAX_IOSTATE_SCHEDREADY, 00837 };
| enum iax2_thread_type |
Definition at line 839 of file chan_iax2.c.
00839 { 00840 IAX_THREAD_TYPE_POOL, 00841 IAX_THREAD_TYPE_DYNAMIC, 00842 };
| enum iax_reg_state |
| REG_STATE_UNREGISTERED | |
| REG_STATE_REGSENT | |
| REG_STATE_AUTHSENT | |
| REG_STATE_REGISTERED | |
| REG_STATE_REJECTED | |
| REG_STATE_TIMEOUT | |
| REG_STATE_NOAUTH |
Definition at line 439 of file chan_iax2.c.
00439 { 00440 REG_STATE_UNREGISTERED = 0, 00441 REG_STATE_REGSENT, 00442 REG_STATE_AUTHSENT, 00443 REG_STATE_REGISTERED, 00444 REG_STATE_REJECTED, 00445 REG_STATE_TIMEOUT, 00446 REG_STATE_NOAUTH 00447 };
| enum iax_transfer_state |
| TRANSFER_NONE | |
| TRANSFER_BEGIN | |
| TRANSFER_READY | |
| TRANSFER_RELEASED | |
| TRANSFER_PASSTHROUGH | |
| TRANSFER_MBEGIN | |
| TRANSFER_MREADY | |
| TRANSFER_MRELEASED | |
| TRANSFER_MPASSTHROUGH | |
| TRANSFER_MEDIA | |
| TRANSFER_MEDIAPASS |
Definition at line 449 of file chan_iax2.c.
00449 { 00450 TRANSFER_NONE = 0, 00451 TRANSFER_BEGIN, 00452 TRANSFER_READY, 00453 TRANSFER_RELEASED, 00454 TRANSFER_PASSTHROUGH, 00455 TRANSFER_MBEGIN, 00456 TRANSFER_MREADY, 00457 TRANSFER_MRELEASED, 00458 TRANSFER_MPASSTHROUGH, 00459 TRANSFER_MEDIA, 00460 TRANSFER_MEDIAPASS 00461 };
| static void __attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 3144 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, chan_iax2_pvt::error, f, iax_frame::final, ast_frame::frametype, ast_channel::hangupcause, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), iax2_sched_add(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, LOG_WARNING, MAX_RETRY_TIME, iax_frame::oseqno, chan_iax2_pvt::owner, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_TIMEOUT, iax2_registry::regstate, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_command(), send_packet(), ast_frame::subclass, iax_frame::transfer, iax_frame::ts, update_packet(), and iax2_registry::us.
Referenced by attempt_transmit().
03145 { 03146 /* Attempt to transmit the frame to the remote peer... 03147 Called without iaxsl held. */ 03148 struct iax_frame *f = (struct iax_frame *)data; 03149 int freeme = 0; 03150 int callno = f->callno; 03151 /* Make sure this call is still active */ 03152 if (callno) 03153 ast_mutex_lock(&iaxsl[callno]); 03154 if (callno && iaxs[callno]) { 03155 if ((f->retries < 0) /* Already ACK'd */ || 03156 (f->retries >= max_retries) /* Too many attempts */) { 03157 /* Record an error if we've transmitted too many times */ 03158 if (f->retries >= max_retries) { 03159 if (f->transfer) { 03160 /* Transfer timeout */ 03161 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 03162 } else if (f->final) { 03163 if (f->final) 03164 iax2_destroy(callno); 03165 } else { 03166 if (iaxs[callno]->owner) 03167 ast_log(LOG_WARNING, "Max retries exceeded to host %s on %s (type = %d, subclass = %d, ts=%d, seqno=%d)\n", ast_inet_ntoa(iaxs[f->callno]->addr.sin_addr),iaxs[f->callno]->owner->name , f->af.frametype, f->af.subclass, f->ts, f->oseqno); 03168 iaxs[callno]->error = ETIMEDOUT; 03169 if (iaxs[callno]->owner) { 03170 struct ast_frame fr = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP, .data.uint32 = AST_CAUSE_DESTINATION_OUT_OF_ORDER }; 03171 /* Hangup the fd */ 03172 iax2_queue_frame(callno, &fr); /* XXX */ 03173 /* Remember, owner could disappear */ 03174 if (iaxs[callno] && iaxs[callno]->owner) 03175 iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 03176 } else { 03177 if (iaxs[callno]->reg) { 03178 memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us)); 03179 iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT; 03180 iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE; 03181 } 03182 iax2_destroy(callno); 03183 } 03184 } 03185 03186 } 03187 freeme = 1; 03188 } else { 03189 /* Update it if it needs it */ 03190 update_packet(f); 03191 /* Attempt transmission */ 03192 send_packet(f); 03193 f->retries++; 03194 /* Try again later after 10 times as long */ 03195 f->retrytime *= 10; 03196 if (f->retrytime > MAX_RETRY_TIME) 03197 f->retrytime = MAX_RETRY_TIME; 03198 /* Transfer messages max out at one second */ 03199 if (f->transfer && (f->retrytime > 1000)) 03200 f->retrytime = 1000; 03201 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 03202 } 03203 } else { 03204 /* Make sure it gets freed */ 03205 f->retries = -1; 03206 freeme = 1; 03207 } 03208 if (callno) 03209 ast_mutex_unlock(&iaxsl[callno]); 03210 /* Do not try again */ 03211 if (freeme) { 03212 /* Don't attempt delivery, just remove it from the queue */ 03213 AST_LIST_LOCK(&frame_queue); 03214 AST_LIST_REMOVE(&frame_queue, f, list); 03215 AST_LIST_UNLOCK(&frame_queue); 03216 f->retrans = -1; 03217 /* Free the IAX frame */ 03218 iax2_frame_free(f); 03219 } 03220 }
| static void __auth_reject | ( | const void * | nothing | ) | [static] |
Definition at line 8351 of file chan_iax2.c.
References AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_FACILITY_REJECTED, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax_ie_data::buf, IAX_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iax_ie_data::pos, and send_command_final().
Referenced by auth_reject().
08352 { 08353 /* Called from IAX thread only, without iaxs lock */ 08354 int callno = (int)(long)(nothing); 08355 struct iax_ie_data ied; 08356 ast_mutex_lock(&iaxsl[callno]); 08357 if (iaxs[callno]) { 08358 memset(&ied, 0, sizeof(ied)); 08359 if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) { 08360 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused"); 08361 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED); 08362 } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) { 08363 iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found"); 08364 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 08365 } 08366 send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1); 08367 } 08368 ast_mutex_unlock(&iaxsl[callno]); 08369 }
| static void __auto_congest | ( | const void * | nothing | ) | [static] |
Definition at line 4253 of file chan_iax2.c.
References AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_queue_frame(), chan_iax2_pvt::initid, LOG_NOTICE, and PTR_TO_CALLNO.
Referenced by auto_congest().
04254 { 04255 int callno = PTR_TO_CALLNO(nothing); 04256 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION }; 04257 ast_mutex_lock(&iaxsl[callno]); 04258 if (iaxs[callno]) { 04259 iaxs[callno]->initid = -1; 04260 iax2_queue_frame(callno, &f); 04261 ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n"); 04262 } 04263 ast_mutex_unlock(&iaxsl[callno]); 04264 }
| static void __auto_hangup | ( | const void * | nothing | ) | [static] |
Definition at line 8400 of file chan_iax2.c.
References AST_CAUSE_NO_USER_RESPONSE, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax_ie_data::buf, IAX_COMMAND_HANGUP, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iax_ie_data::pos, and send_command_final().
Referenced by auto_hangup().
08401 { 08402 /* Called from IAX thread only, without iaxs lock */ 08403 int callno = (int)(long)(nothing); 08404 struct iax_ie_data ied; 08405 ast_mutex_lock(&iaxsl[callno]); 08406 if (iaxs[callno]) { 08407 memset(&ied, 0, sizeof(ied)); 08408 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout"); 08409 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE); 08410 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 08411 } 08412 ast_mutex_unlock(&iaxsl[callno]); 08413 }
| static int __do_deliver | ( | void * | data | ) | [static] |
Definition at line 2939 of file chan_iax2.c.
References iax_frame::af, ast_clear_flag, AST_FRFLAG_HAS_TIMING_INFO, ast_test_flag, iax_frame::callno, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, and iax_frame::retrans.
Referenced by __get_from_jb(), and schedule_delivery().
02940 { 02941 /* Just deliver the packet by using queueing. This is called by 02942 the IAX thread with the iaxsl lock held. */ 02943 struct iax_frame *fr = data; 02944 fr->retrans = -1; 02945 ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO); 02946 if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE)) 02947 iax2_queue_frame(fr->callno, &fr->af); 02948 /* Free our iax frame */ 02949 iax2_frame_free(fr); 02950 /* And don't run again */ 02951 return 0; 02952 }
| static void __expire_registry | ( | const void * | data | ) | [static] |
Definition at line 7999 of file chan_iax2.c.
References iax2_peer::addr, ast_db_del(), ast_debug, AST_DEVICE_UNAVAILABLE, ast_devstate_changed(), ast_test_flag, EVENT_FLAG_SYSTEM, iax2_peer::expire, iax2_peer::expiry, iax2_regfunk, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, manager_event, iax2_peer::name, peer_unref(), peercnt_modify(), realtime_update_peer(), register_peer_exten(), and unlink_peer().
Referenced by expire_registry().
08000 { 08001 struct iax2_peer *peer = (struct iax2_peer *) data; 08002 08003 if (!peer) 08004 return; 08005 08006 peer->expire = -1; 08007 08008 ast_debug(1, "Expiring registration for peer '%s'\n", peer->name); 08009 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) 08010 realtime_update_peer(peer->name, &peer->addr, 0); 08011 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 08012 /* modify entry in peercnts table as _not_ registered */ 08013 peercnt_modify(0, 0, &peer->addr); 08014 /* Reset the address */ 08015 memset(&peer->addr, 0, sizeof(peer->addr)); 08016 /* Reset expiry value */ 08017 peer->expiry = min_reg_expire; 08018 if (!ast_test_flag(peer, IAX_TEMPONLY)) 08019 ast_db_del("IAX/Registry", peer->name); 08020 register_peer_exten(peer, 0); 08021 ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", peer->name); /* Activate notification */ 08022 if (iax2_regfunk) 08023 iax2_regfunk(peer->name, 0); 08024 08025 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) 08026 unlink_peer(peer); 08027 08028 peer_unref(peer); 08029 }
| static int __find_callno | ( | unsigned short | callno, | |
| unsigned short | dcallno, | |||
| struct sockaddr_in * | sin, | |||
| int | new, | |||
| int | sockfd, | |||
| int | return_locked, | |||
| int | check_dcallno | |||
| ) | [static] |
Definition at line 2416 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::amaflags, ao2_find, ao2_ref, ast_copy_flags, ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_set, callno_entry::callno, chan_iax2_pvt::callno, chan_iax2_pvt::callno_entry, DEFAULT_RETRY_TIME, chan_iax2_pvt::expiry, get_unused_callno(), iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, chan_iax2_pvt::lagid, LOG_WARNING, match(), NEW_ALLOW, new_iax(), OBJ_POINTER, parkinglot, chan_iax2_pvt::peercallno, peercnt_add(), peercnt_remove_by_addr(), chan_iax2_pvt::pingid, chan_iax2_pvt::pingtime, replace_callno(), send_lagrq(), send_ping(), chan_iax2_pvt::sockfd, store_by_peercallno(), chan_iax2_pvt::transfer, TRUNK_CALL_START, and update_max_nontrunk().
Referenced by find_callno(), and find_callno_locked().
02417 { 02418 int res = 0; 02419 int x; 02420 /* this call is calltoken validated as long as it is either NEW_FORCE 02421 * or NEW_ALLOW_CALLTOKEN_VALIDATED */ 02422 int validated = (new > NEW_ALLOW) ? 1 : 0; 02423 char host[80]; 02424 02425 if (new <= NEW_ALLOW) { 02426 if (callno) { 02427 struct chan_iax2_pvt *pvt; 02428 struct chan_iax2_pvt tmp_pvt = { 02429 .callno = dcallno, 02430 .peercallno = callno, 02431 .transfercallno = callno, 02432 /* hack!! */ 02433 .frames_received = check_dcallno, 02434 }; 02435 02436 memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr)); 02437 /* this works for finding normal call numbers not involving transfering */ 02438 if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) { 02439 if (return_locked) { 02440 ast_mutex_lock(&iaxsl[pvt->callno]); 02441 } 02442 res = pvt->callno; 02443 ao2_ref(pvt, -1); 02444 pvt = NULL; 02445 return res; 02446 } 02447 /* this searches for transfer call numbers that might not get caught otherwise */ 02448 memset(&tmp_pvt.addr, 0, sizeof(tmp_pvt.addr)); 02449 memcpy(&tmp_pvt.transfer, sin, sizeof(tmp_pvt.addr)); 02450 if ((pvt = ao2_find(iax_transfercallno_pvts, &tmp_pvt, OBJ_POINTER))) { 02451 if (return_locked) { 02452 ast_mutex_lock(&iaxsl[pvt->callno]); 02453 } 02454 res = pvt->callno; 02455 ao2_ref(pvt, -1); 02456 pvt = NULL; 02457 return res; 02458 } 02459 } 02460 /* This will occur on the first response to a message that we initiated, 02461 * such as a PING. */ 02462 if (dcallno) { 02463 ast_mutex_lock(&iaxsl[dcallno]); 02464 } 02465 if (callno && dcallno && iaxs[dcallno] && !iaxs[dcallno]->peercallno && match(sin, callno, dcallno, iaxs[dcallno], check_dcallno)) { 02466 iaxs[dcallno]->peercallno = callno; 02467 res = dcallno; 02468 store_by_peercallno(iaxs[dcallno]); 02469 if (!res || !return_locked) { 02470 ast_mutex_unlock(&iaxsl[dcallno]); 02471 } 02472 return res; 02473 } 02474 if (dcallno) { 02475 ast_mutex_unlock(&iaxsl[dcallno]); 02476 } 02477 #ifdef IAX_OLD_FIND 02478 /* If we get here, we SHOULD NOT find a call structure for this 02479 callno; if we do, it means that there is a call structure that 02480 has a peer callno but did NOT get entered into the hash table, 02481 which is bad. 02482 02483 If we find a call structure using this old, slow method, output a log 02484 message so we'll know about it. After a few months of leaving this in 02485 place, if we don't hear about people seeing these messages, we can 02486 remove this code for good. 02487 */ 02488 02489 for (x = 1; !res && x < maxnontrunkcall; x++) { 02490 ast_mutex_lock(&iaxsl[x]); 02491 if (iaxs[x]) { 02492 /* Look for an exact match */ 02493 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 02494 res = x; 02495 } 02496 } 02497 if (!res || !return_locked) 02498 ast_mutex_unlock(&iaxsl[x]); 02499 } 02500 for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) { 02501 ast_mutex_lock(&iaxsl[x]); 02502 if (iaxs[x]) { 02503 /* Look for an exact match */ 02504 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 02505 res = x; 02506 } 02507 } 02508 if (!res || !return_locked) 02509 ast_mutex_unlock(&iaxsl[x]); 02510 } 02511 #endif 02512 } 02513 if (!res && (new >= NEW_ALLOW)) { 02514 struct callno_entry *callno_entry; 02515 /* It may seem odd that we look through the peer list for a name for 02516 * this *incoming* call. Well, it is weird. However, users don't 02517 * have an IP address/port number that we can match against. So, 02518 * this is just checking for a peer that has that IP/port and 02519 * assuming that we have a user of the same name. This isn't always 02520 * correct, but it will be changed if needed after authentication. */ 02521 if (!iax2_getpeername(*sin, host, sizeof(host))) 02522 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 02523 02524 if (peercnt_add(sin)) { 02525 /* This address has hit its callnumber limit. When the limit 02526 * is reached, the connection is not added to the peercnts table.*/ 02527 return 0; 02528 } 02529 02530 if (!(callno_entry = get_unused_callno(0, validated))) { 02531 /* since we ran out of space, remove the peercnt 02532 * entry we added earlier */ 02533 peercnt_remove_by_addr(sin); 02534 ast_log(LOG_WARNING, "No more space\n"); 02535 return 0; 02536 } 02537 x = callno_entry->callno; 02538 ast_mutex_lock(&iaxsl[x]); 02539 02540 iaxs[x] = new_iax(sin, host); 02541 update_max_nontrunk(); 02542 if (iaxs[x]) { 02543 if (iaxdebug) 02544 ast_debug(1, "Creating new call structure %d\n", x); 02545 iaxs[x]->callno_entry = callno_entry; 02546 iaxs[x]->sockfd = sockfd; 02547 iaxs[x]->addr.sin_port = sin->sin_port; 02548 iaxs[x]->addr.sin_family = sin->sin_family; 02549 iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr; 02550 iaxs[x]->peercallno = callno; 02551 iaxs[x]->callno = x; 02552 iaxs[x]->pingtime = DEFAULT_RETRY_TIME; 02553 iaxs[x]->expiry = min_reg_expire; 02554 iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 02555 iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 02556 iaxs[x]->amaflags = amaflags; 02557 ast_copy_flags(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 02558 02559 ast_string_field_set(iaxs[x], accountcode, accountcode); 02560 ast_string_field_set(iaxs[x], mohinterpret, mohinterpret); 02561 ast_string_field_set(iaxs[x], mohsuggest, mohsuggest); 02562 ast_string_field_set(iaxs[x], parkinglot, default_parkinglot); 02563 02564 if (iaxs[x]->peercallno) { 02565 store_by_peercallno(iaxs[x]); 02566 } 02567 } else { 02568 ast_log(LOG_WARNING, "Out of resources\n"); 02569 ast_mutex_unlock(&iaxsl[x]); 02570 replace_callno(callno_entry); 02571 return 0; 02572 } 02573 if (!return_locked) 02574 ast_mutex_unlock(&iaxsl[x]); 02575 res = x; 02576 } 02577 return res; 02578 }
| static void __get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 3706 of file chan_iax2.c.
References __do_deliver(), ast_codec_interp_len(), ast_format_rate(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_test_flag, ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, chan_iax2_pvt::jb, JB_DROP, JB_EMPTY, jb_get(), JB_INTERP, jb_next(), JB_NOFRAME, JB_OK, chan_iax2_pvt::jbid, jb_frame::ms, iax2_trunk_peer::next, ast_frame::offset, PTR_TO_CALLNO, chan_iax2_pvt::rxcore, ast_frame::samples, ast_frame::src, ast_frame::subclass, update_jbsched(), and chan_iax2_pvt::voiceformat.
Referenced by get_from_jb().
03707 { 03708 int callno = PTR_TO_CALLNO(p); 03709 struct chan_iax2_pvt *pvt = NULL; 03710 struct iax_frame *fr; 03711 jb_frame frame; 03712 int ret; 03713 long ms; 03714 long next; 03715 struct timeval now = ast_tvnow(); 03716 03717 /* Make sure we have a valid private structure before going on */ 03718 ast_mutex_lock(&iaxsl[callno]); 03719 pvt = iaxs[callno]; 03720 if (!pvt) { 03721 /* No go! */ 03722 ast_mutex_unlock(&iaxsl[callno]); 03723 return; 03724 } 03725 03726 pvt->jbid = -1; 03727 03728 /* round up a millisecond since ast_sched_runq does; */ 03729 /* prevents us from spinning while waiting for our now */ 03730 /* to catch up with runq's now */ 03731 now.tv_usec += 1000; 03732 03733 ms = ast_tvdiff_ms(now, pvt->rxcore); 03734 03735 if(ms >= (next = jb_next(pvt->jb))) { 03736 ret = jb_get(pvt->jb,&frame,ms,ast_codec_interp_len(pvt->voiceformat)); 03737 switch(ret) { 03738 case JB_OK: 03739 fr = frame.data; 03740 __do_deliver(fr); 03741 /* __do_deliver() can cause the call to disappear */ 03742 pvt = iaxs[callno]; 03743 break; 03744 case JB_INTERP: 03745 { 03746 struct ast_frame af = { 0, }; 03747 03748 /* create an interpolation frame */ 03749 af.frametype = AST_FRAME_VOICE; 03750 af.subclass = pvt->voiceformat; 03751 af.samples = frame.ms * (ast_format_rate(pvt->voiceformat) / 1000); 03752 af.src = "IAX2 JB interpolation"; 03753 af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000)); 03754 af.offset = AST_FRIENDLY_OFFSET; 03755 03756 /* queue the frame: For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame, 03757 * which we'd need to malloc, and then it would free it. That seems like a drag */ 03758 if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) { 03759 iax2_queue_frame(callno, &af); 03760 /* iax2_queue_frame() could cause the call to disappear */ 03761 pvt = iaxs[callno]; 03762 } 03763 } 03764 break; 03765 case JB_DROP: 03766 iax2_frame_free(frame.data); 03767 break; 03768 case JB_NOFRAME: 03769 case JB_EMPTY: 03770 /* do nothing */ 03771 break; 03772 default: 03773 /* shouldn't happen */ 03774 break; 03775 } 03776 } 03777 if (pvt) 03778 update_jbsched(pvt); 03779 ast_mutex_unlock(&iaxsl[callno]); 03780 }
| static void __iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 7678 of file chan_iax2.c.
References iax2_registry::expire, and iax2_do_register().
Referenced by iax2_do_register_s().
07679 { 07680 struct iax2_registry *reg = (struct iax2_registry *)data; 07681 reg->expire = -1; 07682 iax2_do_register(reg); 07683 }
| static void __iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 11160 of file chan_iax2.c.
References AST_DEVICE_UNAVAILABLE, ast_devstate_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_peer::callno, EVENT_FLAG_SYSTEM, iax2_destroy(), iax2_poke_peer_s(), iax2_sched_add(), iax2_peer::lastms, LOG_NOTICE, manager_event, iax2_peer::name, peer_ref(), peer_unref(), iax2_peer::pokeexpire, and iax2_peer::pokefreqnotok.
Referenced by iax2_poke_noanswer().
11161 { 11162 struct iax2_peer *peer = (struct iax2_peer *)data; 11163 int callno; 11164 11165 if (peer->lastms > -1) { 11166 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms); 11167 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms); 11168 ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", peer->name); /* Activate notification */ 11169 } 11170 if ((callno = peer->callno) > 0) { 11171 ast_mutex_lock(&iaxsl[callno]); 11172 iax2_destroy(callno); 11173 ast_mutex_unlock(&iaxsl[callno]); 11174 } 11175 peer->callno = 0; 11176 peer->lastms = -1; 11177 /* Try again quickly */ 11178 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 11179 if (peer->pokeexpire == -1) 11180 peer_unref(peer); 11181 }
| static void __iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 8463 of file chan_iax2.c.
References iax2_poke_peer(), and peer_unref().
Referenced by iax2_poke_peer_s().
08464 { 08465 struct iax2_peer *peer = (struct iax2_peer *)data; 08466 iax2_poke_peer(peer, 0); 08467 peer_unref(peer); 08468 }
| static int __iax2_show_peers | ( | int | manager, | |
| int | fd, | |||
| struct mansession * | s, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 6145 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next, ast_cli(), ast_copy_string(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), iax2_peer::encmethods, FORMAT, FORMAT2, IAX_DYNAMIC, IAX_TRUNK, iax2_peer::mask, iax2_peer::name, name, peer_status(), peer_unref(), RESULT_SHOWUSAGE, RESULT_SUCCESS, status, and iax2_peer::username.
Referenced by handle_cli_iax2_show_peers(), and manager_iax2_show_peers().
06146 { 06147 regex_t regexbuf; 06148 int havepattern = 0; 06149 int total_peers = 0; 06150 int online_peers = 0; 06151 int offline_peers = 0; 06152 int unmonitored_peers = 0; 06153 struct ao2_iterator i; 06154 06155 #define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" 06156 #define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" 06157 06158 struct iax2_peer *peer = NULL; 06159 char name[256]; 06160 int registeredonly=0; 06161 char *term = manager ? "\r\n" : "\n"; 06162 char idtext[256] = ""; 06163 switch (argc) { 06164 case 6: 06165 if (!strcasecmp(argv[3], "registered")) 06166 registeredonly = 1; 06167 else 06168 return RESULT_SHOWUSAGE; 06169 if (!strcasecmp(argv[4], "like")) { 06170 if (regcomp(®exbuf, argv[5], REG_EXTENDED | REG_NOSUB)) 06171 return RESULT_SHOWUSAGE; 06172 havepattern = 1; 06173 } else 06174 return RESULT_SHOWUSAGE; 06175 break; 06176 case 5: 06177 if (!strcasecmp(argv[3], "like")) { 06178 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 06179 return RESULT_SHOWUSAGE; 06180 havepattern = 1; 06181 } else 06182 return RESULT_SHOWUSAGE; 06183 break; 06184 case 4: 06185 if (!strcasecmp(argv[3], "registered")) 06186 registeredonly = 1; 06187 else 06188 return RESULT_SHOWUSAGE; 06189 break; 06190 case 3: 06191 break; 06192 default: 06193 return RESULT_SHOWUSAGE; 06194 } 06195 06196 06197 if (!s) 06198 ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 06199 06200 i = ao2_iterator_init(peers, 0); 06201 for (peer = ao2_iterator_next(&i); peer; 06202 peer_unref(peer), peer = ao2_iterator_next(&i)) { 06203 char nm[20]; 06204 char status[20]; 06205 char srch[2000]; 06206 int retstatus; 06207 06208 if (registeredonly && !peer->addr.sin_addr.s_addr) 06209 continue; 06210 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) 06211 continue; 06212 06213 if (!ast_strlen_zero(peer->username)) 06214 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 06215 else 06216 ast_copy_string(name, peer->name, sizeof(name)); 06217 06218 retstatus = peer_status(peer, status, sizeof(status)); 06219 if (retstatus > 0) 06220 online_peers++; 06221 else if (!retstatus) 06222 offline_peers++; 06223 else 06224 unmonitored_peers++; 06225 06226 ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); 06227 06228 snprintf(srch, sizeof(srch), FORMAT, name, 06229 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 06230 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 06231 nm, 06232 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 06233 peer->encmethods ? "(E)" : " ", status, term); 06234 06235 if (s) 06236 astman_append(s, 06237 "Event: PeerEntry\r\n%s" 06238 "Channeltype: IAX2\r\n" 06239 "ChanObjectType: peer\r\n" 06240 "ObjectName: %s\r\n" 06241 "IPaddress: %s\r\n" 06242 "IPport: %d\r\n" 06243 "Dynamic: %s\r\n" 06244 "Status: %s\r\n\r\n", 06245 idtext, 06246 name, 06247 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-", 06248 ntohs(peer->addr.sin_port), 06249 ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no", 06250 status); 06251 06252 else 06253 ast_cli(fd, FORMAT, name, 06254 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 06255 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 06256 nm, 06257 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 06258 peer->encmethods ? "(E)" : " ", status, term); 06259 total_peers++; 06260 } 06261 06262 if (!s) 06263 ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 06264 06265 if (havepattern) 06266 regfree(®exbuf); 06267 06268 return RESULT_SUCCESS; 06269 #undef FORMAT 06270 #undef FORMAT2 06271 }
| static void __reg_module | ( | void | ) | [static] |
Definition at line 13655 of file chan_iax2.c.
| static int __schedule_action | ( | void(*)(const void *data) | func, | |
| const void * | data, | |||
| const char * | funcname | |||
| ) | [static] |
Definition at line 1235 of file chan_iax2.c.
References ast_copy_string(), ast_debug, iax2_thread::cond, iax2_thread::curfunc, find_idle_thread(), IAX_IOSTATE_SCHEDREADY, iax2_thread::iostate, iax2_thread::lock, iax2_thread::scheddata, iax2_thread::schedfunc, signal_condition(), and thread.
01236 { 01237 struct iax2_thread *thread = NULL; 01238 static time_t lasterror; 01239 static time_t t; 01240 01241 thread = find_idle_thread(); 01242 01243 if (thread != NULL) { 01244 thread->schedfunc = func; 01245 thread->scheddata = data; 01246 thread->iostate = IAX_IOSTATE_SCHEDREADY; 01247 #ifdef DEBUG_SCHED_MULTITHREAD 01248 ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc)); 01249 #endif 01250 signal_condition(&thread->lock, &thread->cond); 01251 return 0; 01252 } 01253 time(&t); 01254 if (t != lasterror) 01255 ast_debug(1, "Out of idle IAX2 threads for scheduling!\n"); 01256 lasterror = t; 01257 01258 return -1; 01259 }
| static int __send_command | ( | struct chan_iax2_pvt * | i, | |
| char | type, | |||
| int | command, | |||
| unsigned int | ts, | |||
| const unsigned char * | data, | |||
| int | datalen, | |||
| int | seqno, | |||
| int | now, | |||
| int | transfer, | |||
| int | final | |||
| ) | [static] |
Definition at line 6893 of file chan_iax2.c.
References ast_frame::data, ast_frame::datalen, ast_frame::frametype, iax2_send(), ast_frame::ptr, ast_frame::src, and ast_frame::subclass.
Referenced by send_command(), send_command_final(), send_command_immediate(), and send_command_transfer().
| static void __send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1328 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax2_thread::callno, iax2_sched_add(), IAX_COMMAND_LAGRQ, chan_iax2_pvt::lagid, send_command(), and send_lagrq().
Referenced by send_lagrq().
01329 { 01330 int callno = (long) data; 01331 01332 ast_mutex_lock(&iaxsl[callno]); 01333 01334 if (iaxs[callno]) { 01335 if (iaxs[callno]->peercallno) { 01336 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1); 01337 iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data); 01338 } else { 01339 /* I am the schedule, so I'm allowed to do this */ 01340 iaxs[callno]->lagid = -1; 01341 } 01342 } else { 01343 ast_debug(1, "I was supposed to send a LAGRQ with callno %d, but no such call exists.\n", callno); 01344 } 01345 01346 ast_mutex_unlock(&iaxsl[callno]); 01347 }
| static void __send_ping | ( | const void * | data | ) | [static] |
Definition at line 1283 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax2_thread::callno, iax2_sched_add(), IAX_COMMAND_PING, chan_iax2_pvt::pingid, send_command(), and send_ping().
Referenced by send_ping().
01284 { 01285 int callno = (long) data; 01286 01287 ast_mutex_lock(&iaxsl[callno]); 01288 01289 if (iaxs[callno]) { 01290 if (iaxs[callno]->peercallno) { 01291 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1); 01292 iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data); 01293 } else { 01294 /* I am the schedule, so I'm allowed to do this */ 01295 iaxs[callno]->pingid = -1; 01296 } 01297 } else { 01298 ast_debug(1, "I was supposed to send a PING with callno %d, but no such call exists.\n", callno); 01299 } 01300 01301 ast_mutex_unlock(&iaxsl[callno]); 01302 }
| static int __unload_module | ( | void | ) | [static] |
Definition at line 13342 of file chan_iax2.c.
References ao2_ref, ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_signal(), ast_context_destroy(), ast_context_find(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_release(), AST_PTHREADT_NULL, ast_timer_close(), ast_unload_realtime(), ast_unregister_application(), ast_unregister_switch(), callno_limits, calltoken_ignores, delete_users(), iax2_destroy(), iax_provision_unload(), iaxactivethreadcount, peercnts, reload_firmware(), sched_context_destroy(), sched_lock, thread, and iax2_thread::threadid.
Referenced by load_module(), and unload_module().
13343 { 13344 struct iax2_thread *thread = NULL; 13345 struct ast_context *con; 13346 int x; 13347 13348 /* Make sure threads do not hold shared resources when they are canceled */ 13349 13350 /* Grab the sched lock resource to keep it away from threads about to die */ 13351 /* Cancel the network thread, close the net socket */ 13352 if (netthreadid != AST_PTHREADT_NULL) { 13353 AST_LIST_LOCK(&frame_queue); 13354 ast_mutex_lock(&sched_lock); 13355 pthread_cancel(netthreadid); 13356 ast_cond_signal(&sched_cond); 13357 ast_mutex_unlock(&sched_lock); /* Release the schedule lock resource */ 13358 AST_LIST_UNLOCK(&frame_queue); 13359 pthread_join(netthreadid, NULL); 13360 } 13361 if (schedthreadid != AST_PTHREADT_NULL) { 13362 ast_mutex_lock(&sched_lock); 13363 pthread_cancel(schedthreadid); 13364 ast_cond_signal(&sched_cond); 13365 ast_mutex_unlock(&sched_lock); 13366 pthread_join(schedthreadid, NULL); 13367 } 13368 13369 /* Call for all threads to halt */ 13370 AST_LIST_LOCK(&idle_list); 13371 while ((thread = AST_LIST_REMOVE_HEAD(&idle_list, list))) 13372 pthread_cancel(thread->threadid); 13373 AST_LIST_UNLOCK(&idle_list); 13374 13375 AST_LIST_LOCK(&active_list); 13376 while ((thread = AST_LIST_REMOVE_HEAD(&active_list, list))) 13377 pthread_cancel(thread->threadid); 13378 AST_LIST_UNLOCK(&active_list); 13379 13380 AST_LIST_LOCK(&dynamic_list); 13381 while ((thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list))) 13382 pthread_cancel(thread->threadid); 13383 AST_LIST_UNLOCK(&dynamic_list); 13384 13385 /* Wait for threads to exit */ 13386 while(0 < iaxactivethreadcount) 13387 usleep(10000); 13388 13389 ast_netsock_release(netsock); 13390 ast_netsock_release(outsock); 13391 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 13392 if (iaxs[x]) { 13393 iax2_destroy(x); 13394 } 13395 } 13396 ast_manager_unregister( "IAXpeers" ); 13397 ast_manager_unregister( "IAXpeerlist" ); 13398 ast_manager_unregister( "IAXnetstats" ); 13399 ast_unregister_application(papp); 13400 ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 13401 ast_unregister_switch(&iax2_switch); 13402 ast_channel_unregister(&iax2_tech); 13403 delete_users(); 13404 iax_provision_unload(); 13405 sched_context_destroy(sched); 13406 reload_firmware(1); 13407 13408 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 13409 ast_mutex_destroy(&iaxsl[x]); 13410 } 13411 13412 ao2_ref(peers, -1); 13413 ao2_ref(users, -1); 13414 ao2_ref(iax_peercallno_pvts, -1); 13415 ao2_ref(iax_transfercallno_pvts, -1); 13416 ao2_ref(peercnts, -1); 13417 ao2_ref(callno_limits, -1); 13418 ao2_ref(calltoken_ignores, -1); 13419 ao2_ref(callno_pool, -1); 13420 ao2_ref(callno_pool_trunk, -1); 13421 if (timer) { 13422 ast_timer_close(timer); 13423 } 13424 13425 con = ast_context_find(regcontext); 13426 if (con) 13427 ast_context_destroy(con, "IAX2"); 13428 ast_unload_realtime("iaxpeers"); 13429 return 0; 13430 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 13655 of file chan_iax2.c.
| static int acf_channel_read | ( | struct ast_channel * | chan, | |
| const char * | funcname, | |||
| char * | preparse, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 13127 of file chan_iax2.c.
References chan_iax2_pvt::addr, ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::callno, LOG_ERROR, chan_iax2_pvt::osptoken, PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, and chan_iax2_pvt::username.
13128 { 13129 struct chan_iax2_pvt *pvt; 13130 unsigned int callno; 13131 int res = 0; 13132 13133 if (!chan || chan->tech != &iax2_tech) { 13134 ast_log(LOG_ERROR, "This function requires a valid IAX2 channel\n"); 13135 return -1; 13136 } 13137 13138 callno = PTR_TO_CALLNO(chan->tech_pvt); 13139 ast_mutex_lock(&iaxsl[callno]); 13140 if (!(pvt = iaxs[callno])) { 13141 ast_mutex_unlock(&iaxsl[callno]); 13142 return -1; 13143 } 13144 13145 if (!strcasecmp(args, "osptoken")) { 13146 ast_copy_string(buf, pvt->osptoken, buflen); 13147 } else if (!strcasecmp(args, "peerip")) { 13148 ast_copy_string(buf, pvt->addr.sin_addr.s_addr ? ast_inet_ntoa(pvt->addr.sin_addr) : "", buflen); 13149 } else if (!strcasecmp(args, "peername")) { 13150 ast_copy_string(buf, pvt->username, buflen); 13151 } else { 13152 res = -1; 13153 } 13154 13155 ast_mutex_unlock(&iaxsl[callno]); 13156 13157 return res; 13158 }
| static int acf_channel_write | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| const char * | value | |||
| ) | [static] |
Definition at line 13099 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_set, chan_iax2_pvt::callno, LOG_ERROR, chan_iax2_pvt::osptoken, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.
13100 { 13101 struct chan_iax2_pvt *pvt; 13102 unsigned int callno; 13103 int res = 0; 13104 13105 if (!chan || chan->tech != &iax2_tech) { 13106 ast_log(LOG_ERROR, "This function requires a valid IAX2 channel\n"); 13107 return -1; 13108 } 13109 13110 callno = PTR_TO_CALLNO(chan->tech_pvt); 13111 ast_mutex_lock(&iaxsl[callno]); 13112 if (!(pvt = iaxs[callno])) { 13113 ast_mutex_unlock(&iaxsl[callno]); 13114 return -1; 13115 } 13116 13117 if (!strcasecmp(args, "osptoken")) 13118 ast_string_field_set(pvt, osptoken, value); 13119 else 13120 res = -1; 13121 13122 ast_mutex_unlock(&iaxsl[callno]); 13123 13124 return res; 13125 }
| static int acf_iaxvar_read | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 9131 of file chan_iax2.c.
References ast_channel_datastore_find(), ast_copy_string(), AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_datastore::data, ast_var_t::name, ast_var_t::value, and var.
09132 { 09133 struct ast_datastore *variablestore = ast_channel_datastore_find(chan, &iax2_variable_datastore_info, NULL); 09134 AST_LIST_HEAD(, ast_var_t) *varlist; 09135 struct ast_var_t *var; 09136 09137 if (!variablestore) { 09138 *buf = '\0'; 09139 return 0; 09140 } 09141 varlist = variablestore->data; 09142 09143 AST_LIST_LOCK(varlist); 09144 AST_LIST_TRAVERSE(varlist, var, entries) { 09145 if (strcmp(var->name, data) == 0) { 09146 ast_copy_string(buf, var->value, len); 09147 break; 09148 } 09149 } 09150 AST_LIST_UNLOCK(varlist); 09151 return 0; 09152 }
| static int acf_iaxvar_write | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| const char * | value | |||
| ) | [static] |
Definition at line 9154 of file chan_iax2.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_var_assign(), ast_var_delete(), ast_datastore::data, DATASTORE_INHERIT_FOREVER, ast_datastore::inheritance, LOG_ERROR, ast_var_t::name, and var.
09155 { 09156 struct ast_datastore *variablestore = ast_channel_datastore_find(chan, &iax2_variable_datastore_info, NULL); 09157 AST_LIST_HEAD(, ast_var_t) *varlist; 09158 struct ast_var_t *var; 09159 09160 if (!variablestore) { 09161 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 09162 if (!variablestore) { 09163 ast_log(LOG_ERROR, "Memory allocation error\n"); 09164 return -1; 09165 } 09166 varlist = ast_calloc(1, sizeof(*varlist)); 09167 if (!varlist) { 09168 ast_log(LOG_ERROR, "Unable to assign new variable '%s'\n", data); 09169 return -1; 09170 } 09171 09172 AST_LIST_HEAD_INIT(varlist); 09173 variablestore->data = varlist; 09174 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 09175 ast_channel_datastore_add(chan, variablestore); 09176 } else 09177 varlist = variablestore->data; 09178 09179 AST_LIST_LOCK(varlist); 09180 AST_LIST_TRAVERSE_SAFE_BEGIN(varlist, var, entries) { 09181 if (strcmp(var->name, data) == 0) { 09182 AST_LIST_REMOVE_CURRENT(entries); 09183 ast_var_delete(var); 09184 break; 09185 } 09186 } 09187 AST_LIST_TRAVERSE_SAFE_END; 09188 var = ast_var_assign(data, value); 09189 if (var) 09190 AST_LIST_INSERT_TAIL(varlist, var, entries); 09191 else 09192 ast_log(LOG_ERROR, "Unable to assign new variable '%s'\n", data); 09193 AST_LIST_UNLOCK(varlist); 09194 return 0; 09195 }
| static int add_calltoken_ignore | ( | const char * | addr | ) | [static] |
Definition at line 2170 of file chan_iax2.c.
References ao2_alloc, ao2_find, ao2_link, ao2_lock(), ao2_ref, ao2_unlock(), ast_append_ha(), ast_copy_ha(), ast_free_ha(), ast_log(), ast_strlen_zero(), calltoken_ignores, addr_range::delme, addr_range::ha, LOG_WARNING, and OBJ_POINTER.
Referenced by set_config().
02171 { 02172 struct addr_range tmp; 02173 struct addr_range *addr_range = NULL; 02174 struct ast_ha *ha = NULL; 02175 int error = 0; 02176 02177 if (ast_strlen_zero(addr)) { 02178 ast_log(LOG_WARNING, "invalid calltokenoptional %s\n", addr); 02179 return -1; 02180 } 02181 02182 ha = ast_append_ha("permit", addr, NULL, &error); 02183 02184 /* check for valid config information */ 02185 if (error) { 02186 ast_log(LOG_WARNING, "Error %d creating calltokenoptional entry %s\n", error, addr); 02187 return -1; 02188 } 02189 02190 ast_copy_ha(ha, &tmp.ha); 02191 /* find or create the addr_range */ 02192 if ((addr_range = ao2_find(calltoken_ignores, &tmp, OBJ_POINTER))) { 02193 ao2_lock(addr_range); 02194 addr_range->delme = 0; 02195 ao2_unlock(addr_range); 02196 } else if ((addr_range = ao2_alloc(sizeof(*addr_range), NULL))) { 02197 /* copy over config data into addr_range object */ 02198 ast_copy_ha(ha, &addr_range->ha); /* this is safe because only one ha is possible */ 02199 ao2_link(calltoken_ignores, addr_range); 02200 } else { 02201 ast_free_ha(ha); 02202 return -1; 02203 } 02204 02205 ast_free_ha(ha); 02206 ao2_ref(addr_range, -1); /* decrement ref from ao2_find and ao2_alloc, only container ref remains */ 02207 02208 return 0; 02209 }
| static void add_empty_calltoken_ie | ( | struct chan_iax2_pvt * | pvt, | |
| struct iax_ie_data * | ied | |||
| ) | [static] |
Definition at line 4327 of file chan_iax2.c.
References iax_ie_data::buf, chan_iax2_pvt::calltoken_ie_len, IAX_IE_CALLTOKEN, and iax_ie_data::pos.
Referenced by cache_get_callno_locked(), iax2_call(), iax2_do_register(), iax2_poke_peer(), and registry_rerequest().
04328 { 04329 /* first make sure their are two empty bytes left in ied->buf */ 04330 if (pvt && ied && (2 < ((int) sizeof(ied->buf) - ied->pos))) { 04331 ied->buf[ied->pos++] = IAX_IE_CALLTOKEN; /* type */ 04332 ied->buf[ied->pos++] = 0; /* data size, ZERO in this case */ 04333 pvt->calltoken_ie_len = 2; 04334 } 04335 }
| static int addr_range_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1836 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, addr_range::ha, ast_ha::netaddr, and ast_ha::netmask.
Referenced by load_objects().
| static int addr_range_delme_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1823 of file chan_iax2.c.
References addr_range::delme.
Referenced by set_config_destroy().
01824 { 01825 struct addr_range *lim = obj; 01826 lim->delme = 1; 01827 return 0; 01828 }
| static int addr_range_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1830 of file chan_iax2.c.
References addr_range::ha, and ast_ha::netaddr.
Referenced by load_objects().
01831 { 01832 const struct addr_range *lim = obj; 01833 return abs((int) lim->ha.netaddr.s_addr); 01834 }
| static int addr_range_match_address_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1856 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, addr_range::ha, ast_ha::netaddr, and ast_ha::netmask.
Referenced by calltoken_required(), and set_peercnt_limit().
01857 { 01858 struct addr_range *addr_range = obj; 01859 struct sockaddr_in *sin = arg; 01860 01861 if ((sin->sin_addr.s_addr & addr_range->ha.netmask.s_addr) == addr_range->ha.netaddr.s_addr) { 01862 return CMP_MATCH | CMP_STOP; 01863 } 01864 return 0; 01865 }
| static int apply_context | ( | struct iax2_context * | con, | |
| const char * | context | |||
| ) | [static] |
Definition at line 6946 of file chan_iax2.c.
References iax2_context::context, and iax2_context::next.
Referenced by check_access().
| static int ast_cli_netstats | ( | struct mansession * | s, | |
| int | fd, | |||
| int | limit_fmt | |||
| ) | [static] |
Definition at line 6656 of file chan_iax2.c.
References ACN_FORMAT1, ACN_FORMAT2, ARRAY_LEN, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, astman_append(), jb_info::current, iax_rr::delay, iax_rr::dropped, chan_iax2_pvt::first_iax_message, jb_info::frames_dropped, jb_info::frames_lost, jb_info::frames_ooo, chan_iax2_pvt::frames_received, iax_frame_subclass2str(), IAX_USEJITTERBUF, jb_getinfo(), iax_rr::jitter, jb_info::jitter, chan_iax2_pvt::last_iax_message, iax_rr::losscnt, iax_rr::losspct, jb_info::losspct, MARK_IAX_SUBCLASS_TX, jb_info::min, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::pingtime, and chan_iax2_pvt::remote_rr.
Referenced by handle_cli_iax2_show_netstats(), and manager_iax2_show_netstats().
06657 { 06658 int x; 06659 int numchans = 0; 06660 char first_message[10] = { 0, }; 06661 char last_message[10] = { 0, }; 06662 #define ACN_FORMAT1 "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n" 06663 #define ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n" 06664 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 06665 ast_mutex_lock(&iaxsl[x]); 06666 if (iaxs[x]) { 06667 int localjitter, localdelay, locallost, locallosspct, localdropped, localooo; 06668 jb_info jbinfo; 06669 iax_frame_subclass2str(iaxs[x]->first_iax_message & ~MARK_IAX_SUBCLASS_TX, first_message, sizeof(first_message)); 06670 iax_frame_subclass2str(iaxs[x]->last_iax_message & ~MARK_IAX_SUBCLASS_TX, last_message, sizeof(last_message)); 06671 06672 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 06673 jb_getinfo(iaxs[x]->jb, &jbinfo); 06674 localjitter = jbinfo.jitter; 06675 localdelay = jbinfo.current - jbinfo.min; 06676 locallost = jbinfo.frames_lost; 06677 locallosspct = jbinfo.losspct/1000; 06678 localdropped = jbinfo.frames_dropped; 06679 localooo = jbinfo.frames_ooo; 06680 } else { 06681 localjitter = -1; 06682 localdelay = 0; 06683 locallost = -1; 06684 locallosspct = -1; 06685 localdropped = 0; 06686 localooo = -1; 06687 } 06688 if (s) 06689 astman_append(s, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2, 06690 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 06691 iaxs[x]->pingtime, 06692 localjitter, 06693 localdelay, 06694 locallost, 06695 locallosspct, 06696 localdropped, 06697 localooo, 06698 iaxs[x]->frames_received/1000, 06699 iaxs[x]->remote_rr.jitter, 06700 iaxs[x]->remote_rr.delay, 06701 iaxs[x]->remote_rr.losscnt, 06702 iaxs[x]->remote_rr.losspct, 06703 iaxs[x]->remote_rr.dropped, 06704 iaxs[x]->remote_rr.ooo, 06705 iaxs[x]->remote_rr.packets/1000, 06706 (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 06707 first_message, 06708 (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 06709 last_message); 06710 else 06711 ast_cli(fd, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2, 06712 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 06713 iaxs[x]->pingtime, 06714 localjitter, 06715 localdelay, 06716 locallost, 06717 locallosspct, 06718 localdropped, 06719 localooo, 06720 iaxs[x]->frames_received/1000, 06721 iaxs[x]->remote_rr.jitter, 06722 iaxs[x]->remote_rr.delay, 06723 iaxs[x]->remote_rr.losscnt, 06724 iaxs[x]->remote_rr.losspct, 06725 iaxs[x]->remote_rr.dropped, 06726 iaxs[x]->remote_rr.ooo, 06727 iaxs[x]->remote_rr.packets/1000, 06728 (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 06729 first_message, 06730 (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 06731 last_message); 06732 numchans++; 06733 } 06734 ast_mutex_unlock(&iaxsl[x]); 06735 } 06736 06737 return numchans; 06738 }
| static struct ast_channel* ast_iax2_new | ( | int | callno, | |
| int | state, | |||
| int | capability | |||
| ) | [static, read] |
Create new call, interface with the PBX core.
Definition at line 5237 of file chan_iax2.c.
References chan_iax2_pvt::accountcode, chan_iax2_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, chan_iax2_pvt::amaflags, chan_iax2_pvt::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_calloc, ast_channel_alloc, ast_channel_datastore_add(), ast_channel_free(), ast_copy_string(), ast_datastore_alloc, ast_datastore_free(), ast_debug, ast_free, ast_hangup(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, ast_log(), ast_module_ref(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), AST_STATE_DOWN, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_var_assign(), chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, chan_iax2_pvt::callno, CALLNO_TO_PTR, chan_iax2_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, chan_iax2_pvt::cid_name, chan_iax2_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, chan_iax2_pvt::context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, chan_iax2_pvt::dnid, ast_channel::exten, chan_iax2_pvt::exten, chan_iax2_pvt::host, iax2_ami_channelupdate(), chan_iax2_pvt::iaxvars, ast_datastore::inheritance, chan_iax2_pvt::language, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_channel::nativeformats, ast_variable::next, chan_iax2_pvt::owner, parkinglot, chan_iax2_pvt::parkinglot, pbx_builtin_setvar_helper(), chan_iax2_pvt::peeradsicpe, ast_channel::rawreadformat, ast_channel::rawwriteformat, chan_iax2_pvt::rdnis, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, ast_variable::value, var, chan_iax2_pvt::vars, and ast_channel::writeformat.
Referenced by iax2_request(), and socket_process().
05238 { 05239 struct ast_channel *tmp; 05240 struct chan_iax2_pvt *i; 05241 struct ast_variable *v = NULL; 05242 05243 if (!(i = iaxs[callno])) { 05244 ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno); 05245 return NULL; 05246 } 05247 05248 /* Don't hold call lock */ 05249 ast_mutex_unlock(&iaxsl[callno]); 05250 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "IAX2/%s-%d", i->host, i->callno); 05251 ast_mutex_lock(&iaxsl[callno]); 05252 if (i != iaxs[callno]) { 05253 if (tmp) { 05254 /* unlock and relock iaxsl[callno] to preserve locking order */ 05255 ast_mutex_unlock(&iaxsl[callno]); 05256 ast_channel_free(tmp); 05257 ast_mutex_lock(&iaxsl[callno]); 05258 } 05259 return NULL; 05260 } 05261 iax2_ami_channelupdate(i); 05262 if (!tmp) 05263 return NULL; 05264 tmp->tech = &iax2_tech; 05265 /* We can support any format by default, until we get restricted */ 05266 tmp->nativeformats = capability; 05267 tmp->readformat = tmp->rawreadformat = ast_best_codec(capability); 05268 tmp->writeformat = tmp->rawwriteformat = ast_best_codec(capability); 05269 tmp->tech_pvt = CALLNO_TO_PTR(i->callno); 05270 05271 if (!ast_strlen_zero(i->parkinglot)) 05272 ast_string_field_set(tmp, parkinglot, i->parkinglot); 05273 /* Don't use ast_set_callerid() here because it will 05274 * generate a NewCallerID event before the NewChannel event */ 05275 if (!ast_strlen_zero(i->ani)) 05276 tmp->cid.cid_ani = ast_strdup(i->ani); 05277 else 05278 tmp->cid.cid_ani = ast_strdup(i->cid_num); 05279 tmp->cid.cid_dnid = ast_strdup(i->dnid); 05280 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 05281 tmp->cid.cid_pres = i->calling_pres; 05282 tmp->cid.cid_ton = i->calling_ton; 05283 tmp->cid.cid_tns = i->calling_tns; 05284 if (!ast_strlen_zero(i->language)) 05285 ast_string_field_set(tmp, language, i->language); 05286 if (!ast_strlen_zero(i->accountcode)) 05287 ast_string_field_set(tmp, accountcode, i->accountcode); 05288 if (i->amaflags) 05289 tmp->amaflags = i->amaflags; 05290 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 05291 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 05292 if (i->adsi) 05293 tmp->adsicpe = i->peeradsicpe; 05294 else 05295 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 05296 i->owner = tmp; 05297 i->capability = capability; 05298 05299 /* Set inherited variables */ 05300 if (i->vars) { 05301 for (v = i->vars ; v ; v = v->next) 05302 pbx_builtin_setvar_helper(tmp, v->name, v->value); 05303 } 05304 if (i->iaxvars) { 05305 struct ast_datastore *variablestore; 05306 struct ast_variable *var, *prev = NULL; 05307 AST_LIST_HEAD(, ast_var_t) *varlist; 05308 ast_debug(1, "Loading up the channel with IAXVARs\n"); 05309 varlist = ast_calloc(1, sizeof(*varlist)); 05310 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 05311 if (variablestore && varlist) { 05312 variablestore->data = varlist; 05313 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 05314 AST_LIST_HEAD_INIT(varlist); 05315 for (var = i->iaxvars; var; var = var->next) { 05316 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 05317 if (prev) 05318 ast_free(prev); 05319 prev = var; 05320 if (!newvar) { 05321 /* Don't abort list traversal, as this would leave i->iaxvars in an inconsistent state. */ 05322 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 05323 } else { 05324 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 05325 } 05326 } 05327 if (prev) 05328 ast_free(prev); 05329 i->iaxvars = NULL; 05330 ast_channel_datastore_add(i->owner, variablestore); 05331 } else { 05332 if (variablestore) { 05333 ast_datastore_free(variablestore); 05334 } 05335 if (varlist) { 05336 ast_free(varlist); 05337 } 05338 } 05339 } 05340 05341 if (state != AST_STATE_DOWN) { 05342 if (ast_pbx_start(tmp)) { 05343 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 05344 ast_hangup(tmp); 05345 i->owner = NULL; 05346 return NULL; 05347 } 05348 } 05349 05350 ast_module_ref(ast_module_info->self); 05351 return tmp; 05352 }
| static int attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 3222 of file chan_iax2.c.
References __attempt_transmit(), and schedule_action.
Referenced by __attempt_transmit(), and network_thread().
03223 { 03224 #ifdef SCHED_MULTITHREADED 03225 if (schedule_action(__attempt_transmit, data)) 03226 #endif 03227 __attempt_transmit(data); 03228 return 0; 03229 }
| static int auth_fail | ( | int | callno, | |
| int | failcode | |||
| ) | [static] |
Definition at line 8385 of file chan_iax2.c.
References auth_reject(), chan_iax2_pvt::authfail, chan_iax2_pvt::authid, and iax2_sched_replace().
Referenced by socket_process().
08386 { 08387 /* Schedule sending the authentication failure in one second, to prevent 08388 guessing */ 08389 if (iaxs[callno]) { 08390 iaxs[callno]->authfail = failcode; 08391 if (delayreject) { 08392 iaxs[callno]->authid = iax2_sched_replace(iaxs[callno]->authid, 08393 sched, 1000, auth_reject, (void *)(long)callno); 08394 } else 08395 auth_reject((void *)(long)callno); 08396 } 08397 return 0; 08398 }
| static int auth_reject | ( | const void * | data | ) | [static] |
Definition at line 8371 of file chan_iax2.c.
References __auth_reject(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::authid, and schedule_action.
Referenced by auth_fail().
08372 { 08373 int callno = (int)(long)(data); 08374 ast_mutex_lock(&iaxsl[callno]); 08375 if (iaxs[callno]) 08376 iaxs[callno]->authid = -1; 08377 ast_mutex_unlock(&iaxsl[callno]); 08378 #ifdef SCHED_MULTITHREADED 08379 if (schedule_action(__auth_reject, data)) 08380 #endif 08381 __auth_reject(data); 08382 return 0; 08383 }
| static int authenticate | ( | const char * | challenge, | |
| const char * | secret, | |||
| const char * | keyn, | |||
| int | authmethods, | |||
| struct iax_ie_data * | ied, | |||
| struct sockaddr_in * | sin, | |||
| struct chan_iax2_pvt * | pvt | |||
| ) | [static] |
Definition at line 7510 of file chan_iax2.c.
References ast_inet_ntoa(), ast_key_get, AST_KEY_PRIVATE, ast_log(), ast_sign, ast_strlen_zero(), build_encryption_keys(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, iax_ie_append_str(), IAX_IE_MD5_RESULT, IAX_IE_PASSWORD, IAX_IE_RSA_RESULT, LOG_NOTICE, MD5Final(), MD5Init(), and MD5Update().
Referenced by authenticate_reply(), and registry_rerequest().
07511 { 07512 int res = -1; 07513 int x; 07514 if (!ast_strlen_zero(keyn)) { 07515 if (!(authmethods & IAX_AUTH_RSA)) { 07516 if (ast_strlen_zero(secret)) 07517 ast_log(LOG_NOTICE, "Asked to authenticate to %s with an RSA key, but they don't allow RSA authentication\n", ast_inet_ntoa(sin->sin_addr)); 07518 } else if (ast_strlen_zero(challenge)) { 07519 ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr)); 07520 } else { 07521 char sig[256]; 07522 struct ast_key *key; 07523 key = ast_key_get(keyn, AST_KEY_PRIVATE); 07524 if (!key) { 07525 ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn); 07526 } else { 07527 if (ast_sign(key, (char*)challenge, sig)) { 07528 ast_log(LOG_NOTICE, "Unable to sign challenge with key\n"); 07529 res = -1; 07530 } else { 07531 iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig); 07532 res = 0; 07533 } 07534 } 07535 } 07536 } 07537 /* Fall back */ 07538 if (res && !ast_strlen_zero(secret)) { 07539 if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) { 07540 struct MD5Context md5; 07541 unsigned char digest[16]; 07542 char digres[128]; 07543 MD5Init(&md5); 07544 MD5Update(&md5, (unsigned char *)challenge, strlen(challenge)); 07545 MD5Update(&md5, (unsigned char *)secret, strlen(secret)); 07546 MD5Final(digest, &md5); 07547 /* If they support md5, authenticate with it. */ 07548 for (x=0;x<16;x++) 07549 sprintf(digres + (x << 1), "%2.2x", digest[x]); /* safe */ 07550 if (pvt) { 07551 build_encryption_keys(digest, pvt); 07552 } 07553 iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres); 07554 res = 0; 07555 } else if (authmethods & IAX_AUTH_PLAINTEXT) { 07556 iax_ie_append_str(ied, IAX_IE_PASSWORD, secret); 07557 res = 0; 07558 } else 07559 ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods); 07560 } 07561 return res; 07562 }
| static int authenticate_reply | ( | struct chan_iax2_pvt * | p, | |
| struct sockaddr_in * | sin, | |||
| struct iax_ies * | ies, | |||
| const char * | override, | |||
| const char * | okey | |||
| ) | [static] |
Definition at line 7568 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next, ast_calloc, ast_channel_datastore_add(), ast_datastore_alloc, ast_datastore_free(), AST_FRAME_IAX, ast_free, AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_var_assign(), authenticate(), iax_ies::authmethods, iax2_peer::authmethods, iax_ie_data::buf, chan_iax2_pvt::callno, chan_iax2_pvt::challenge, iax_ies::challenge, ast_datastore::data, DATASTORE_INHERIT_FOREVER, chan_iax2_pvt::encmethods, iax_ies::encmethods, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, ast_datastore::inheritance, LOG_ERROR, iax2_peer::mask, merge_encryption(), ast_variable::name, iax2_peer::name, ast_variable::next, iax2_peer::outkey, chan_iax2_pvt::owner, chan_iax2_pvt::peer, peer_unref(), iax_ie_data::pos, realtime_peer(), iax2_peer::secret, send_command(), chan_iax2_pvt::username, iax2_peer::username, iax_ies::username, ast_variable::value, var, and iax_ies::vars.
Referenced by socket_process().
07569 { 07570 struct iax2_peer *peer = NULL; 07571 /* Start pessimistic */ 07572 int res = -1; 07573 int authmethods = 0; 07574 struct iax_ie_data ied; 07575 uint16_t callno = p->callno; 07576 07577 memset(&ied, 0, sizeof(ied)); 07578 07579 if (ies->username) 07580 ast_string_field_set(p, username, ies->username); 07581 if (ies->challenge) 07582 ast_string_field_set(p, challenge, ies->challenge); 07583 if (ies->authmethods) 07584 authmethods = ies->authmethods; 07585 if (authmethods & IAX_AUTH_MD5) 07586 merge_encryption(p, ies->encmethods); 07587 else 07588 p->encmethods = 0; 07589 07590 /* Check for override RSA authentication first */ 07591 if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) { 07592 /* Normal password authentication */ 07593 res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, p); 07594 } else { 07595 struct ao2_iterator i = ao2_iterator_init(peers, 0); 07596 while ((peer = ao2_iterator_next(&i))) { 07597 if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 07598 /* No peer specified at our end, or this is the peer */ 07599 && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username))) 07600 /* No username specified in peer rule, or this is the right username */ 07601 && (!peer->addr.sin_addr.s_addr || ((sin->sin_addr.s_addr & peer->mask.s_addr) == (peer->addr.sin_addr.s_addr & peer->mask.s_addr))) 07602 /* No specified host, or this is our host */ 07603 ) { 07604 res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, p); 07605 if (!res) { 07606 peer_unref(peer); 07607 break; 07608 } 07609 } 07610 peer_unref(peer); 07611 } 07612 if (!peer) { 07613 /* We checked our list and didn't find one. It's unlikely, but possible, 07614 that we're trying to authenticate *to* a realtime peer */ 07615 const char *peer_name = ast_strdupa(p->peer); 07616 ast_mutex_unlock(&iaxsl[callno]); 07617 if ((peer = realtime_peer(peer_name, NULL))) { 07618 ast_mutex_lock(&iaxsl[callno]); 07619 if (!(p = iaxs[callno])) { 07620 peer_unref(peer); 07621 return -1; 07622 } 07623 res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, p); 07624 peer_unref(peer); 07625 } 07626 if (!peer) { 07627 ast_mutex_lock(&iaxsl[callno]); 07628 if (!(p = iaxs[callno])) 07629 return -1; 07630 } 07631 } 07632 } 07633 if (ies->encmethods) 07634 ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED); 07635 if (!res) { 07636 struct ast_datastore *variablestore; 07637 struct ast_variable *var, *prev = NULL; 07638 AST_LIST_HEAD(, ast_var_t) *varlist; 07639 varlist = ast_calloc(1, sizeof(*varlist)); 07640 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 07641 if (variablestore && varlist && p->owner) { 07642 variablestore->data = varlist; 07643 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 07644 AST_LIST_HEAD_INIT(varlist); 07645 for (var = ies->vars; var; var = var->next) { 07646 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 07647 if (prev) 07648 ast_free(prev); 07649 prev = var; 07650 if (!newvar) { 07651 /* Don't abort list traversal, as this would leave ies->vars in an inconsistent state. */ 07652 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 07653 } else { 07654 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 07655 } 07656 } 07657 if (prev) 07658 ast_free(prev); 07659 ies->vars = NULL; 07660 ast_channel_datastore_add(p->owner, variablestore); 07661 } else { 07662 if (p->owner) 07663 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 07664 if (variablestore) 07665 ast_datastore_free(variablestore); 07666 if (varlist) 07667 ast_free(varlist); 07668 } 07669 } 07670 07671 if (!res) 07672 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1); 07673 return res; 07674 }
| static int authenticate_request | ( | int | call_num | ) | [static] |
Definition at line 7221 of file chan_iax2.c.
References ao2_find, AST_CAUSE_CALL_REJECTED, AST_FRAME_IAX, ast_random(), ast_set_flag, ast_string_field_set, ast_test_flag, chan_iax2_pvt::authmethods, iax_ie_data::buf, chan_iax2_pvt::challenge, iax2_user::curauthreq, chan_iax2_pvt::encmethods, IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_AUTHREQ, IAX_COMMAND_REJECT, IAX_ENCRYPTED, iax_ie_append_byte(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_ENCRYPTION, IAX_IE_USERNAME, IAX_MAXAUTHREQ, iax2_user::maxauthreq, OBJ_POINTER, iax_ie_data::pos, send_command(), send_command_final(), user_unref(), and chan_iax2_pvt::username.
Referenced by socket_process().
07222 { 07223 struct iax_ie_data ied; 07224 int res = -1, authreq_restrict = 0; 07225 char challenge[10]; 07226 struct chan_iax2_pvt *p = iaxs[call_num]; 07227 07228 memset(&ied, 0, sizeof(ied)); 07229 07230 /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */ 07231 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 07232 struct iax2_user *user, tmp_user = { 07233 .name = p->username, 07234 }; 07235 07236 user = ao2_find(users, &tmp_user, OBJ_POINTER); 07237 if (user) { 07238 if (user->curauthreq == user->maxauthreq) 07239 authreq_restrict = 1; 07240 else 07241 user->curauthreq++; 07242 user = user_unref(user); 07243 } 07244 } 07245 07246 /* If the AUTHREQ limit test failed, send back an error */ 07247 if (authreq_restrict) { 07248 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached"); 07249 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED); 07250 send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1); 07251 return 0; 07252 } 07253 07254 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 07255 if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) { 07256 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 07257 ast_string_field_set(p, challenge, challenge); 07258 /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */ 07259 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge); 07260 } 07261 if (p->encmethods) 07262 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods); 07263 07264 iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username); 07265 07266 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1); 07267 07268 if (p->encmethods) 07269 ast_set_flag(p, IAX_ENCRYPTED); 07270 07271 return res; 07272 }
| static int authenticate_verify | ( | struct chan_iax2_pvt * | p, | |
| struct iax_ies * | ies | |||
| ) | [static] |
Definition at line 7274 of file chan_iax2.c.
References ao2_find, ast_atomic_fetchadd_int(), ast_check_signature, ast_clear_flag, ast_copy_string(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, chan_iax2_pvt::authmethods, chan_iax2_pvt::authrej, chan_iax2_pvt::challenge, iax2_user::curauthreq, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_MAXAUTHREQ, IAX_STATE_AUTHENTICATED, chan_iax2_pvt::inkeys, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax2_user::name, OBJ_POINTER, iax_ies::password, iax_ies::rsa_result, chan_iax2_pvt::secret, secret, chan_iax2_pvt::state, strsep(), user_unref(), and chan_iax2_pvt::username.
Referenced by socket_process().
07275 { 07276 char requeststr[256]; 07277 char md5secret[256] = ""; 07278 char secret[256] = ""; 07279 char rsasecret[256] = ""; 07280 int res = -1; 07281 int x; 07282 struct iax2_user *user, tmp_user = { 07283 .name = p->username, 07284 }; 07285 07286 if (p->authrej) { 07287 return res; 07288 } 07289 user = ao2_find(users, &tmp_user, OBJ_POINTER); 07290 if (user) { 07291 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 07292 ast_atomic_fetchadd_int(&user->curauthreq, -1); 07293 ast_clear_flag(p, IAX_MAXAUTHREQ); 07294 } 07295 ast_string_field_set(p, host, user->name); 07296 user = user_unref(user); 07297 } 07298 07299 if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED)) 07300 return res; 07301 if (ies->password) 07302 ast_copy_string(secret, ies->password, sizeof(secret)); 07303 if (ies->md5_result) 07304 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 07305 if (ies->rsa_result) 07306 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 07307 if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) { 07308 struct ast_key *key; 07309 char *keyn; 07310 char tmpkey[256]; 07311 char *stringp=NULL; 07312 ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey)); 07313 stringp=tmpkey; 07314 keyn = strsep(&stringp, ":"); 07315 while(keyn) { 07316 key = ast_key_get(keyn, AST_KEY_PUBLIC); 07317 if (key && !ast_check_signature(key, p->challenge, rsasecret)) { 07318 res = 0; 07319 break; 07320 } else if (!key) 07321 ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn); 07322 keyn = strsep(&stringp, ":"); 07323 } 07324 } else if (p->authmethods & IAX_AUTH_MD5) { 07325 struct MD5Context md5; 07326 unsigned char digest[16]; 07327 char *tmppw, *stringp; 07328 07329 tmppw = ast_strdupa(p->secret); 07330 stringp = tmppw; 07331 while((tmppw = strsep(&stringp, ";"))) { 07332 MD5Init(&md5); 07333 MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge)); 07334 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 07335 MD5Final(digest, &md5); 07336 /* If they support md5, authenticate with it. */ 07337 for (x=0;x<16;x++) 07338 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 07339 if (!strcasecmp(requeststr, md5secret)) { 07340 res = 0; 07341 break; 07342 } 07343 } 07344 } else if (p->authmethods & IAX_AUTH_PLAINTEXT) { 07345 if (!strcmp(secret, p->secret)) 07346 res = 0; 07347 } 07348 return res; 07349 }
| static int auto_congest | ( | const void * | data | ) | [static] |
Definition at line 4266 of file chan_iax2.c.
References __auto_congest(), and schedule_action.
Referenced by iax2_call().
04267 { 04268 #ifdef SCHED_MULTITHREADED 04269 if (schedule_action(__auto_congest, data)) 04270 #endif 04271 __auto_congest(data); 04272 return 0; 04273 }
| static int auto_hangup | ( | const void * | data | ) | [static] |
Definition at line 8415 of file chan_iax2.c.
References __auto_hangup(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::autoid, and schedule_action.
Referenced by iax2_dprequest(), and iax2_provision().
08416 { 08417 int callno = (int)(long)(data); 08418 ast_mutex_lock(&iaxsl[callno]); 08419 if (iaxs[callno]) { 08420 iaxs[callno]->autoid = -1; 08421 } 08422 ast_mutex_unlock(&iaxsl[callno]); 08423 #ifdef SCHED_MULTITHREADED 08424 if (schedule_action(__auto_hangup, data)) 08425 #endif 08426 __auto_hangup(data); 08427 return 0; 08428 }
| static void build_callno_limits | ( | struct ast_variable * | v | ) | [static] |
Definition at line 2115 of file chan_iax2.c.
References ao2_alloc, ao2_find, ao2_link, ao2_lock(), ao2_ref, ao2_unlock(), ast_append_ha(), ast_copy_ha(), ast_free_ha(), ast_log(), callno_limits, addr_range::delme, addr_range::ha, addr_range::limit, LOG_ERROR, ast_variable::name, ast_variable::next, OBJ_POINTER, and ast_variable::value.
Referenced by set_config().
02116 { 02117 struct addr_range *addr_range = NULL; 02118 struct addr_range tmp; 02119 struct ast_ha *ha; 02120 int limit; 02121 int error; 02122 int found; 02123 02124 for (; v; v = v->next) { 02125 limit = -1; 02126 error = 0; 02127 found = 0; 02128 ha = ast_append_ha("permit", v->name, NULL, &error); 02129 02130 /* check for valid config information */ 02131 if (error) { 02132 ast_log(LOG_ERROR, "Call number limit for %s could not be added, Invalid address range\n.", v->name); 02133 continue; 02134 } else if ((sscanf(v->value, "%d", &limit) != 1) || (limit < 0)) { 02135 ast_log(LOG_ERROR, "Call number limit for %s could not be added. Invalid limit %s\n.", v->name, v->value); 02136 ast_free_ha(ha); 02137 continue; 02138 } 02139 02140 ast_copy_ha(ha, &tmp.ha); 02141 /* find or create the addr_range */ 02142 if ((addr_range = ao2_find(callno_limits, &tmp, OBJ_POINTER))) { 02143 ao2_lock(addr_range); 02144 found = 1; 02145 } else if (!(addr_range = ao2_alloc(sizeof(*addr_range), NULL))) { 02146 ast_free_ha(ha); 02147 return; /* out of memory */ 02148 } 02149 02150 /* copy over config data into addr_range object */ 02151 ast_copy_ha(ha, &addr_range->ha); /* this is safe because only one ha is possible for each limit */ 02152 ast_free_ha(ha); /* cleanup the tmp ha */ 02153 addr_range->limit = limit; 02154 addr_range->delme = 0; 02155 02156 /* cleanup */ 02157 if (found) { 02158 ao2_unlock(addr_range); 02159 } else { 02160 ao2_link(callno_limits, addr_range); 02161 } 02162 ao2_ref(addr_range, -1); /* decrement ref from ao2_find and ao2_alloc, only container ref remains */ 02163 } 02164 }
| static struct iax2_context* build_context | ( | const char * | context | ) | [static, read] |
Definition at line 11480 of file chan_iax2.c.
References ast_calloc, ast_copy_string(), and iax2_context::context.
Referenced by build_user().
11481 { 11482 struct iax2_context *con; 11483 11484 if ((con = ast_calloc(1, sizeof(*con)))) 11485 ast_copy_string(con->context, context, sizeof(con->context)); 11486 11487 return con; 11488 }
| static void build_ecx_key | ( | const unsigned char * | digest, | |
| struct chan_iax2_pvt * | pvt | |||
| ) | [static] |
Definition at line 5695 of file chan_iax2.c.
References ast_aes_decrypt_key, ast_aes_encrypt_key, build_rand_pad(), chan_iax2_pvt::ecx, chan_iax2_pvt::mydcx, and chan_iax2_pvt::semirand.
Referenced by build_encryption_keys(), and iax2_key_rotate().
05696 { 05697 /* it is required to hold the corresponding decrypt key to our encrypt key 05698 * in the pvt struct because queued frames occasionally need to be decrypted and 05699 * re-encrypted when updated for a retransmission */ 05700 build_rand_pad(pvt->semirand, sizeof(pvt->semirand)); 05701 ast_aes_encrypt_key(digest, &pvt->ecx); 05702 ast_aes_decrypt_key(digest, &pvt->mydcx); 05703 }
| static void build_encryption_keys | ( | const unsigned char * | digest, | |
| struct chan_iax2_pvt * | pvt | |||
| ) | [static] |
Definition at line 5689 of file chan_iax2.c.
References ast_aes_decrypt_key, build_ecx_key(), and chan_iax2_pvt::dcx.
Referenced by authenticate(), and decrypt_frame().
05690 { 05691 build_ecx_key(digest, pvt); 05692 ast_aes_decrypt_key(digest, &pvt->dcx); 05693 }
| static struct iax2_peer * build_peer | ( | const char * | name, | |
| struct ast_variable * | v, | |||
| struct ast_variable * | alt, | |||
| int | temponly | |||
| ) | [static, read] |
Create peer structure based on configuration.
Definition at line 11628 of file chan_iax2.c.
References iax2_peer::addr, iax2_peer::adsi, ao2_alloc, ao2_find, ast_append_ha(), ast_callerid_split(), ast_clear_flag, ast_copy_flags, ast_dnsmgr_lookup(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_false(), ast_free_ha(), ast_get_ip(), ast_log(), ast_parse_allow_disallow(), AST_SCHED_DEL, ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_strdupa, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), iax2_peer::authmethods, CALLTOKEN_AUTO, CALLTOKEN_DEFAULT, CALLTOKEN_NO, iax2_peer::calltoken_required, CALLTOKEN_YES, iax2_peer::capability, cid_name, cid_num, context, iax2_peer::dbsecret, iax2_peer::defaddr, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, iax2_peer::dnsmgr, iax2_peer::encmethods, iax2_peer::expire, iax2_peer::expiry, get_auth_methods(), get_encrypt_methods(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_peer::inkeys, ast_variable::lineno, LOG_WARNING, iax2_peer::mailbox, mailbox, iax2_peer::mask, iax2_peer::maxcallno, iax2_peer::maxms, mwi_event_cb(), iax2_peer::mwi_event_sub, ast_variable::name, iax2_peer::name, ast_variable::next, OBJ_POINTER, iax2_peer::outkey, peer_destructor(), peer_set_srcaddr(), peer_unref(), peercnt_modify(), iax2_peer::peercontext, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, prefs, iax2_peer::prefs, regexten, S_OR, secret, iax2_peer::smoothing, iax2_peer::sockfd, strsep(), unlink_peer(), ast_variable::value, and zonetag.
Referenced by realtime_peer(), and set_config().
11629 { 11630 struct iax2_peer *peer = NULL; 11631 struct ast_ha *oldha = NULL; 11632 int maskfound = 0; 11633 int found = 0; 11634 int firstpass = 1; 11635 struct iax2_peer tmp_peer = { 11636 .name = name, 11637 }; 11638 11639 if (!temponly) { 11640 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 11641 if (peer && !ast_test_flag(peer, IAX_DELME)) 11642 firstpass = 0; 11643 } 11644 11645 if (peer) { 11646 found++; 11647 if (firstpass) { 11648 oldha = peer->ha; 11649 peer->ha = NULL; 11650 } 11651 unlink_peer(peer); 11652 } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) { 11653 peer->expire = -1; 11654 peer->pokeexpire = -1; 11655 peer->sockfd = defaultsockfd; 11656 if (ast_string_field_init(peer, 32)) 11657 peer = peer_unref(peer); 11658 } 11659 11660 if (peer) { 11661 if (firstpass) { 11662 ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 11663 peer->encmethods = iax2_encryption; 11664 peer->adsi = adsi; 11665 ast_string_field_set(peer,secret,""); 11666 if (!found) { 11667 ast_string_field_set(peer, name, name); 11668 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 11669 peer->expiry = min_reg_expire; 11670 } 11671 peer->prefs = prefs; 11672 peer->capability = iax2_capability; 11673 peer->smoothing = 0; 11674 peer->pokefreqok = DEFAULT_FREQ_OK; 11675 peer->pokefreqnotok = DEFAULT_FREQ_NOTOK; 11676 peer->maxcallno = 0; 11677 peercnt_modify(0, 0, &peer->addr); 11678 peer->calltoken_required = CALLTOKEN_DEFAULT; 11679 ast_string_field_set(peer,context,""); 11680 ast_string_field_set(peer,peercontext,""); 11681 ast_clear_flag(peer, IAX_HASCALLERID); 11682 ast_string_field_set(peer, cid_name, ""); 11683 ast_string_field_set(peer, cid_num, ""); 11684 ast_string_field_set(peer, mohinterpret, mohinterpret); 11685 ast_string_field_set(peer, mohsuggest, mohsuggest); 11686 } 11687 11688 if (!v) { 11689 v = alt; 11690 alt = NULL; 11691 } 11692 while(v) { 11693 if (!strcasecmp(v->name, "secret")) { 11694 ast_string_field_set(peer, secret, v->value); 11695 } else if (!strcasecmp(v->name, "mailbox")) { 11696 ast_string_field_set(peer, mailbox, v->value); 11697 } else if (!strcasecmp(v->name, "hasvoicemail")) { 11698 if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) { 11699 ast_string_field_set(peer, mailbox, name); 11700 } 11701 } else if (!strcasecmp(v->name, "mohinterpret")) { 11702 ast_string_field_set(peer, mohinterpret, v->value); 11703 } else if (!strcasecmp(v->name, "mohsuggest")) { 11704 ast_string_field_set(peer, mohsuggest, v->value); 11705 } else if (!strcasecmp(v->name, "dbsecret")) { 11706 ast_string_field_set(peer, dbsecret, v->value); 11707 } else if (!strcasecmp(v->name, "trunk")) { 11708 ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK); 11709 if (ast_test_flag(peer, IAX_TRUNK) && !timer) { 11710 ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without a timing interface\n", peer->name); 11711 ast_clear_flag(peer, IAX_TRUNK); 11712 } 11713 } else if (!strcasecmp(v->name, "auth")) { 11714 peer->authmethods = get_auth_methods(v->value); 11715 } else if (!strcasecmp(v->name, "encryption")) { 11716 peer->encmethods |= get_encrypt_methods(v->value); 11717 } else if (!strcasecmp(v->name, "transfer")) { 11718 if (!strcasecmp(v->value, "mediaonly")) { 11719 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 11720 } else if (ast_true(v->value)) { 11721 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 11722 } else 11723 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 11724 } else if (!strcasecmp(v->name, "jitterbuffer")) { 11725 ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF); 11726 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 11727 ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF); 11728 } else if (!strcasecmp(v->name, "host")) { 11729 if (!strcasecmp(v->value, "dynamic")) { 11730 /* They'll register with us */ 11731 ast_set_flag(peer, IAX_DYNAMIC); 11732 if (!found) { 11733 /* Initialize stuff iff we're not found, otherwise 11734 we keep going with what we had */ 11735 memset(&peer->addr.sin_addr, 0, 4); 11736 if (peer->addr.sin_port) { 11737 /* If we've already got a port, make it the default rather than absolute */ 11738 peer->defaddr.sin_port = peer->addr.sin_port; 11739 peer->addr.sin_port = 0; 11740 } 11741 } 11742 } else { 11743 /* Non-dynamic. Make sure we become that way if we're not */ 11744 AST_SCHED_DEL(sched, peer->expire); 11745 ast_clear_flag(peer, IAX_DYNAMIC); 11746 if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL)) 11747 return peer_unref(peer); 11748 if (!peer->addr.sin_port) 11749 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 11750 } 11751 if (!maskfound) 11752 inet_aton("255.255.255.255", &peer->mask); 11753 } else if (!strcasecmp(v->name, "defaultip")) { 11754 if (ast_get_ip(&peer->defaddr, v->value)) 11755 return peer_unref(peer); 11756 } else if (!strcasecmp(v->name, "sourceaddress")) { 11757 peer_set_srcaddr(peer, v->value); 11758 } else if (!strcasecmp(v->name, "permit") || 11759 !strcasecmp(v->name, "deny")) { 11760 peer->ha = ast_append_ha(v->name, v->value, peer->ha, NULL); 11761 } else if (!strcasecmp(v->name, "mask")) { 11762 maskfound++; 11763 inet_aton(v->value, &peer->mask); 11764 } else if (!strcasecmp(v->name, "context")) { 11765 ast_string_field_set(peer, context, v->value); 11766 } else if (!strcasecmp(v->name, "regexten")) { 11767 ast_string_field_set(peer, regexten, v->value); 11768 } else if (!strcasecmp(v->name, "peercontext")) { 11769 ast_string_field_set(peer, peercontext, v->value); 11770 } else if (!strcasecmp(v->name, "port")) { 11771 if (ast_test_flag(peer, IAX_DYNAMIC)) 11772 peer->defaddr.sin_port = htons(atoi(v->value)); 11773 else 11774 peer->addr.sin_port = htons(atoi(v->value)); 11775 } else if (!strcasecmp(v->name, "username")) { 11776 ast_string_field_set(peer, username, v->value); 11777 } else if (!strcasecmp(v->name, "allow")) { 11778 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1); 11779 } else if (!strcasecmp(v->name, "disallow")) { 11780 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); 11781 } else if (!strcasecmp(v->name, "callerid")) { 11782 if (!ast_strlen_zero(v->value)) { 11783 char name2[80]; 11784 char num2[80]; 11785 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 11786 ast_string_field_set(peer, cid_name, name2); 11787 ast_string_field_set(peer, cid_num, num2); 11788 } else { 11789 ast_string_field_set(peer, cid_name, ""); 11790 ast_string_field_set(peer, cid_num, ""); 11791 } 11792 ast_set_flag(peer, IAX_HASCALLERID); 11793 } else if (!strcasecmp(v->name, "fullname")) { 11794 ast_string_field_set(peer, cid_name, S_OR(v->value, "")); 11795 ast_set_flag(peer, IAX_HASCALLERID); 11796 } else if (!strcasecmp(v->name, "cid_number")) { 11797 ast_string_field_set(peer, cid_num, S_OR(v->value, "")); 11798 ast_set_flag(peer, IAX_HASCALLERID); 11799 } else if (!strcasecmp(v->name, "sendani")) { 11800 ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 11801 } else if (!strcasecmp(v->name, "inkeys")) { 11802 ast_string_field_set(peer, inkeys, v->value); 11803 } else if (!strcasecmp(v->name, "outkey")) { 11804 ast_string_field_set(peer, outkey, v->value); 11805 } else if (!strcasecmp(v->name, "qualify")) { 11806 if (!strcasecmp(v->value, "no")) { 11807 peer->maxms = 0; 11808 } else if (!strcasecmp(v->value, "yes")) { 11809 peer->maxms = DEFAULT_MAXMS; 11810 } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) { 11811 ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of iax.conf\n", peer->name, v->lineno); 11812 peer->maxms = 0; 11813 } 11814 } else if (!strcasecmp(v->name, "qualifysmoothing")) { 11815 peer->smoothing = ast_true(v->value); 11816 } else if (!strcasecmp(v->name, "qualifyfreqok")) { 11817 if (sscanf(v->value, "%30d", &peer->pokefreqok) != 1) { 11818 ast_log(LOG_WARNING, "Qualification testing frequency of peer '%s' when OK should a number of milliseconds at line %d of iax.conf\n", peer->name, v->lineno); 11819 } 11820 } else if (!strcasecmp(v->name, "qualifyfreqnotok")) { 11821 if (sscanf(v->value, "%30d", &peer->pokefreqnotok) != 1) { 11822 ast_log(LOG_WARNING, "Qualification testing frequency of peer '%s' when NOT OK should be a number of milliseconds at line %d of iax.conf\n", peer->name, v->lineno); 11823 } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok); 11824 } else if (!strcasecmp(v->name, "timezone")) { 11825 ast_string_field_set(peer, zonetag, v->value); 11826 } else if (!strcasecmp(v->name, "adsi")) { 11827 peer->adsi = ast_true(v->value); 11828 } else if (!strcasecmp(v->name, "maxcallnumbers")) { 11829 if (sscanf(v->value, "%10hu", &peer->maxcallno) != 1) { 11830 ast_log(LOG_WARNING, "maxcallnumbers must be set to a valid number. %s is not valid at line %d.\n", v->value, v->lineno); 11831 } else { 11832 peercnt_modify(1, peer->maxcallno, &peer->addr); 11833 } 11834 } else if (!strcasecmp(v->name, "requirecalltoken")) { 11835 /* default is required unless in optional ip list */ 11836 if (ast_false(v->value)) { 11837 peer->calltoken_required = CALLTOKEN_NO; 11838 } else if (!strcasecmp(v->value, "auto")) { 11839 peer->calltoken_required = CALLTOKEN_AUTO; 11840 } else if (ast_true(v->value)) { 11841 peer->calltoken_required = CALLTOKEN_YES; 11842 } else { 11843 ast_log(LOG_WARNING, "requirecalltoken must be set to a valid value. at line %d\n", v->lineno); 11844 } 11845 } /* else if (strcasecmp(v->name,"type")) */ 11846 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 11847 v = v->next; 11848 if (!v) { 11849 v = alt; 11850 alt = NULL; 11851 } 11852 } 11853 if (!peer->authmethods) 11854 peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 11855 ast_clear_flag(peer, IAX_DELME); 11856 /* Make sure these are IPv4 addresses */ 11857 peer->addr.sin_family = AF_INET; 11858 } 11859 11860 if (oldha) 11861 ast_free_ha(oldha); 11862 11863 if (!ast_strlen_zero(peer->mailbox)) { 11864 char *mailbox, *context; 11865 context = mailbox = ast_strdupa(peer->mailbox); 11866 strsep(&context, "@"); 11867 if (ast_strlen_zero(context)) 11868 context = "default"; 11869 peer->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 11870 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 11871 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 11872 AST_EVENT_IE_END); 11873 } 11874 11875 return peer; 11876 }
| static void build_rand_pad | ( | unsigned char * | buf, | |
| ssize_t | len | |||
| ) | [static] |
Definition at line 5679 of file chan_iax2.c.
References ast_random().
Referenced by build_ecx_key(), and update_packet().
05680 { 05681 long tmp; 05682 for (tmp = ast_random(); len > 0; tmp = ast_random()) { 05683 memcpy(buf, (unsigned char *) &tmp, (len > sizeof(tmp)) ? sizeof(tmp) : len); 05684 buf += sizeof(tmp); 05685 len -= sizeof(tmp); 05686 } 05687 }
| static struct iax2_user * build_user | ( | const char * | name, | |
| struct ast_variable * | v, | |||
| struct ast_variable * | alt, | |||
| int | temponly | |||
| ) | [static, read] |
Create in-memory user structure from configuration.
Definition at line 11892 of file chan_iax2.c.
References iax2_user::adsi, iax2_user::amaflags, ao2_alloc, ao2_find, ao2_unlink, ast_append_ha(), ast_callerid_split(), ast_cdr_amaflags2int(), ast_clear_flag, ast_copy_flags, ast_false(), ast_free_ha(), ast_log(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_strdupa, ast_string_field_build, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_new(), iax2_user::authmethods, build_context(), CALLTOKEN_AUTO, CALLTOKEN_DEFAULT, CALLTOKEN_NO, iax2_user::calltoken_required, CALLTOKEN_YES, iax2_user::capability, iax2_user::cid_name, cid_name, iax2_user::cid_num, cid_num, cleanup(), iax2_user::contexts, iax2_user::curauthreq, iax2_user::dbsecret, iax2_user::encmethods, format, free_context(), get_auth_methods(), get_encrypt_methods(), iax2_user::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_user::inkeys, ast_variable::lineno, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, iax2_user::name, ast_variable::next, iax2_context::next, OBJ_POINTER, parkinglot, prefs, iax2_user::prefs, secret, iax2_user::secret, user_destructor(), user_unref(), ast_variable::value, and iax2_user::vars.
Referenced by realtime_user(), and set_config().
11893 { 11894 struct iax2_user *user = NULL; 11895 struct iax2_context *con, *conl = NULL; 11896 struct ast_ha *oldha = NULL; 11897 struct iax2_context *oldcon = NULL; 11898 int format; 11899 int firstpass=1; 11900 int oldcurauthreq = 0; 11901 char *varname = NULL, *varval = NULL; 11902 struct ast_variable *tmpvar = NULL; 11903 struct iax2_user tmp_user = { 11904 .name = name, 11905 }; 11906 11907 if (!temponly) { 11908 user = ao2_find(users, &tmp_user, OBJ_POINTER); 11909 if (user && !ast_test_flag(user, IAX_DELME)) 11910 firstpass = 0; 11911 } 11912 11913 if (user) { 11914 if (firstpass) { 11915 oldcurauthreq = user->curauthreq; 11916 oldha = user->ha; 11917 oldcon = user->contexts; 11918 user->ha = NULL; 11919 user->contexts = NULL; 11920 } 11921 /* Already in the list, remove it and it will be added back (or FREE'd) */ 11922 ao2_unlink(users, user); 11923 } else { 11924 user = ao2_alloc(sizeof(*user), user_destructor); 11925 } 11926 11927 if (user) { 11928 if (firstpass) { 11929 ast_string_field_free_memory(user); 11930 memset(user, 0, sizeof(struct iax2_user)); 11931 if (ast_string_field_init(user, 32)) { 11932 user = user_unref(user); 11933 goto cleanup; 11934 } 11935 user->maxauthreq = maxauthreq; 11936 user->curauthreq = oldcurauthreq; 11937 user->prefs = prefs; 11938 user->capability = iax2_capability; 11939 user->encmethods = iax2_encryption; 11940 user->adsi = adsi; 11941 user->calltoken_required = CALLTOKEN_DEFAULT; 11942 ast_string_field_set(user, name, name); 11943 ast_string_field_set(user, language, language); 11944 ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP); 11945 ast_clear_flag(user, IAX_HASCALLERID); 11946 ast_string_field_set(user, cid_name, ""); 11947 ast_string_field_set(user, cid_num, ""); 11948 ast_string_field_set(user, accountcode, accountcode); 11949 ast_string_field_set(user, mohinterpret, mohinterpret); 11950 ast_string_field_set(user, mohsuggest, mohsuggest); 11951 } 11952 if (!v) { 11953 v = alt; 11954 alt = NULL; 11955 } 11956 while(v) { 11957 if (!strcasecmp(v->name, "context")) { 11958 con = build_context(v->value); 11959 if (con) { 11960 if (conl) 11961 conl->next = con; 11962 else 11963 user->contexts = con; 11964 conl = con; 11965 } 11966 } else if (!strcasecmp(v->name, "permit") || 11967 !strcasecmp(v->name, "deny")) { 11968 user->ha = ast_append_ha(v->name, v->value, user->ha, NULL); 11969 } else if (!strcasecmp(v->name, "setvar")) { 11970 varname = ast_strdupa(v->value); 11971 if (varname && (varval = strchr(varname,'='))) { 11972 *varval = '\0'; 11973 varval++; 11974 if((tmpvar = ast_variable_new(varname, varval, ""))) { 11975 tmpvar->next = user->vars; 11976 user->vars = tmpvar; 11977 } 11978 } 11979 } else if (!strcasecmp(v->name, "allow")) { 11980 ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1); 11981 } else if (!strcasecmp(v->name, "disallow")) { 11982 ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0); 11983 } else if (!strcasecmp(v->name, "trunk")) { 11984 ast_set2_flag(user, ast_true(v->value), IAX_TRUNK); 11985 if (ast_test_flag(user, IAX_TRUNK) && !timer) { 11986 ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without a timing interface\n", user->name); 11987 ast_clear_flag(user, IAX_TRUNK); 11988 } 11989 } else if (!strcasecmp(v->name, "auth")) { 11990 user->authmethods = get_auth_methods(v->value); 11991 } else if (!strcasecmp(v->name, "encryption")) { 11992 user->encmethods |= get_encrypt_methods(v->value); 11993 } else if (!strcasecmp(v->name, "transfer")) { 11994 if (!strcasecmp(v->value, "mediaonly")) { 11995 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 11996 } else if (ast_true(v->value)) { 11997 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 11998 } else 11999 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 12000 } else if (!strcasecmp(v->name, "codecpriority")) { 12001 if(!strcasecmp(v->value, "caller")) 12002 ast_set_flag(user, IAX_CODEC_USER_FIRST); 12003 else if(!strcasecmp(v->value, "disabled")) 12004 ast_set_flag(user, IAX_CODEC_NOPREFS); 12005 else if(!strcasecmp(v->value, "reqonly")) { 12006 ast_set_flag(user, IAX_CODEC_NOCAP); 12007 ast_set_flag(user, IAX_CODEC_NOPREFS); 12008 } 12009 } else if (!strcasecmp(v->name, "jitterbuffer")) { 12010 ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF); 12011 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 12012 ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF); 12013 } else if (!strcasecmp(v->name, "dbsecret")) { 12014 ast_string_field_set(user, dbsecret, v->value); 12015 } else if (!strcasecmp(v->name, "secret")) { 12016 if (!ast_strlen_zero(user->secret)) { 12017 char *old = ast_strdupa(user->secret); 12018 12019 ast_string_field_build(user, secret, "%s;%s", old, v->value); 12020 } else 12021 ast_string_field_set(user, secret, v->value); 12022 } else if (!strcasecmp(v->name, "callerid")) { 12023 if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) { 12024 char name2[80]; 12025 char num2[80]; 12026 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 12027 ast_string_field_set(user, cid_name, name2); 12028 ast_string_field_set(user, cid_num, num2); 12029 ast_set_flag(user, IAX_HASCALLERID); 12030 } else { 12031 ast_clear_flag(user, IAX_HASCALLERID); 12032 ast_string_field_set(user, cid_name, ""); 12033 ast_string_field_set(user, cid_num, ""); 12034 } 12035 } else if (!strcasecmp(v->name, "fullname")) { 12036 if (!ast_strlen_zero(v->value)) { 12037 ast_string_field_set(user, cid_name, v->value); 12038 ast_set_flag(user, IAX_HASCALLERID); 12039 } else { 12040 ast_string_field_set(user, cid_name, ""); 12041 if (ast_strlen_zero(user->cid_num)) 12042 ast_clear_flag(user, IAX_HASCALLERID); 12043 } 12044 } else if (!strcasecmp(v->name, "cid_number")) { 12045 if (!ast_strlen_zero(v->value)) { 12046 ast_string_field_set(user, cid_num, v->value); 12047 ast_set_flag(user, IAX_HASCALLERID); 12048 } else { 12049 ast_string_field_set(user, cid_num, ""); 12050 if (ast_strlen_zero(user->cid_name)) 12051 ast_clear_flag(user, IAX_HASCALLERID); 12052 } 12053 } else if (!strcasecmp(v->name, "accountcode")) { 12054 ast_string_field_set(user, accountcode, v->value); 12055 } else if (!strcasecmp(v->name, "mohinterpret")) { 12056 ast_string_field_set(user, mohinterpret, v->value); 12057 } else if (!strcasecmp(v->name, "mohsuggest")) { 12058 ast_string_field_set(user, mohsuggest, v->value); 12059 } else if (!strcasecmp(v->name, "parkinglot")) { 12060 ast_string_field_set(user, parkinglot, v->value); 12061 } else if (!strcasecmp(v->name, "language")) { 12062 ast_string_field_set(user, language, v->value); 12063 } else if (!strcasecmp(v->name, "amaflags")) { 12064 format = ast_cdr_amaflags2int(v->value); 12065 if (format < 0) { 12066 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 12067 } else { 12068 user->amaflags = format; 12069 } 12070 } else if (!strcasecmp(v->name, "inkeys")) { 12071 ast_string_field_set(user, inkeys, v->value); 12072 } else if (!strcasecmp(v->name, "maxauthreq")) { 12073 user->maxauthreq = atoi(v->value); 12074 if (user->maxauthreq < 0) 12075 user->maxauthreq = 0; 12076 } else if (!strcasecmp(v->name, "adsi")) { 12077 user->adsi = ast_true(v->value); 12078 } else if (!strcasecmp(v->name, "requirecalltoken")) { 12079 /* default is required unless in optional ip list */ 12080 if (ast_false(v->value)) { 12081 user->calltoken_required = CALLTOKEN_NO; 12082 } else if (!strcasecmp(v->value, "auto")) { 12083 user->calltoken_required = CALLTOKEN_AUTO; 12084 } else if (ast_true(v->value)) { 12085 user->calltoken_required = CALLTOKEN_YES; 12086 } else { 12087 ast_log(LOG_WARNING, "requirecalltoken must be set to a valid value. at line %d\n", v->lineno); 12088 } 12089 } /* else if (strcasecmp(v->name,"type")) */ 12090 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 12091 v = v->next; 12092 if (!v) { 12093 v = alt; 12094 alt = NULL; 12095 } 12096 } 12097 if (!user->authmethods) { 12098 if (!ast_strlen_zero(user->secret)) { 12099 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 12100 if (!ast_strlen_zero(user->inkeys)) 12101 user->authmethods |= IAX_AUTH_RSA; 12102 } else if (!ast_strlen_zero(user->inkeys)) { 12103 user->authmethods = IAX_AUTH_RSA; 12104 } else { 12105 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 12106 } 12107 } 12108 ast_clear_flag(user, IAX_DELME); 12109 } 12110 cleanup: 12111 if (oldha) 12112 ast_free_ha(oldha); 12113 if (oldcon) 12114 free_context(oldcon); 12115 return user; 12116 }
| static int cache_get_callno_locked | ( | const char * | data | ) | [static] |
Definition at line 12688 of file chan_iax2.c.
References add_empty_calltoken_ie(), ARRAY_LEN, ast_debug, AST_FRAME_IAX, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), iax_ie_data::buf, chan_iax2_pvt::capability, parsed_dial_string::context, create_addr(), parsed_dial_string::exten, find_callno_locked(), IAX_CAPABILITY_FULLBANDWIDTH, IAX_COMMAND_NEW, iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CAPABILITY, IAX_IE_FORMAT, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, parsed_dial_string::key, LOG_WARNING, NEW_FORCE, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, iax_ie_data::pos, secret, send_command(), create_addr_info::sockfd, and parsed_dial_string::username.
Referenced by find_cache().
12689 { 12690 struct sockaddr_in sin; 12691 int x; 12692 int callno; 12693 struct iax_ie_data ied; 12694 struct create_addr_info cai; 12695 struct parsed_dial_string pds; 12696 char *tmpstr; 12697 12698 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 12699 /* Look for an *exact match* call. Once a call is negotiated, it can only 12700 look up entries for a single context */ 12701 if (!ast_mutex_trylock(&iaxsl[x])) { 12702 if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot)) 12703 return x; 12704 ast_mutex_unlock(&iaxsl[x]); 12705 } 12706 } 12707 12708 /* No match found, we need to create a new one */ 12709 12710 memset(&cai, 0, sizeof(cai)); 12711 memset(&ied, 0, sizeof(ied)); 12712 memset(&pds, 0, sizeof(pds)); 12713 12714 tmpstr = ast_strdupa(data); 12715 parse_dial_string(tmpstr, &pds); 12716 12717 if (ast_strlen_zero(pds.peer)) { 12718 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data); 12719 return -1; 12720 } 12721 12722 /* Populate our address from the given */ 12723 if (create_addr(pds.peer, NULL, &sin, &cai)) 12724 return -1; 12725 12726 ast_debug(1, "peer: %s, username: %s, password: %s, context: %s\n", 12727 pds.peer, pds.username, pds.password, pds.context); 12728 12729 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 12730 if (callno < 1) { 12731 ast_log(LOG_WARNING, "Unable to create call\n"); 12732 return -1; 12733 } 12734 12735 ast_string_field_set(iaxs[callno], dproot, data); 12736 iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH; 12737 12738 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 12739 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD"); 12740 /* the string format is slightly different from a standard dial string, 12741 because the context appears in the 'exten' position 12742 */ 12743 if (pds.exten) 12744 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten); 12745 if (pds.username) 12746 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 12747 iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH); 12748 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH); 12749 /* Keep password handy */ 12750 if (pds.password) 12751 ast_string_field_set(iaxs[callno], secret, pds.password); 12752 if (pds.key) 12753 ast_string_field_set(iaxs[callno], outkey, pds.key); 12754 /* Start the call going */ 12755 add_empty_calltoken_ie(iaxs[callno], &ied); /* this _MUST_ be the last ie added */ 12756 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 12757 12758 return callno; 12759 }
| static unsigned int calc_rxstamp | ( | struct chan_iax2_pvt * | p, | |
| unsigned int | offset | |||
| ) | [static] |
Definition at line 5531 of file chan_iax2.c.
References ast_debug, ast_random(), ast_samp2tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), chan_iax2_pvt::callno, and chan_iax2_pvt::rxcore.
Referenced by schedule_delivery().
05532 { 05533 /* Returns where in "receive time" we are. That is, how many ms 05534 since we received (or would have received) the frame with timestamp 0 */ 05535 int ms; 05536 #ifdef IAXTESTS 05537 int jit; 05538 #endif /* IAXTESTS */ 05539 /* Setup rxcore if necessary */ 05540 if (ast_tvzero(p->rxcore)) { 05541 p->rxcore = ast_tvnow(); 05542 if (iaxdebug) 05543 ast_debug(1, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n", 05544 p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset); 05545 p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000)); 05546 #if 1 05547 if (iaxdebug) 05548 ast_debug(1, "calc_rxstamp: call=%d: works out as %d.%6.6d\n", 05549 p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec)); 05550 #endif 05551 } 05552 05553 ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore); 05554 #ifdef IAXTESTS 05555 if (test_jit) { 05556 if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) { 05557 jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0)); 05558 if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0))) 05559 jit = -jit; 05560 ms += jit; 05561 } 05562 } 05563 if (test_late) { 05564 ms += test_late; 05565 test_late = 0; 05566 } 05567 #endif /* IAXTESTS */ 05568 return ms; 05569 }
| static unsigned int calc_timestamp | ( | struct chan_iax2_pvt * | p, | |
| unsigned int | ts, | |||
| struct ast_frame * | f | |||
| ) | [static] |
Definition at line 5398 of file chan_iax2.c.
References ast_debug, ast_format_rate(), AST_FRAME_CNG, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_samp2tv(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), chan_iax2_pvt::callno, ast_frame::delivery, ast_frame::frametype, iax2_trunk_peer::lastsent, chan_iax2_pvt::lastsent, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, chan_iax2_pvt::offset, chan_iax2_pvt::peercallno, ast_frame::samples, and ast_frame::subclass.
Referenced by iax2_send(), and socket_process().
05399 { 05400 int ms; 05401 int voice = 0; 05402 int genuine = 0; 05403 int adjust; 05404 int rate = ast_format_rate(f->subclass) / 1000; 05405 struct timeval *delivery = NULL; 05406 05407 05408 /* What sort of frame do we have?: voice is self-explanatory 05409 "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK 05410 non-genuine frames are CONTROL frames [ringing etc], DTMF 05411 The "genuine" distinction is needed because genuine frames must get a clock-based timestamp, 05412 the others need a timestamp slaved to the voice frames so that they go in sequence 05413 */ 05414 if (f) { 05415 if (f->frametype == AST_FRAME_VOICE) { 05416 voice = 1; 05417 delivery = &f->delivery; 05418 } else if (f->frametype == AST_FRAME_IAX) { 05419 genuine = 1; 05420 } else if (f->frametype == AST_FRAME_CNG) { 05421 p->notsilenttx = 0; 05422 } 05423 } 05424 if (ast_tvzero(p->offset)) { 05425 p->offset = ast_tvnow(); 05426 /* Round to nearest 20ms for nice looking traces */ 05427 p->offset.tv_usec -= p->offset.tv_usec % 20000; 05428 } 05429 /* If the timestamp is specified, just send it as is */ 05430 if (ts) 05431 return ts; 05432 /* If we have a time that the frame arrived, always use it to make our timestamp */ 05433 if (delivery && !ast_tvzero(*delivery)) { 05434 ms = ast_tvdiff_ms(*delivery, p->offset); 05435 if (ms < 0) { 05436 ms = 0; 05437 } 05438 if (iaxdebug) 05439 ast_debug(3, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno); 05440 } else { 05441 ms = ast_tvdiff_ms(ast_tvnow(), p->offset); 05442 if (ms < 0) 05443 ms = 0; 05444 if (voice) { 05445 /* On a voice frame, use predicted values if appropriate */ 05446 if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) { 05447 /* Adjust our txcore, keeping voice and non-voice synchronized */ 05448 /* AN EXPLANATION: 05449 When we send voice, we usually send "calculated" timestamps worked out 05450 on the basis of the number of samples sent. When we send other frames, 05451 we usually send timestamps worked out from the real clock. 05452 The problem is that they can tend to drift out of step because the 05453 source channel's clock and our clock may not be exactly at the same rate. 05454 We fix this by continuously "tweaking" p->offset. p->offset is "time zero" 05455 for this call. Moving it adjusts timestamps for non-voice frames. 05456 We make the adjustment in the style of a moving average. Each time we 05457 adjust p->offset by 10% of the difference between our clock-derived 05458 timestamp and the predicted timestamp. That's why you see "10000" 05459 below even though IAX2 timestamps are in milliseconds. 05460 The use of a moving average avoids offset moving too radically. 05461 Generally, "adjust" roams back and forth around 0, with offset hardly 05462 changing at all. But if a consistent different starts to develop it 05463 will be eliminated over the course of 10 frames (200-300msecs) 05464 */ 05465 adjust = (ms - p->nextpred); 05466 if (adjust < 0) 05467 p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000)); 05468 else if (adjust > 0) 05469 p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000)); 05470 05471 if (!p->nextpred) { 05472 p->nextpred = ms; /*f->samples / rate;*/ 05473 if (p->nextpred <= p->lastsent) 05474 p->nextpred = p->lastsent + 3; 05475 } 05476 ms = p->nextpred; 05477 } else { 05478 /* in this case, just use the actual 05479 * time, since we're either way off 05480 * (shouldn't happen), or we're ending a 05481 * silent period -- and seed the next 05482 * predicted time. Also, round ms to the 05483 * next multiple of frame size (so our 05484 * silent periods are multiples of 05485 * frame size too) */ 05486 05487 if (iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW ) 05488 ast_debug(1, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n", 05489 abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW); 05490 05491 if (f->samples >= rate) /* check to make sure we dont core dump */ 05492 { 05493 int diff = ms % (f->samples / rate); 05494 if (diff) 05495 ms += f->samples/rate - diff; 05496 } 05497 05498 p->nextpred = ms; 05499 p->notsilenttx = 1; 05500 } 05501 } else if ( f->frametype == AST_FRAME_VIDEO ) { 05502 /* 05503 * IAX2 draft 03 says that timestamps MUST be in order. 05504 * It does not say anything about several frames having the same timestamp 05505 * When transporting video, we can have a frame that spans multiple iax packets 05506 * (so called slices), so it would make sense to use the same timestamp for all of 05507 * them 05508 * We do want to make sure that frames don't go backwards though 05509 */ 05510 if ( (unsigned int)ms < p->lastsent ) 05511 ms = p->lastsent; 05512 } else { 05513 /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless 05514 it's a genuine frame */ 05515 if (genuine) { 05516 /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */ 05517 if (ms <= p->lastsent) 05518 ms = p->lastsent + 3; 05519 } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) { 05520 /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */ 05521 ms = p->lastsent + 3; 05522 } 05523 } 05524 } 05525 p->lastsent = ms; 05526 if (voice) 05527 p->nextpred = p->nextpred + f->samples / rate; 05528 return ms; 05529 }
| static unsigned int calc_txpeerstamp | ( | struct iax2_trunk_peer * | tpeer, | |
| int | sampms, | |||
| struct timeval * | now | |||
| ) | [static] |
Definition at line 5354 of file chan_iax2.c.
References ast_tvdiff_ms(), ast_tvzero(), iax2_trunk_peer::lastsent, iax2_trunk_peer::lasttxtime, MAX_TIMESTAMP_SKEW, iax2_trunk_peer::trunkact, and iax2_trunk_peer::txtrunktime.
Referenced by send_trunk().
05355 { 05356 unsigned long int mssincetx; /* unsigned to handle overflows */ 05357 long int ms, pred; 05358 05359 tpeer->trunkact = *now; 05360 mssincetx = ast_tvdiff_ms(*now, tpeer->lasttxtime); 05361 if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) { 05362 /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */ 05363 tpeer->txtrunktime = *now; 05364 tpeer->lastsent = 999999; 05365 } 05366 /* Update last transmit time now */ 05367 tpeer->lasttxtime = *now; 05368 05369 /* Calculate ms offset */ 05370 ms = ast_tvdiff_ms(*now, tpeer->txtrunktime); 05371 /* Predict from last value */ 05372 pred = tpeer->lastsent + sampms; 05373 if (abs(ms - pred) < MAX_TIMESTAMP_SKEW) 05374 ms = pred; 05375 05376 /* We never send the same timestamp twice, so fudge a little if we must */ 05377 if (ms == tpeer->lastsent) 05378 ms = tpeer->lastsent + 1; 05379 tpeer->lastsent = ms; 05380 return ms; 05381 }
| static int callno_hash | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 2319 of file chan_iax2.c.
References ast_random().
Referenced by create_callno_pools().
02320 { 02321 return abs(ast_random()); 02322 }
| static int calltoken_required | ( | struct sockaddr_in * | sin, | |
| const char * | name, | |||
| int | subclass | |||
| ) | [static] |
Definition at line 1872 of file chan_iax2.c.
References addr_range_match_address_cb(), ao2_callback, ao2_ref, ast_debug, ast_inet_ntoa(), CALLTOKEN_AUTO, CALLTOKEN_DEFAULT, calltoken_ignores, CALLTOKEN_NO, iax2_peer::calltoken_required, iax2_user::calltoken_required, find_peer(), find_user(), IAX_COMMAND_NEW, peer_unref(), S_OR, and user_unref().
Referenced by handle_call_token().
01873 { 01874 struct addr_range *addr_range; 01875 struct iax2_peer *peer = NULL; 01876 struct iax2_user *user = NULL; 01877 /* if no username is given, check for guest accounts */ 01878 const char *find = S_OR(name, "guest"); 01879 int res = 1; /* required by default */ 01880 int optional = 0; 01881 enum calltoken_peer_enum calltoken_required = CALLTOKEN_DEFAULT; 01882 /* There are only two cases in which calltoken validation is not required. 01883 * Case 1. sin falls within the list of address ranges specified in the calltoken optional table and 01884 * the peer definition has not set the requirecalltoken option. 01885 * Case 2. Username is a valid peer/user, and that peer has requirecalltoken set either auto or no. 01886 */ 01887 01888 /* ----- Case 1 ----- */ 01889 if ((addr_range = ao2_callback(calltoken_ignores, 0, addr_range_match_address_cb, sin))) { 01890 ao2_ref(addr_range, -1); 01891 optional = 1; 01892 } 01893 01894 /* ----- Case 2 ----- */ 01895 if ((subclass == IAX_COMMAND_NEW) && (user = find_user(find))) { 01896 calltoken_required = user->calltoken_required; 01897 } else if ((subclass != IAX_COMMAND_NEW) && (peer = find_peer(find, 1))) { 01898 calltoken_required = peer->calltoken_required; 01899 } 01900 01901 if (peer) { 01902 peer_unref(peer); 01903 } 01904 if (user) { 01905 user_unref(user); 01906 } 01907 01908 ast_debug(1, "Determining if address %s with username %s requires calltoken validation. Optional = %d calltoken_required = %d \n", ast_inet_ntoa(sin->sin_addr), name, optional, calltoken_required); 01909 if (((calltoken_required == CALLTOKEN_NO) || (calltoken_required == CALLTOKEN_AUTO)) || 01910 (optional && (calltoken_required == CALLTOKEN_DEFAULT))) { 01911 res = 0; 01912 } 01913 01914 return res; 01915 }
| static int check_access | ( | int | callno, | |
| struct sockaddr_in * | sin, | |||
| struct iax_ies * | ies | |||
| ) | [static] |
Definition at line 6957 of file chan_iax2.c.
References iax2_user::accountcode, iax2_user::adsi, chan_iax2_pvt::adsi, iax_ies::adsicpe, chan_iax2_pvt::amaflags, iax2_user::amaflags, ao2_iterator_init(), ao2_iterator_next, apply_context(), ast_apply_ha(), ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_inet_ntoa(), ast_log(), AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, ast_set2_flag, ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_variable_new(), iax2_user::authmethods, chan_iax2_pvt::authmethods, chan_iax2_pvt::authrej, iax_ies::called_context, iax_ies::called_number, iax_ies::calling_ani, iax_ies::calling_name, iax_ies::calling_number, chan_iax2_pvt::calling_pres, iax_ies::calling_pres, chan_iax2_pvt::calling_tns, iax_ies::calling_tns, chan_iax2_pvt::calling_ton, iax_ies::calling_ton, iax2_user::capability, chan_iax2_pvt::capability, iax_ies::capability, iax2_user::cid_name, cid_name, iax2_user::cid_num, cid_num, iax_ies::codec_prefs, iax2_context::context, chan_iax2_pvt::context, context, iax2_user::contexts, iax2_user::dbsecret, DEFAULT_CONTEXT, iax_ies::dnid, iax2_user::encmethods, chan_iax2_pvt::encmethods, exten, ast_variable::file, iax_ies::format, iax2_user::ha, iax2_getpeertrunk(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_MAXAUTHREQ, IAX_NOTRANSFER, IAX_PROTO_VERSION, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_user::inkeys, iax2_user::language, iax_ies::language, LOG_WARNING, iax2_user::maxauthreq, iax2_user::mohinterpret, iax2_user::mohsuggest, ast_variable::name, iax2_user::name, ast_variable::next, parkinglot, iax2_user::parkinglot, chan_iax2_pvt::peeradsicpe, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_user::prefs, chan_iax2_pvt::prefs, prefs, iax_ies::rdnis, realtime_user(), secret, iax2_user::secret, user_unref(), iax_ies::username, ast_variable::value, chan_iax2_pvt::vars, iax2_user::vars, iax_ies::version, and version.
Referenced by socket_process().
06958 { 06959 /* Start pessimistic */ 06960 int res = -1; 06961 int version = 2; 06962 struct iax2_user *user = NULL, *best = NULL; 06963 int bestscore = 0; 06964 int gotcapability = 0; 06965 struct ast_variable *v = NULL, *tmpvar = NULL; 06966 struct ao2_iterator i; 06967 06968 if (!iaxs[callno]) 06969 return res; 06970 if (ies->called_number) 06971 ast_string_field_set(iaxs[callno], exten, ies->called_number); 06972 if (ies->calling_number) { 06973 ast_shrink_phone_number(ies->calling_number); 06974 ast_string_field_set(iaxs[callno], cid_num, ies->calling_number); 06975 } 06976 if (ies->calling_name) 06977 ast_string_field_set(iaxs[callno], cid_name, ies->calling_name); 06978 if (ies->calling_ani) 06979 ast_string_field_set(iaxs[callno], ani, ies->calling_ani); 06980 if (ies->dnid) 06981 ast_string_field_set(iaxs[callno], dnid, ies->dnid); 06982 if (ies->rdnis) 06983 ast_string_field_set(iaxs[callno], rdnis, ies->rdnis); 06984 if (ies->called_context) 06985 ast_string_field_set(iaxs[callno], context, ies->called_context); 06986 if (ies->language) 06987 ast_string_field_set(iaxs[callno], language, ies->language); 06988 if (ies->username) 06989 ast_string_field_set(iaxs[callno], username, ies->username); 06990 if (ies->calling_ton > -1) 06991 iaxs[callno]->calling_ton = ies->calling_ton; 06992 if (ies->calling_tns > -1) 06993 iaxs[callno]->calling_tns = ies->calling_tns; 06994 if (ies->calling_pres > -1) 06995 iaxs[callno]->calling_pres = ies->calling_pres; 06996 if (ies->format) 06997 iaxs[callno]->peerformat = ies->format; 06998 if (ies->adsicpe) 06999 iaxs[callno]->peeradsicpe = ies->adsicpe; 07000 if (ies->capability) { 07001 gotcapability = 1; 07002 iaxs[callno]->peercapability = ies->capability; 07003 } 07004 if (ies->version) 07005 version = ies->version; 07006 07007 /* Use provided preferences until told otherwise for actual preferences */ 07008 if(ies->codec_prefs) { 07009 ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0); 07010 ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0); 07011 } 07012 07013 if (!gotcapability) 07014 iaxs[callno]->peercapability = iaxs[callno]->peerformat; 07015 if (version > IAX_PROTO_VERSION) { 07016 ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 07017 ast_inet_ntoa(sin->sin_addr), version); 07018 return res; 07019 } 07020 /* Search the userlist for a compatible entry, and fill in the rest */ 07021 i = ao2_iterator_init(users, 0); 07022 while ((user = ao2_iterator_next(&i))) { 07023 if ((ast_strlen_zero(iaxs[callno]->username) || /* No username specified */ 07024 !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */ 07025 && ast_apply_ha(user->ha, sin) /* Access is permitted from this IP */ 07026 && (ast_strlen_zero(iaxs[callno]->context) || /* No context specified */ 07027 apply_context(user->contexts, iaxs[callno]->context))) { /* Context is permitted */ 07028 if (!ast_strlen_zero(iaxs[callno]->username)) { 07029 /* Exact match, stop right now. */ 07030 if (best) 07031 user_unref(best); 07032 best = user; 07033 break; 07034 } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) { 07035 /* No required authentication */ 07036 if (user->ha) { 07037 /* There was host authentication and we passed, bonus! */ 07038 if (bestscore < 4) { 07039 bestscore = 4; 07040 if (best) 07041 user_unref(best); 07042 best = user; 07043 continue; 07044 } 07045 } else { 07046 /* No host access, but no secret, either, not bad */ 07047 if (bestscore < 3) { 07048 bestscore = 3; 07049 if (best) 07050 user_unref(best); 07051 best = user; 07052 continue; 07053 } 07054 } 07055 } else { 07056 if (user->ha) { 07057 /* Authentication, but host access too, eh, it's something.. */ 07058 if (bestscore < 2) { 07059 bestscore = 2; 07060 if (best) 07061 user_unref(best); 07062 best = user; 07063 continue; 07064 } 07065 } else { 07066 /* Authentication and no host access... This is our baseline */ 07067 if (bestscore < 1) { 07068 bestscore = 1; 07069 if (best) 07070 user_unref(best); 07071 best = user; 07072 continue; 07073 } 07074 } 07075 } 07076 } 07077 user_unref(user); 07078 } 07079 user = best; 07080 if (!user && !ast_strlen_zero(iaxs[callno]->username)) { 07081 user = realtime_user(iaxs[callno]->username, sin); 07082 if (user && !ast_strlen_zero(iaxs[callno]->context) && /* No context specified */ 07083 !apply_context(user->contexts, iaxs[callno]->context)) { /* Context is permitted */ 07084 user = user_unref(user); 07085 } 07086 } 07087 if (user) { 07088 /* We found our match (use the first) */ 07089 /* copy vars */ 07090 for (v = user->vars ; v ; v = v->next) { 07091 if((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 07092 tmpvar->next = iaxs[callno]->vars; 07093 iaxs[callno]->vars = tmpvar; 07094 } 07095 } 07096 /* If a max AUTHREQ restriction is in place, activate it */ 07097 if (user->maxauthreq > 0) 07098 ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ); 07099 iaxs[callno]->prefs = user->prefs; 07100 ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST); 07101 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS); 07102 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP); 07103 iaxs[callno]->encmethods = user->encmethods; 07104 /* Store the requested username if not specified */ 07105 if (ast_strlen_zero(iaxs[callno]->username)) 07106 ast_string_field_set(iaxs[callno], username, user->name); 07107 /* Store whether this is a trunked call, too, of course, and move if appropriate */ 07108 ast_copy_flags(iaxs[callno], user, IAX_TRUNK); 07109 iaxs[callno]->capability = user->capability; 07110 /* And use the default context */ 07111 if (ast_strlen_zero(iaxs[callno]->context)) { 07112 if (user->contexts) 07113 ast_string_field_set(iaxs[callno], context, user->contexts->context); 07114 else 07115 ast_string_field_set(iaxs[callno], context, DEFAULT_CONTEXT); 07116 } 07117 /* And any input keys */ 07118 ast_string_field_set(iaxs[callno], inkeys, user->inkeys); 07119 /* And the permitted authentication methods */ 07120 iaxs[callno]->authmethods = user->authmethods; 07121 iaxs[callno]->adsi = user->adsi; 07122 /* If the user has callerid, override the remote caller id. */ 07123 if (ast_test_flag(user, IAX_HASCALLERID)) { 07124 iaxs[callno]->calling_tns = 0; 07125 iaxs[callno]->calling_ton = 0; 07126 ast_string_field_set(iaxs[callno], cid_num, user->cid_num); 07127 ast_string_field_set(iaxs[callno], cid_name, user->cid_name); 07128 ast_string_field_set(iaxs[callno], ani, user->cid_num); 07129 iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 07130 } else if (ast_strlen_zero(iaxs[callno]->cid_num) && ast_strlen_zero(iaxs[callno]->cid_name)) { 07131 iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE; 07132 } /* else user is allowed to set their own CID settings */ 07133 if (!ast_strlen_zero(user->accountcode)) 07134 ast_string_field_set(iaxs[callno], accountcode, user->accountcode); 07135 if (!ast_strlen_zero(user->mohinterpret)) 07136 ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret); 07137 if (!ast_strlen_zero(user->mohsuggest)) 07138 ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest); 07139 if (!ast_strlen_zero(user->parkinglot)) 07140 ast_string_field_set(iaxs[callno], parkinglot, user->parkinglot); 07141 if (user->amaflags) 07142 iaxs[callno]->amaflags = user->amaflags; 07143 if (!ast_strlen_zero(user->language)) 07144 ast_string_field_set(iaxs[callno], language, user->language); 07145 ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 07146 /* Keep this check last */ 07147 if (!ast_strlen_zero(user->dbsecret)) { 07148 char *family, *key=NULL; 07149 char buf[80]; 07150 family = ast_strdupa(user->dbsecret); 07151 key = strchr(family, '/'); 07152 if (key) { 07153 *key = '\0'; 07154 key++; 07155 } 07156 if (!key || ast_db_get(family, key, buf, sizeof(buf))) 07157 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret); 07158 else 07159 ast_string_field_set(iaxs[callno], secret, buf); 07160 } else 07161 ast_string_field_set(iaxs[callno], secret, user->secret); 07162 res = 0; 07163 user = user_unref(user); 07164 } else { 07165 /* user was not found, but we should still fake an AUTHREQ. 07166 * Set authmethods to the last known authmethod used by the system 07167 * Set a fake secret, it's not looked at, just required to attempt authentication. 07168 * Set authrej so the AUTHREP is rejected without even looking at its contents */ 07169 iaxs[callno]->authmethods = last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT); 07170 ast_string_field_set(iaxs[callno], secret, "badsecret"); 07171 iaxs[callno]->authrej = 1; 07172 if (!ast_strlen_zero(iaxs[callno]->username)) { 07173 /* only send the AUTHREQ if a username was specified. */ 07174 res = 0; 07175 } 07176 } 07177 ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK); 07178 return res; 07179 }
| static int check_provisioning | ( | struct sockaddr_in * | sin, | |
| int | sockfd, | |||
| char * | si, | |||
| unsigned int | ver | |||
| ) | [static] |
Definition at line 8739 of file chan_iax2.c.
References ast_debug, iax2_provision(), and iax_provision_version().
Referenced by socket_process().
08740 { 08741 unsigned int ourver; 08742 char rsi[80]; 08743 snprintf(rsi, sizeof(rsi), "si-%s", si); 08744 if (iax_provision_version(&ourver, rsi, 1)) 08745 return 0; 08746 ast_debug(1, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver); 08747 if (ourver != ver) 08748 iax2_provision(sin, sockfd, NULL, rsi, 1); 08749 return 0; 08750 }
| static int check_srcaddr | ( | struct sockaddr * | sa, | |
| socklen_t | salen | |||
| ) | [static] |
Check if address can be used as packet source.
Definition at line 11506 of file chan_iax2.c.
References ast_debug, ast_log(), errno, and LOG_ERROR.
Referenced by peer_set_srcaddr().
11507 { 11508 int sd; 11509 int res; 11510 11511 sd = socket(AF_INET, SOCK_DGRAM, 0); 11512 if (sd < 0) { 11513 ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno)); 11514 return -1; 11515 } 11516 11517 res = bind(sd, sa, salen); 11518 if (res < 0) { 11519 ast_debug(1, "Can't bind: %s\n", strerror(errno)); 11520 close(sd); 11521 return 1; 11522 } 11523 11524 close(sd); 11525 return 0; 11526 }
| static int complete_dpreply | ( | struct chan_iax2_pvt * | pvt, | |
| struct iax_ies * | ies | |||
| ) | [static] |
Definition at line 7724 of file chan_iax2.c.
References ARRAY_LEN, ast_copy_string(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_UNKNOWN, iax_ies::called_number, iax2_dpcache::callno, iax_ies::dpstatus, iax2_dpcache::expiry, iax2_dpcache::exten, exten, iax2_dpcache::flags, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, matchmore(), iax2_dpcache::orig, iax2_dpcache::peer_list, iax_ies::refresh, status, and iax2_dpcache::waiters.
Referenced by socket_process().
07725 { 07726 char exten[256] = ""; 07727 int status = CACHE_FLAG_UNKNOWN, expiry = iaxdefaultdpcache, x, matchmore = 0; 07728 struct iax2_dpcache *dp = NULL; 07729 07730 if (ies->called_number) 07731 ast_copy_string(exten, ies->called_number, sizeof(exten)); 07732 07733 if (ies->dpstatus & IAX_DPSTATUS_EXISTS) 07734 status = CACHE_FLAG_EXISTS; 07735 else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST) 07736 status = CACHE_FLAG_CANEXIST; 07737 else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT) 07738 status = CACHE_FLAG_NONEXISTENT; 07739 07740 if (ies->refresh) 07741 expiry = ies->refresh; 07742 if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE) 07743 matchmore = CACHE_FLAG_MATCHMORE; 07744 07745 AST_LIST_LOCK(&dpcache); 07746 AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, peer_list) { 07747 if (strcmp(dp->exten, exten)) 07748 continue; 07749 AST_LIST_REMOVE_CURRENT(peer_list); 07750 dp->callno = 0; 07751 dp->expiry.tv_sec = dp->orig.tv_sec + expiry; 07752 if (dp->flags & CACHE_FLAG_PENDING) { 07753 dp->flags &= ~CACHE_FLAG_PENDING; 07754 dp->flags |= status; 07755 dp->flags |= matchmore; 07756 } 07757 /* Wake up waiters */ 07758 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 07759 if (dp->waiters[x] > -1) { 07760 if (write(dp->waiters[x], "asdf", 4) < 0) { 07761 } 07762 } 07763 } 07764 } 07765 AST_LIST_TRAVERSE_SAFE_END; 07766 AST_LIST_UNLOCK(&dpcache); 07767 07768 return 0; 07769 }
| static char * complete_iax2_peers | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 3476 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, ast_strdup, iax2_peer::name, and peer_unref().
Referenced by handle_cli_iax2_prune_realtime(), handle_cli_iax2_set_debug(), and handle_cli_iax2_show_peer().
03477 { 03478 int which = 0; 03479 struct iax2_peer *peer; 03480 char *res = NULL; 03481 int wordlen = strlen(word); 03482 struct ao2_iterator i; 03483 03484 i = ao2_iterator_init(peers, 0); 03485 while ((peer = ao2_iterator_next(&i))) { 03486 if (!strncasecmp(peer->name, word, wordlen) && ++which > state) { 03487 res = ast_strdup(peer->name); 03488 peer_unref(peer); 03489 break; 03490 } 03491 peer_unref(peer); 03492 } 03493 03494 return res; 03495 }
| static char * complete_iax2_unregister | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 6385 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, ast_strdup, iax2_peer::expire, iax2_peer::name, and peer_unref().
Referenced by handle_cli_iax2_unregister().
06386 { 06387 int which = 0; 06388 struct iax2_peer *p = NULL; 06389 char *res = NULL; 06390 int wordlen = strlen(word); 06391 06392 /* 0 - iax2; 1 - unregister; 2 - <peername> */ 06393 if (pos == 2) { 06394 struct ao2_iterator i = ao2_iterator_init(peers, 0); 06395 while ((p = ao2_iterator_next(&i))) { 06396 if (!strncasecmp(p->name, word, wordlen) && 06397 ++which > state && p->expire > 0) { 06398 res = ast_strdup(p->name); 06399 peer_unref(p); 06400 break; 06401 } 06402 peer_unref(p); 06403 } 06404 } 06405 06406 return res; 06407 }
| static int complete_transfer | ( | int | callno, | |
| struct iax_ies * | ies | |||
| ) | [static] |
Definition at line 7771 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::aseqno, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), iax_frame::callno, iax_ies::callno, jb_frame::data, DEFAULT_RETRY_TIME, iax2_frame_free(), chan_iax2_pvt::iseqno, chan_iax2_pvt::jb, jb_getall(), JB_OK, jb_reset(), chan_iax2_pvt::lag, chan_iax2_pvt::last, chan_iax2_pvt::lastsent, LOG_WARNING, chan_iax2_pvt::nextpred, chan_iax2_pvt::offset, chan_iax2_pvt::oseqno, chan_iax2_pvt::peercallno, peercnt_add(), peercnt_remove_by_addr(), chan_iax2_pvt::pingtime, remove_by_peercallno(), remove_by_transfercallno(), iax_frame::retries, chan_iax2_pvt::rseqno, chan_iax2_pvt::rxcore, store_by_peercallno(), chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, TRANSFER_NONE, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, chan_iax2_pvt::videoformat, and chan_iax2_pvt::voiceformat.
Referenced by socket_process().
07772 { 07773 int peercallno = 0; 07774 struct chan_iax2_pvt *pvt = iaxs[callno]; 07775 struct iax_frame *cur; 07776 jb_frame frame; 07777 07778 if (ies->callno) 07779 peercallno = ies->callno; 07780 07781 if (peercallno < 1) { 07782 ast_log(LOG_WARNING, "Invalid transfer request\n"); 07783 return -1; 07784 } 07785 remove_by_transfercallno(pvt); 07786 /* since a transfer has taken place, the address will change. 07787 * This must be accounted for in the peercnts table. Remove 07788 * the old address and add the new one */ 07789 peercnt_remove_by_addr(&pvt->addr); 07790 peercnt_add(&pvt->transfer); 07791 /* now copy over the new address */ 07792 memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr)); 07793 memset(&pvt->transfer, 0, sizeof(pvt->transfer)); 07794 /* Reset sequence numbers */ 07795 pvt->oseqno = 0; 07796 pvt->rseqno = 0; 07797 pvt->iseqno = 0; 07798 pvt->aseqno = 0; 07799 07800 if (pvt->peercallno) { 07801 remove_by_peercallno(pvt); 07802 } 07803 pvt->peercallno = peercallno; 07804 /*this is where the transfering call swiches hash tables */ 07805 store_by_peercallno(pvt); 07806 pvt->transferring = TRANSFER_NONE; 07807 pvt->svoiceformat = -1; 07808 pvt->voiceformat = 0; 07809 pvt->svideoformat = -1; 07810 pvt->videoformat = 0; 07811 pvt->transfercallno = -1; 07812 memset(&pvt->rxcore, 0, sizeof(pvt->rxcore)); 07813 memset(&pvt->offset, 0, sizeof(pvt->offset)); 07814 /* reset jitterbuffer */ 07815 while(jb_getall(pvt->jb,&frame) == JB_OK) 07816 iax2_frame_free(frame.data); 07817 jb_reset(pvt->jb); 07818 pvt->lag = 0; 07819 pvt->last = 0; 07820 pvt->lastsent = 0; 07821 pvt->nextpred = 0; 07822 pvt->pingtime = DEFAULT_RETRY_TIME; 07823 AST_LIST_LOCK(&frame_queue); 07824 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 07825 /* We must cancel any packets that would have been transmitted 07826 because now we're talking to someone new. It's okay, they 07827 were transmitted to someone that didn't care anyway. */ 07828 if (callno == cur->callno) 07829 cur->retries = -1; 07830 } 07831 AST_LIST_UNLOCK(&frame_queue); 07832 return 0; 07833 }
| static unsigned char compress_subclass | ( | int | subclass | ) | [static] |
Definition at line 1359 of file chan_iax2.c.
References ast_log(), IAX_FLAG_SC_LOG, IAX_MAX_SHIFT, and LOG_WARNING.
Referenced by iax2_send(), raw_hangup(), and send_apathetic_reply().
01360 { 01361 int x; 01362 int power=-1; 01363 /* If it's 128 or smaller, just return it */ 01364 if (subclass < IAX_FLAG_SC_LOG) 01365 return subclass; 01366 /* Otherwise find its power */ 01367 for (x = 0; x < IAX_MAX_SHIFT; x++) { 01368 if (subclass & (1 << x)) { 01369 if (power > -1) { 01370 ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass); 01371 return 0; 01372 } else 01373 power = x; 01374 } 01375 } 01376 return power | IAX_FLAG_SC_LOG; 01377 }
| static void construct_rr | ( | struct chan_iax2_pvt * | pvt, | |
| struct iax_ie_data * | iep | |||
| ) | [static] |
Definition at line 8752 of file chan_iax2.c.
References jb_info::current, jb_info::frames_dropped, jb_info::frames_in, jb_info::frames_lost, jb_info::frames_ooo, iax_ie_append_int(), iax_ie_append_short(), IAX_IE_RR_DELAY, IAX_IE_RR_DROPPED, IAX_IE_RR_JITTER, IAX_IE_RR_LOSS, IAX_IE_RR_OOO, IAX_IE_RR_PKTS, chan_iax2_pvt::jb, jb_getinfo(), jb_info::jitter, jb_info::losspct, and jb_info::min.
Referenced by socket_process().
08753 { 08754 jb_info stats; 08755 jb_getinfo(pvt->jb, &stats); 08756 08757 memset(iep, 0, sizeof(*iep)); 08758 08759 iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter); 08760 if(stats.frames_in == 0) stats.frames_in = 1; 08761 iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff))); 08762 iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in); 08763 iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min); 08764 iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped); 08765 iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo); 08766 }
| static int create_addr | ( | const char * | peername, | |
| struct ast_channel * | c, | |||
| struct sockaddr_in * | sin, | |||
| struct create_addr_info * | cai | |||
| ) | [static] |
Definition at line 4164 of file chan_iax2.c.
References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ast_clear_flag, ast_codec_pref_convert(), ast_codec_pref_prepend(), ast_copy_flags, ast_copy_string(), ast_db_get(), ast_debug, ast_get_ip_or_srv(), ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::capability, create_addr_info::capability, iax2_peer::context, create_addr_info::context, iax2_peer::dbsecret, iax2_peer::defaddr, iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_peer::lastms, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, iax2_peer::mohinterpret, create_addr_info::mohinterpret, iax2_peer::mohsuggest, create_addr_info::mohsuggest, ast_channel::nativeformats, iax2_peer::outkey, create_addr_info::outkey, peer_unref(), iax2_peer::peercontext, create_addr_info::peercontext, iax2_peer::prefs, create_addr_info::prefs, prefs, iax2_peer::secret, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, iax2_peer::username, create_addr_info::username, and iax2_peer::zonetag.
Referenced by cache_get_callno_locked(), iax2_call(), iax2_provision(), and iax2_request().
04165 { 04166 struct iax2_peer *peer; 04167 int res = -1; 04168 struct ast_codec_pref ourprefs; 04169 04170 ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK); 04171 cai->sockfd = defaultsockfd; 04172 cai->maxtime = 0; 04173 sin->sin_family = AF_INET; 04174 04175 if (!(peer = find_peer(peername, 1))) { 04176 cai->found = 0; 04177 if (ast_get_ip_or_srv(sin, peername, srvlookup ? "_iax._udp" : NULL)) { 04178 ast_log(LOG_WARNING, "No such host: %s\n", peername); 04179 return -1; 04180 } 04181 sin->sin_port = htons(IAX_DEFAULT_PORTNO); 04182 /* use global iax prefs for unknown peer/user */ 04183 /* But move the calling channel's native codec to the top of the preference list */ 04184 memcpy(&ourprefs, &prefs, sizeof(ourprefs)); 04185 if (c) 04186 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 04187 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 04188 return 0; 04189 } 04190 04191 cai->found = 1; 04192 04193 /* if the peer has no address (current or default), return failure */ 04194 if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) 04195 goto return_unref; 04196 04197 /* if the peer is being monitored and is currently unreachable, return failure */ 04198 if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0))) 04199 goto return_unref; 04200 04201 ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 04202 cai->maxtime = peer->maxms; 04203 cai->capability = peer->capability; 04204 cai->encmethods = peer->encmethods; 04205 cai->sockfd = peer->sockfd; 04206 cai->adsi = peer->adsi; 04207 memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs)); 04208 /* Move the calling channel's native codec to the top of the preference list */ 04209 if (c) { 04210 ast_debug(1, "prepending %x to prefs\n", c->nativeformats); 04211 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 04212 } 04213 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 04214 ast_copy_string(cai->context, peer->context, sizeof(cai->context)); 04215 ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext)); 04216 ast_copy_string(cai->username, peer->username, sizeof(cai->username)); 04217 ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone)); 04218 ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey)); 04219 ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret)); 04220 ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest)); 04221 if (ast_strlen_zero(peer->dbsecret)) { 04222 ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret)); 04223 } else { 04224 char *family; 04225 char *key = NULL; 04226 04227 family = ast_strdupa(peer->dbsecret); 04228 key = strchr(family, '/'); 04229 if (key) 04230 *key++ = '\0'; 04231 if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) { 04232 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret); 04233 goto return_unref; 04234 } 04235 } 04236 04237 if (peer->addr.sin_addr.s_addr) { 04238 sin->sin_addr = peer->addr.sin_addr; 04239 sin->sin_port = peer->addr.sin_port; 04240 } else { 04241 sin->sin_addr = peer->defaddr.sin_addr; 04242 sin->sin_port = peer->defaddr.sin_port; 04243 } 04244 04245 res = 0; 04246 04247 return_unref: 04248 peer_unref(peer); 04249 04250 return res; 04251 }
| static int create_callno_pools | ( | void | ) | [static] |
Definition at line 2324 of file chan_iax2.c.
References ao2_alloc, ao2_container_alloc, ao2_link, ao2_ref, callno_entry::callno, callno_hash(), IAX_MAX_CALLS, and TRUNK_CALL_START.
Referenced by load_objects().
02325 { 02326 uint16_t i; 02327 02328 if (!(callno_pool = ao2_container_alloc(CALLNO_POOL_BUCKETS, callno_hash, NULL))) { 02329 return -1; 02330 } 02331 02332 if (!(callno_pool_trunk = ao2_container_alloc(CALLNO_POOL_BUCKETS, callno_hash, NULL))) { 02333 return -1; 02334 } 02335 02336 /* start at 2, 0 and 1 are reserved */ 02337 for (i = 2; i <= IAX_MAX_CALLS; i++) { 02338 struct callno_entry *callno_entry; 02339 02340 if (!(callno_entry = ao2_alloc(sizeof(*callno_entry), NULL))) { 02341 return -1; 02342 } 02343 02344 callno_entry->callno = i; 02345 02346 if (i < TRUNK_CALL_START) { 02347 ao2_link(callno_pool, callno_entry); 02348 } else { 02349 ao2_link(callno_pool_trunk, callno_entry); 02350 } 02351 02352 ao2_ref(callno_entry, -1); 02353 } 02354 02355 return 0; 02356 }
| static int decode_frame | ( | ast_aes_decrypt_key * | dcx, | |
| struct ast_iax2_full_hdr * | fh, | |||
| struct ast_frame * | f, | |||
| int * | datalen | |||
| ) | [static] |
Definition at line 5753 of file chan_iax2.c.
References ast_debug, AST_FRAME_VIDEO, ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, ast_frame::frametype, IAX_FLAG_FULL, memcpy_decrypt(), ast_iax2_full_hdr::scallno, ast_frame::subclass, ast_iax2_full_hdr::type, and uncompress_subclass().
Referenced by decrypt_frame(), and update_packet().
05754 { 05755 int padding; 05756 unsigned char *workspace; 05757 05758 workspace = alloca(*datalen); 05759 memset(f, 0, sizeof(*f)); 05760 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 05761 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 05762 if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr)) 05763 return -1; 05764 /* Decrypt */ 05765 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx); 05766 05767 padding = 16 + (workspace[15] & 0x0f); 05768 if (iaxdebug) 05769 ast_debug(1, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]); 05770 if (*datalen < padding + sizeof(struct ast_iax2_full_hdr)) 05771 return -1; 05772 05773 *datalen -= padding; 05774 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 05775 f->frametype = fh->type; 05776 if (f->frametype == AST_FRAME_VIDEO) { 05777 f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 05778 } else { 05779 f->subclass = uncompress_subclass(fh->csub); 05780 } 05781 } else { 05782 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 05783 if (iaxdebug) 05784 ast_debug(1, "Decoding mini with length %d\n", *datalen); 05785 if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr)) 05786 return -1; 05787 /* Decrypt */ 05788 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx); 05789 padding = 16 + (workspace[15] & 0x0f); 05790 if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr)) 05791 return -1; 05792 *datalen -= padding; 05793 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 05794 } 05795 return 0; 05796 }
| static int decrypt_frame | ( | int | callno, | |
| struct ast_iax2_full_hdr * | fh, | |||
| struct ast_frame * | f, | |||
| int * | datalen | |||
| ) | [static] |
Definition at line 5839 of file chan_iax2.c.
References ast_set_flag, ast_strdupa, ast_test_flag, build_encryption_keys(), decode_frame(), IAX_KEYPOPULATED, MD5Final(), MD5Init(), MD5Update(), secret, and strsep().
Referenced by socket_process().
05840 { 05841 int res=-1; 05842 if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) { 05843 /* Search for possible keys, given secrets */ 05844 struct MD5Context md5; 05845 unsigned char digest[16]; 05846 char *tmppw, *stringp; 05847 05848 tmppw = ast_strdupa(iaxs[callno]->secret); 05849 stringp = tmppw; 05850 while ((tmppw = strsep(&stringp, ";"))) { 05851 MD5Init(&md5); 05852 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 05853 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 05854 MD5Final(digest, &md5); 05855 build_encryption_keys(digest, iaxs[callno]); 05856 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 05857 if (!res) { 05858 ast_set_flag(iaxs[callno], IAX_KEYPOPULATED); 05859 break; 05860 } 05861 } 05862 } else 05863 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 05864 return res; 05865 }
| static void defer_full_frame | ( | struct iax2_thread * | from_here, | |
| struct iax2_thread * | to_here | |||
| ) | [static] |
Queue the last read full frame for processing by a certain thread.
If there are already any full frames queued, they are sorted by sequence number.
Definition at line 8899 of file chan_iax2.c.
References ast_calloc, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), iax2_thread::buf, iax2_pkt_buf::buf, iax2_thread::buf_len, iax2_thread::full_frames, iax2_pkt_buf::len, iax2_thread::lock, and ast_iax2_full_hdr::oseqno.
Referenced by socket_read().
08900 { 08901 struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf; 08902 struct ast_iax2_full_hdr *fh, *cur_fh; 08903 08904 if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len))) 08905 return; 08906 08907 pkt_buf->len = from_here->buf_len; 08908 memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len); 08909 08910 fh = (struct ast_iax2_full_hdr *) pkt_buf->buf; 08911 ast_mutex_lock(&to_here->lock); 08912 AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) { 08913 cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf; 08914 if (fh->oseqno < cur_fh->oseqno) { 08915 AST_LIST_INSERT_BEFORE_CURRENT(pkt_buf, entry); 08916 break; 08917 } 08918 } 08919 AST_LIST_TRAVERSE_SAFE_END 08920 08921 if (!cur_pkt_buf) 08922 AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry); 08923 08924 ast_mutex_unlock(&to_here->lock); 08925 }
| static void delete_users | ( | void | ) | [static] |
Definition at line 12136 of file chan_iax2.c.
References ao2_callback, ast_dnsmgr_release(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, iax2_destroy(), peer_delme_cb(), chan_iax2_pvt::reg, and user_delme_cb().
Referenced by __unload_module(), and set_config_destroy().
12137 { 12138 struct iax2_registry *reg; 12139 12140 ao2_callback(users, 0, user_delme_cb, NULL); 12141 12142 AST_LIST_LOCK(®istrations); 12143 while ((reg = AST_LIST_REMOVE_HEAD(®istrations, entry))) { 12144 AST_SCHED_DEL(sched, reg->expire); 12145 if (reg->callno) { 12146 int callno = reg->callno; 12147 ast_mutex_lock(&iaxsl[callno]); 12148 if (iaxs[callno]) { 12149 iaxs[callno]->reg = NULL; 12150 iax2_destroy(callno); 12151 } 12152 ast_mutex_unlock(&iaxsl[callno]); 12153 } 12154 if (reg->dnsmgr) 12155 ast_dnsmgr_release(reg->dnsmgr); 12156 ast_free(reg); 12157 } 12158 AST_LIST_UNLOCK(®istrations); 12159 12160 ao2_callback(peers, 0, peer_delme_cb, NULL); 12161 }
| static void destroy_firmware | ( | struct iax_firmware * | cur | ) | [static] |
Definition at line 2680 of file chan_iax2.c.
References ast_free, ast_iax2_firmware_header::datalen, iax_firmware::fd, and iax_firmware::fwh.
Referenced by reload_firmware().
| static void dp_lookup | ( | int | callno, | |
| const char * | context, | |||
| const char * | callednum, | |||
| const char * | callerid, | |||
| int | skiplock | |||
| ) | [static] |
Definition at line 8600 of file chan_iax2.c.
References ast_canmatch_extension(), ast_exists_extension(), AST_FRAME_IAX, ast_ignore_pattern(), ast_matchmore_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), iax_ie_data::buf, IAX_COMMAND_DPREP, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_NUMBER, IAX_IE_DPSTATUS, IAX_IE_REFRESH, iax_ie_data::pos, and send_command().
Referenced by dp_lookup_thread(), and socket_process().
08601 { 08602 unsigned short dpstatus = 0; 08603 struct iax_ie_data ied1; 08604 int mm; 08605 08606 memset(&ied1, 0, sizeof(ied1)); 08607 mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid); 08608 /* Must be started */ 08609 if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) { 08610 dpstatus = IAX_DPSTATUS_EXISTS; 08611 } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) { 08612 dpstatus = IAX_DPSTATUS_CANEXIST; 08613 } else { 08614 dpstatus = IAX_DPSTATUS_NONEXISTENT; 08615 } 08616 if (ast_ignore_pattern(context, callednum)) 08617 dpstatus |= IAX_DPSTATUS_IGNOREPAT; 08618 if (mm) 08619 dpstatus |= IAX_DPSTATUS_MATCHMORE; 08620 if (!skiplock) 08621 ast_mutex_lock(&iaxsl[callno]); 08622 if (iaxs[callno]) { 08623 iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum); 08624 iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus); 08625 iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache); 08626 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1); 08627 } 08628 if (!skiplock) 08629 ast_mutex_unlock(&iaxsl[callno]); 08630 }
| static void* dp_lookup_thread | ( | void * | data | ) | [static] |
Definition at line 8632 of file chan_iax2.c.
References ast_free, dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, and dp_lookup().
Referenced by spawn_dp_lookup().
| static int encrypt_frame | ( | ast_aes_encrypt_key * | ecx, | |
| struct ast_iax2_full_hdr * | fh, | |||
| unsigned char * | poo, | |||
| int * | datalen | |||
| ) | [static] |
Definition at line 5798 of file chan_iax2.c.
References ast_debug, ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, IAX_FLAG_FULL, memcpy_encrypt(), ast_iax2_full_hdr::scallno, and ast_iax2_full_hdr::type.
Referenced by iax2_send(), and update_packet().
05799 { 05800 int padding; 05801 unsigned char *workspace; 05802 workspace = alloca(*datalen + 32); 05803 if (!workspace) 05804 return -1; 05805 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 05806 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 05807 if (iaxdebug) 05808 ast_debug(1, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen); 05809 padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16); 05810 padding = 16 + (padding & 0xf); 05811 memcpy(workspace, poo, padding); 05812 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 05813 workspace[15] &= 0xf0; 05814 workspace[15] |= (padding & 0xf); 05815 if (iaxdebug) 05816 ast_debug(1, "Encoding full frame %d/%d with length %d + %d padding (15=%02x)\n", fh->type, fh->csub, *datalen, padding, workspace[15]); 05817 *datalen += padding; 05818 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx); 05819 if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr)) 05820 memcpy(poo, workspace + *datalen - 32, 32); 05821 } else { 05822 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 05823 if (iaxdebug) 05824 ast_debug(1, "Encoding mini frame with length %d\n", *datalen); 05825 padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16); 05826 padding = 16 + (padding & 0xf); 05827 memcpy(workspace, poo, padding); 05828 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 05829 workspace[15] &= 0xf0; 05830 workspace[15] |= (padding & 0x0f); 05831 *datalen += padding; 05832 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx); 05833 if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr)) 05834 memcpy(poo, workspace + *datalen - 32, 32); 05835 } 05836 return 0; 05837 }
| static int expire_registry | ( | const void * | data | ) | [static] |
Definition at line 8031 of file chan_iax2.c.
References __expire_registry(), and schedule_action.
Referenced by handle_cli_iax2_prune_realtime(), handle_cli_iax2_unregister(), realtime_peer(), reg_source_db(), and update_registry().
08032 { 08033 #ifdef SCHED_MULTITHREADED 08034 if (schedule_action(__expire_registry, data)) 08035 #endif 08036 __expire_registry(data); 08037 return 0; 08038 }
| static struct iax2_dpcache* find_cache | ( | struct ast_channel * | chan, | |
| const char * | data, | |||
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) | [static, read] |
Definition at line 12761 of file chan_iax2.c.
References ARRAY_LEN, ast_calloc, ast_channel_defer_dtmf(), ast_channel_undefer_dtmf(), ast_copy_string(), ast_free, ast_frfree, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_unlock(), ast_read(), ast_test_flag, ast_tvcmp(), ast_tvnow(), ast_waitfor_nandfds(), CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, cache_get_callno_locked(), iax2_dpcache::callno, errno, iax2_dpcache::expiry, iax2_dpcache::exten, f, iax2_dpcache::flags, iax2_dprequest(), IAX_STATE_STARTED, LOG_WARNING, iax2_dpcache::orig, iax2_dpcache::peercontext, and iax2_dpcache::waiters.
Referenced by iax2_canmatch(), iax2_exec(), iax2_exists(), and iax2_matchmore().
12762 { 12763 struct iax2_dpcache *dp = NULL; 12764 struct timeval now = ast_tvnow(); 12765 int x, com[2], timeout, old = 0, outfd, doabort, callno; 12766 struct ast_channel *c = NULL; 12767 struct ast_frame *f = NULL; 12768 12769 AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, cache_list) { 12770 if (ast_tvcmp(now, dp->expiry) > 0) { 12771 AST_LIST_REMOVE_CURRENT(cache_list); 12772 if ((dp->flags & CACHE_FLAG_PENDING) || dp->callno) 12773 ast_log(LOG_WARNING, "DP still has peer field or pending or callno (flags = %d, peer = blah, callno = %d)\n", dp->flags, dp->callno); 12774 else 12775 ast_free(dp); 12776 continue; 12777 } 12778 if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 12779 break; 12780 } 12781 AST_LIST_TRAVERSE_SAFE_END; 12782 12783 if (!dp) { 12784 /* No matching entry. Create a new one. */ 12785 /* First, can we make a callno? */ 12786 if ((callno = cache_get_callno_locked(data)) < 0) { 12787 ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data); 12788 return NULL; 12789 } 12790 if (!(dp = ast_calloc(1, sizeof(*dp)))) { 12791 ast_mutex_unlock(&iaxsl[callno]); 12792 return NULL; 12793 } 12794 ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext)); 12795 ast_copy_string(dp->exten, exten, sizeof(dp->exten)); 12796 dp->expiry = ast_tvnow(); 12797 dp->orig = dp->expiry; 12798 /* Expires in 30 mins by default */ 12799 dp->expiry.tv_sec += iaxdefaultdpcache; 12800 dp->flags = CACHE_FLAG_PENDING; 12801 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) 12802 dp->waiters[x] = -1; 12803 /* Insert into the lists */ 12804 AST_LIST_INSERT_TAIL(&dpcache, dp, cache_list); 12805 AST_LIST_INSERT_TAIL(&iaxs[callno]->dpentries, dp, peer_list); 12806 /* Send the request if we're already up */ 12807 if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 12808 iax2_dprequest(dp, callno); 12809 ast_mutex_unlock(&iaxsl[callno]); 12810 } 12811 12812 /* By here we must have a dp */ 12813 if (dp->flags & CACHE_FLAG_PENDING) { 12814 /* Okay, here it starts to get nasty. We need a pipe now to wait 12815 for a reply to come back so long as it's pending */ 12816 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 12817 /* Find an empty slot */ 12818 if (dp->waiters[x] < 0) 12819 break; 12820 } 12821 if (x >= ARRAY_LEN(dp->waiters)) { 12822 ast_log(LOG_WARNING, "No more waiter positions available\n"); 12823 return NULL; 12824 } 12825 if (pipe(com)) { 12826 ast_log(LOG_WARNING, "Unable to create pipe for comm\n"); 12827 return NULL; 12828 } 12829 dp->waiters[x] = com[1]; 12830 /* Okay, now we wait */ 12831 timeout = iaxdefaulttimeout * 1000; 12832 /* Temporarily unlock */ 12833 AST_LIST_UNLOCK(&dpcache); 12834 /* Defer any dtmf */ 12835 if (chan) 12836 old = ast_channel_defer_dtmf(chan); 12837 doabort = 0; 12838 while(timeout) { 12839 c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout); 12840 if (outfd > -1) 12841 break; 12842 if (!c) 12843 continue; 12844 if (!(f = ast_read(c))) { 12845 doabort = 1; 12846 break; 12847 } 12848 ast_frfree(f); 12849 } 12850 if (!timeout) { 12851 ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten); 12852 } 12853 AST_LIST_LOCK(&dpcache); 12854 dp->waiters[x] = -1; 12855 close(com[1]); 12856 close(com[0]); 12857 if (doabort) { 12858 /* Don't interpret anything, just abort. Not sure what th epoint 12859 of undeferring dtmf on a hung up channel is but hey whatever */ 12860 if (!old && chan) 12861 ast_channel_undefer_dtmf(chan); 12862 return NULL; 12863 } 12864 if (!(dp->flags & CACHE_FLAG_TIMEOUT)) { 12865 /* Now to do non-independent analysis the results of our wait */ 12866 if (dp->flags & CACHE_FLAG_PENDING) { 12867 /* Still pending... It's a timeout. Wake everybody up. Consider it no longer 12868 pending. Don't let it take as long to timeout. */ 12869 dp->flags &= ~CACHE_FLAG_PENDING; 12870 dp->flags |= CACHE_FLAG_TIMEOUT; 12871 /* Expire after only 60 seconds now. This is designed to help reduce backlog in heavily loaded 12872 systems without leaving it unavailable once the server comes back online */ 12873 dp->expiry.tv_sec = dp->orig.tv_sec + 60; 12874 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 12875 if (dp->waiters[x] > -1) { 12876 if (write(dp->waiters[x], "asdf", 4) < 0) { 12877 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 12878 } 12879 } 12880 } 12881 } 12882 } 12883 /* Our caller will obtain the rest */ 12884 if (!old && chan) 12885 ast_channel_undefer_dtmf(chan); 12886 } 12887 return dp; 12888 }
| static int find_callno | ( | unsigned short | callno, | |
| unsigned short | dcallno, | |||
| struct sockaddr_in * | sin, | |||
| int | new, | |||
| int | sockfd, | |||
| int | full_frame | |||
| ) | [static] |
Definition at line 2580 of file chan_iax2.c.
References __find_callno().
Referenced by iax2_poke_peer(), and socket_process().
02580 { 02581 02582 return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame); 02583 }
| static int find_callno_locked | ( | unsigned short | callno, | |
| unsigned short | dcallno, | |||
| struct sockaddr_in * | sin, | |||
| int | new, | |||
| int | sockfd, | |||
| int | full_frame | |||
| ) | [static] |
Definition at line 2585 of file chan_iax2.c.
References __find_callno().
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_provision(), iax2_request(), and socket_process_meta().
02585 { 02586 02587 return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame); 02588 }
| static struct iax2_thread* find_idle_thread | ( | void | ) | [static, read] |
Definition at line 1171 of file chan_iax2.c.
References ast_atomic_fetchadd_int(), ast_calloc, ast_cond_destroy(), ast_cond_init(), ast_cond_wait(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_detached_background, iax2_thread::cond, iax2_thread::ffinfo, iax2_process_thread(), IAX_THREAD_TYPE_DYNAMIC, iaxdynamicthreadcount, iaxdynamicthreadnum, iaxmaxthreadcount, iax2_thread::init_cond, iax2_thread::init_lock, iax2_thread::lock, thread, iax2_thread::threadid, iax2_thread::threadnum, and iax2_thread::type.
Referenced by __schedule_action(), and socket_read().
01172 { 01173 struct iax2_thread *thread = NULL; 01174 01175 /* Pop the head of the idle list off */ 01176 AST_LIST_LOCK(&idle_list); 01177 thread = AST_LIST_REMOVE_HEAD(&idle_list, list); 01178 AST_LIST_UNLOCK(&idle_list); 01179 01180 /* If we popped a thread off the idle list, just return it */ 01181 if (thread) { 01182 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 01183 return thread; 01184 } 01185 01186 /* Pop the head of the dynamic list off */ 01187 AST_LIST_LOCK(&dynamic_list); 01188 thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list); 01189 AST_LIST_UNLOCK(&dynamic_list); 01190 01191 /* If we popped a thread off the dynamic list, just return it */ 01192 if (thread) { 01193 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 01194 return thread; 01195 } 01196 01197 /* If we can't create a new dynamic thread for any reason, return no thread at all */ 01198 if (iaxdynamicthreadcount >= iaxmaxthreadcount || !(thread = ast_calloc(1, sizeof(*thread)))) 01199 return NULL; 01200 01201 /* Set default values */ 01202 ast_atomic_fetchadd_int(&iaxdynamicthreadcount, 1); 01203 thread->threadnum = ast_atomic_fetchadd_int(&iaxdynamicthreadnum, 1); 01204 thread->type = IAX_THREAD_TYPE_DYNAMIC; 01205 01206 /* Initialize lock and condition */ 01207 ast_mutex_init(&thread->lock); 01208 ast_cond_init(&thread->cond, NULL); 01209 ast_mutex_init(&thread->init_lock); 01210 ast_cond_init(&thread->init_cond, NULL); 01211 ast_mutex_lock(&thread->init_lock); 01212 01213 /* Create thread and send it on it's way */ 01214 if (ast_pthread_create_detached_background(&thread->threadid, NULL, iax2_process_thread, thread)) { 01215 ast_cond_destroy(&thread->cond); 01216 ast_mutex_destroy(&thread->lock); 01217 ast_free(thread); 01218 return NULL; 01219 } 01220 01221 /* this thread is not processing a full frame (since it is idle), 01222 so ensure that the field for the full frame call number is empty */ 01223 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 01224 01225 /* Wait for the thread to be ready before returning it to the caller */ 01226 ast_cond_wait(&thread->init_cond, &thread->init_lock); 01227 01228 /* Done with init_lock */ 01229 ast_mutex_unlock(&thread->init_lock); 01230 01231 return thread; 01232 }
| static struct iax2_peer* find_peer | ( | const char * | name, | |
| int | realtime | |||
| ) | [static, read] |
Definition at line 1437 of file chan_iax2.c.
References ao2_find, iax2_peer::name, OBJ_POINTER, and realtime_peer().
Referenced by calltoken_required(), create_addr(), function_iaxpeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_set_debug(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), iax2_devicestate(), register_verify(), registry_authrequest(), requirecalltoken_mark_auto(), and update_registry().
01438 { 01439 struct iax2_peer *peer = NULL; 01440 struct iax2_peer tmp_peer = { 01441 .name = name, 01442 }; 01443 01444 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 01445 01446 /* Now go for realtime if applicable */ 01447 if(!peer && realtime) 01448 peer = realtime_peer(name, NULL); 01449 01450 return peer; 01451 }
| static struct iax2_trunk_peer* find_tpeer | ( | struct sockaddr_in * | sin, | |
| int | fd | |||
| ) | [static, read] |
Definition at line 5571 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_calloc, ast_debug, ast_inet_ntoa(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_init(), ast_mutex_lock(), ast_tvnow(), inaddrcmp(), iax2_trunk_peer::lastsent, iax2_trunk_peer::lock, iax2_trunk_peer::sockfd, and iax2_trunk_peer::trunkact.
Referenced by iax2_trunk_queue(), and socket_process_meta().
05572 { 05573 struct iax2_trunk_peer *tpeer = NULL; 05574 05575 /* Finds and locks trunk peer */ 05576 AST_LIST_LOCK(&tpeers); 05577 05578 AST_LIST_TRAVERSE(&tpeers, tpeer, list) { 05579 if (!inaddrcmp(&tpeer->addr, sin)) { 05580 ast_mutex_lock(&tpeer->lock); 05581 break; 05582 } 05583 } 05584 05585 if (!tpeer) { 05586 if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) { 05587 ast_mutex_init(&tpeer->lock); 05588 tpeer->lastsent = 9999; 05589 memcpy(&tpeer->addr, sin, sizeof(tpeer->addr)); 05590 tpeer->trunkact = ast_tvnow(); 05591 ast_mutex_lock(&tpeer->lock); 05592 tpeer->sockfd = fd; 05593 #ifdef SO_NO_CHECK 05594 setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 05595 #endif 05596 ast_debug(1, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port)); 05597 AST_LIST_INSERT_TAIL(&tpeers, tpeer, list); 05598 } 05599 } 05600 05601 AST_LIST_UNLOCK(&tpeers); 05602 05603 return tpeer; 05604 }
| static struct iax2_user* find_user | ( | const char * | name | ) | [static, read] |
Definition at line 1465 of file chan_iax2.c.
References ao2_find, iax2_user::name, and OBJ_POINTER.
Referenced by calltoken_required(), handle_cli_iax2_prune_realtime(), and requirecalltoken_mark_auto().
01466 { 01467 struct iax2_user tmp_user = { 01468 .name = name, 01469 }; 01470 01471 return ao2_find(users, &tmp_user, OBJ_POINTER); 01472 }
| static unsigned int fix_peerts | ( | struct timeval * | rxtrunktime, | |
| int | callno, | |||
| unsigned int | ts | |||
| ) | [static] |
Definition at line 5383 of file chan_iax2.c.
References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and chan_iax2_pvt::rxcore.
Referenced by socket_process_meta().
05384 { 05385 long ms; /* NOT unsigned */ 05386 if (ast_tvzero(iaxs[callno]->rxcore)) { 05387 /* Initialize rxcore time if appropriate */ 05388 iaxs[callno]->rxcore = ast_tvnow(); 05389 /* Round to nearest 20ms so traces look pretty */ 05390 iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000; 05391 } 05392 /* Calculate difference between trunk and channel */ 05393 ms = ast_tvdiff_ms(*rxtrunktime, iaxs[callno]->rxcore); 05394 /* Return as the sum of trunk time and the difference between trunk and real time */ 05395 return ms + ts; 05396 }
| static void free_context | ( | struct iax2_context * | con | ) | [static] |
Definition at line 11270 of file chan_iax2.c.
References ast_free, and iax2_context::next.
Referenced by build_user(), and user_destructor().
11271 { 11272 struct iax2_context *conl; 11273 while(con) { 11274 conl = con; 11275 con = con->next; 11276 ast_free(conl); 11277 } 11278 }
| static int function_iaxpeer | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 13011 of file chan_iax2.c.
References iax2_peer::addr, iax2_trunk_peer::addr, ast_codec_pref_index(), ast_copy_string(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strdupa, ast_test_flag, iax2_peer::callno, iax2_peer::capability, iax2_peer::cid_name, iax2_peer::cid_num, iax2_peer::context, iax2_peer::expire, find_peer(), IAX_DYNAMIC, iax2_peer::mailbox, peer_status(), peer_unref(), iax2_peer::prefs, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.
13012 { 13013 struct iax2_peer *peer; 13014 char *peername, *colname; 13015 13016 peername = ast_strdupa(data); 13017 13018 /* if our channel, return the IP address of the endpoint of current channel */ 13019 if (!strcmp(peername,"CURRENTCHANNEL")) { 13020 unsigned short callno; 13021 if (chan->tech != &iax2_tech) 13022 return -1; 13023 callno = PTR_TO_CALLNO(chan->tech_pvt); 13024 ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len); 13025 return 0; 13026 } 13027 13028 if ((colname = strchr(peername, ','))) 13029 *colname++ = '\0'; 13030 else 13031 colname = "ip"; 13032 13033 if (!(peer = find_peer(peername, 1))) 13034 return -1; 13035 13036 if (!strcasecmp(colname, "ip")) { 13037 ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); 13038 } else if (!strcasecmp(colname, "status")) { 13039 peer_status(peer, buf, len); 13040 } else if (!strcasecmp(colname, "mailbox")) { 13041 ast_copy_string(buf, peer->mailbox, len); 13042 } else if (!strcasecmp(colname, "context")) { 13043 ast_copy_string(buf, peer->context, len); 13044 } else if (!strcasecmp(colname, "expire")) { 13045 snprintf(buf, len, "%d", peer->expire); 13046 } else if (!strcasecmp(colname, "dynamic")) { 13047 ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len); 13048 } else if (!strcasecmp(colname, "callerid_name")) { 13049 ast_copy_string(buf, peer->cid_name, len); 13050 } else if (!strcasecmp(colname, "callerid_num")) { 13051 ast_copy_string(buf, peer->cid_num, len); 13052 } else if (!strcasecmp(colname, "codecs")) { 13053 ast_getformatname_multiple(buf, len -1, peer->capability); 13054 } else if (!strncasecmp(colname, "codec[", 6)) { 13055 char *codecnum, *ptr; 13056 int codec = 0; 13057 13058 codecnum = strchr(colname, '['); 13059 *codecnum = '\0'; 13060 codecnum++; 13061 if ((ptr = strchr(codecnum, ']'))) { 13062 *ptr = '\0'; 13063 } 13064 if((codec = ast_codec_pref_index(&peer->prefs, atoi(codecnum)))) { 13065 ast_copy_string(buf, ast_getformatname(codec), len); 13066 } else { 13067 buf[0] = '\0'; 13068 } 13069 } else { 13070 buf[0] = '\0'; 13071 } 13072 13073 peer_unref(peer); 13074 13075 return 0; 13076 }
| static int get_auth_methods | ( | const char * | value | ) | [static] |
Definition at line 11490 of file chan_iax2.c.
References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.
Referenced by build_peer(), and build_user().
11491 { 11492 int methods = 0; 11493 if (strstr(value, "rsa")) 11494 methods |= IAX_AUTH_RSA; 11495 if (strstr(value, "md5")) 11496 methods |= IAX_AUTH_MD5; 11497 if (strstr(value, "plaintext")) 11498 methods |= IAX_AUTH_PLAINTEXT; 11499 return methods; 11500 }
| static int get_encrypt_methods | ( | const char * | s | ) | [static] |
Definition at line 1314 of file chan_iax2.c.
References ast_true(), and IAX_ENCRYPT_AES128.
Referenced by build_peer(), build_user(), and set_config().
01315 { 01316 int e; 01317 if (!strcasecmp(s, "aes128")) 01318 e = IAX_ENCRYPT_AES128; 01319 else if (ast_true(s)) 01320 e = IAX_ENCRYPT_AES128; 01321 else 01322 e = 0; 01323 return e; 01324 }
| static int get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 3782 of file chan_iax2.c.
References __get_from_jb(), and schedule_action.
Referenced by update_jbsched().
03783 { 03784 #ifdef SCHED_MULTITHREADED 03785 if (schedule_action(__get_from_jb, data)) 03786 #endif 03787 __get_from_jb(data); 03788 return 0; 03789 }
| static struct callno_entry * get_unused_callno | ( | int | trunk, | |
| int | validated | |||
| ) | [static, read] |
Definition at line 2257 of file chan_iax2.c.
References ao2_container_count(), ao2_find, ao2_lock(), ao2_unlock(), ast_log(), global_maxcallno_nonval, LOG_WARNING, OBJ_CONTINUE, OBJ_POINTER, OBJ_UNLINK, total_nonval_callno_used, and callno_entry::validated.
Referenced by __find_callno(), and make_trunk().
02258 { 02259 struct callno_entry *callno_entry = NULL; 02260 if ((!ao2_container_count(callno_pool) && !trunk) || (!ao2_container_count(callno_pool_trunk) && trunk)) { 02261 ast_log(LOG_WARNING, "Out of CallNumbers\n"); 02262 /* Minor optimization for the extreme case. */ 02263 return NULL; 02264 } 02265 02266 /* the callno_pool container is locked here primarily to ensure thread 02267 * safety of the total_nonval_callno_used check and increment */ 02268 ao2_lock(callno_pool); 02269 02270 /* only a certain number of nonvalidated call numbers should be allocated. 02271 * If there ever is an attack, this separates the calltoken validating 02272 * users from the non calltoken validating users. */ 02273 if (!validated && (total_nonval_callno_used >= global_maxcallno_nonval)) { 02274 ast_log(LOG_WARNING, "NON-CallToken callnumber limit is reached. Current:%d Max:%d\n", total_nonval_callno_used, global_maxcallno_nonval); 02275 ao2_unlock(callno_pool); 02276 return NULL; 02277 } 02278 02279 /* unlink the object from the container, taking over ownership 02280 * of the reference the container had to the object */ 02281 callno_entry = ao2_find((trunk ? callno_pool_trunk : callno_pool), NULL, OBJ_POINTER | OBJ_UNLINK | OBJ_CONTINUE); 02282 02283 if (callno_entry) { 02284 callno_entry->validated = validated; 02285 if (!validated) { 02286 total_nonval_callno_used++; 02287 } 02288 } 02289 02290 ao2_unlock(callno_pool); 02291 return callno_entry; 02292 }
| static int handle_call_token | ( | struct ast_iax2_full_hdr * | fh, | |
| struct iax_ies * | ies, | |||
| struct sockaddr_in * | sin, | |||
| int | fd | |||
| ) | [static] |
Definition at line 4461 of file chan_iax2.c.
References ast_inet_ntoa(), ast_log(), ast_sha1_hash(), ast_str_alloca, ast_str_buffer, ast_str_set(), iax_ie_data::buf, iax_ies::calltoken, CALLTOKEN_HASH_FORMAT, CALLTOKEN_IE_FORMAT, calltoken_required(), iax_ies::calltokendata, ast_iax2_full_hdr::csub, IAX_COMMAND_CALLTOKEN, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, iax_ie_append_str(), IAX_IE_CALLTOKEN, ast_iax2_full_hdr::iseqno, LOG_ERROR, LOG_WARNING, requirecalltoken_mark_auto(), ast_iax2_full_hdr::scallno, send_apathetic_reply(), ast_iax2_full_hdr::ts, uncompress_subclass(), and iax_ies::username.
Referenced by socket_process().
04463 { 04464 #define CALLTOKEN_HASH_FORMAT "%s%d%u%d" /* address + port + ts + randomcalldata */ 04465 #define CALLTOKEN_IE_FORMAT "%u?%s" /* time + ? + (40 char hash) */ 04466 struct ast_str *buf = ast_str_alloca(256); 04467 time_t t = time(NULL); 04468 char hash[41]; /* 40 char sha1 hash */ 04469 int subclass = uncompress_subclass(fh->csub); 04470 04471 /* ----- Case 1 ----- */ 04472 if (ies->calltoken && !ies->calltokendata) { /* empty calltoken is provided, client supports calltokens */ 04473 struct iax_ie_data ied = { 04474 .buf = { 0 }, 04475 .pos = 0, 04476 }; 04477 04478 /* create the hash with their address data and our timestamp */ 04479 ast_str_set(&buf, 0, CALLTOKEN_HASH_FORMAT, ast_inet_ntoa(sin->sin_addr), sin->sin_port, (unsigned int) t, randomcalltokendata); 04480 ast_sha1_hash(hash, ast_str_buffer(buf)); 04481 04482 ast_str_set(&buf, 0, CALLTOKEN_IE_FORMAT, (unsigned int) t, hash); 04483 iax_ie_append_str(&ied, IAX_IE_CALLTOKEN, ast_str_buffer(buf)); 04484 send_apathetic_reply(1, ntohs(fh->scallno), sin, IAX_COMMAND_CALLTOKEN, ntohl(fh->ts), fh->iseqno + 1, fd, &ied); 04485 04486 return 1; 04487 04488 /* ----- Case 2 ----- */ 04489 } else if (ies->calltoken && ies->calltokendata) { /* calltoken received, check to see if it is valid */ 04490 char *rec_hash = NULL; /* the received hash, make sure it matches with ours. */ 04491 char *rec_ts = NULL; /* received timestamp */ 04492 unsigned int rec_time; /* received time_t */ 04493 04494 /* split the timestamp from the hash data */ 04495 rec_hash = strchr((char *) ies->calltokendata, '?'); 04496 if (rec_hash) { 04497 *rec_hash++ = '\0'; 04498 rec_ts = (char *) ies->calltokendata; 04499 } 04500 04501 /* check that we have valid data before we do any comparisons */ 04502 if (!rec_hash || !rec_ts) { 04503 goto reject; 04504 } else if (sscanf(rec_ts, "%u", &rec_time) != 1) { 04505 goto reject; 04506 } 04507 04508 /* create a hash with their address and the _TOKEN'S_ timestamp */ 04509 ast_str_set(&buf, 0, CALLTOKEN_HASH_FORMAT, ast_inet_ntoa(sin->sin_addr), sin->sin_port, (unsigned int) rec_time, randomcalltokendata); 04510 ast_sha1_hash(hash, ast_str_buffer(buf)); 04511 04512 /* compare hashes and then check timestamp delay */ 04513 if (strcmp(hash, rec_hash)) { 04514 ast_log(LOG_WARNING, "Address %s failed CallToken hash inspection\n", ast_inet_ntoa(sin->sin_addr)); 04515 goto reject; /* received hash does not match ours, reject */ 04516 } else if ((t < rec_time) || ((t - rec_time) >= MAX_CALLTOKEN_DELAY)) { 04517 ast_log(LOG_WARNING, "Too much delay in IAX2 calltoken timestamp from address %s\n", ast_inet_ntoa(sin->sin_addr)); 04518 goto reject; /* too much delay, reject */ 04519 } 04520 04521 /* at this point the call token is valid, returning 0 04522 * will allow socket_process to continue as usual */ 04523 requirecalltoken_mark_auto(ies->username, subclass); 04524 return 0; 04525 04526 /* ----- Case 3 ----- */ 04527 } else { /* calltokens are not supported for this client, how do we respond? */ 04528 if (calltoken_required(sin, ies->username, subclass)) { 04529 ast_log(LOG_ERROR, "Call rejected, CallToken Support required. If unexpected, resolve by placing address %s in the calltokenignore list or setting user %s requirecalltoken=no\n", ast_inet_ntoa(sin->sin_addr), ies->username); 04530 goto reject; 04531 } 04532 return 0; /* calltoken is not required for this addr, so permit it. */ 04533 } 04534 04535 reject: 04536 /* received frame has failed calltoken inspection, send apathetic reject messages */ 04537 if (subclass == IAX_COMMAND_REGREQ || subclass == IAX_COMMAND_REGREL) { 04538 send_apathetic_reply(1, ntohs(fh->scallno), sin, IAX_COMMAND_REGREJ, ntohl(fh->ts), fh->iseqno + 1, fd, NULL); 04539 } else { 04540 send_apathetic_reply(1, ntohs(fh->scallno), sin, IAX_COMMAND_REJECT, ntohl(fh->ts), fh->iseqno + 1, fd, NULL); 04541 } 04542 04543 return 1; 04544 }
| static char* handle_cli_iax2_provision | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 11121 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, iax2_provision(), iax_prov_complete_template(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
11122 { 11123 int force = 0; 11124 int res; 11125 11126 switch (cmd) { 11127 case CLI_INIT: 11128 e->command = "iax2 provision"; 11129 e->usage = 11130 "Usage: iax2 provision <host> <template> [forced]\n" 11131 " Provisions the given peer or IP address using a template\n" 11132 " matching either 'template' or '*' if the template is not\n" 11133 " found. If 'forced' is specified, even empty provisioning\n" 11134 " fields will be provisioned as empty fields.\n"; 11135 return NULL; 11136 case CLI_GENERATE: 11137 if (a->pos == 3) 11138 return iax_prov_complete_template(a->line, a->word, a->pos, a->n); 11139 return NULL; 11140 } 11141 11142 if (a->argc < 4) 11143 return CLI_SHOWUSAGE; 11144 if (a->argc > 4) { 11145 if (!strcasecmp(a->argv[4], "forced")) 11146 force = 1; 11147 else 11148 return CLI_SHOWUSAGE; 11149 } 11150 res = iax2_provision(NULL, -1, a->argv[2], a->argv[3], force); 11151 if (res < 0) 11152 ast_cli(a->fd, "Unable to find peer/address '%s'\n", a->argv[2]); 11153 else if (res < 1) 11154 ast_cli(a->fd, "No template (including wildcard) matching '%s'\n", a->argv[3]); 11155 else 11156 ast_cli(a->fd, "Provisioning '%s' with template '%s'%s\n", a->argv[2], a->argv[3], force ? ", forced" : ""); 11157 return CLI_SUCCESS; 11158 }
| static char* handle_cli_iax2_prune_realtime | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3231 of file chan_iax2.c.
References ao2_unlink, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_set_flag, ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_peers(), expire_registry(), ast_cli_args::fd, find_peer(), find_user(), IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, ast_cli_args::line, ast_cli_args::n, peer_ref(), peer_unref(), ast_cli_args::pos, prune_peers(), prune_users(), ast_cli_entry::usage, user_unref(), and ast_cli_args::word.
03232 { 03233 struct iax2_peer *peer = NULL; 03234 struct iax2_user *user = NULL; 03235 03236 switch (cmd) { 03237 case CLI_INIT: 03238 e->command = "iax2 prune realtime"; 03239 e->usage = 03240 "Usage: iax2 prune realtime [<peername>|all]\n" 03241 " Prunes object(s) from the cache\n"; 03242 return NULL; 03243 case CLI_GENERATE: 03244 if (a->pos == 3) 03245 return complete_iax2_peers(a->line, a->word, a->pos, a->n); 03246 return NULL; 03247 } 03248 if (a->argc != 4) 03249 return CLI_SHOWUSAGE; 03250 if (!strcmp(a->argv[3], "all")) { 03251 prune_users(); 03252 prune_peers(); 03253 ast_cli(a->fd, "Cache flushed successfully.\n"); 03254 return CLI_SUCCESS; 03255 } 03256 peer = find_peer(a->argv[3], 0); 03257 user = find_user(a->argv[3]); 03258 if (peer || user) { 03259 if (peer) { 03260 if (ast_test_flag(peer, IAX_RTCACHEFRIENDS)) { 03261 ast_set_flag(peer, IAX_RTAUTOCLEAR); 03262 expire_registry(peer_ref(peer)); 03263 ast_cli(a->fd, "Peer %s was removed from the cache.\n", a->argv[3]); 03264 } else { 03265 ast_cli(a->fd, "Peer %s is not eligible for this operation.\n", a->argv[3]); 03266 } 03267 peer_unref(peer); 03268 } 03269 if (user) { 03270 if (ast_test_flag(user, IAX_RTCACHEFRIENDS)) { 03271 ast_set_flag(user, IAX_RTAUTOCLEAR); 03272 ast_cli(a->fd, "User %s was removed from the cache.\n", a->argv[3]); 03273 } else { 03274 ast_cli(a->fd, "User %s is not eligible for this operation.\n", a->argv[3]); 03275 } 03276 ao2_unlink(users,user); 03277 user_unref(user); 03278 } 03279 } else { 03280 ast_cli(a->fd, "%s was not found in the cache.\n", a->argv[3]); 03281 } 03282 03283 return CLI_SUCCESS; 03284 }
| static char* handle_cli_iax2_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12665 of file chan_iax2.c.
References CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, reload_config(), and ast_cli_entry::usage.
12666 { 12667 switch (cmd) { 12668 case CLI_INIT: 12669 e->command = "iax2 reload"; 12670 e->usage = 12671 "Usage: iax2 reload\n" 12672 " Reloads IAX configuration from iax.conf\n"; 12673 return NULL; 12674 case CLI_GENERATE: 12675 return NULL; 12676 } 12677 12678 reload_config(); 12679 12680 return CLI_SUCCESS; 12681 }
| static char* handle_cli_iax2_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6763 of file chan_iax2.c.
References iax2_peer::addr, ao2_ref, ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_inet_ntoa(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_peers(), debugaddr, ast_cli_args::fd, find_peer(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
06764 { 06765 switch (cmd) { 06766 case CLI_INIT: 06767 e->command = "iax2 set debug {on|off|peer}"; 06768 e->usage = 06769 "Usage: iax2 set debug {on|off|peer peername}\n" 06770 " Enables/Disables dumping of IAX packets for debugging purposes.\n"; 06771 return NULL; 06772 case CLI_GENERATE: 06773 if (a->pos == 4) 06774 return complete_iax2_peers(a->line, a->word, a->pos, a->n); 06775 return NULL; 06776 } 06777 06778 if (a->argc < e->args || a->argc > e->args + 1) 06779 return CLI_SHOWUSAGE; 06780 06781 if (!strcasecmp(a->argv[3], "peer")) { 06782 struct iax2_peer *peer; 06783 06784 if (a->argc != e->args + 1) 06785 return CLI_SHOWUSAGE; 06786 06787 peer = find_peer(a->argv[4], 1); 06788 06789 if (!peer) { 06790 ast_cli(a->fd, "IAX2 peer '%s' does not exist\n", a->argv[e->args-1]); 06791 return CLI_FAILURE; 06792 } 06793 06794 debugaddr.sin_addr = peer->addr.sin_addr; 06795 debugaddr.sin_port = peer->addr.sin_port; 06796 06797 ast_cli(a->fd, "IAX2 Debugging Enabled for IP: %s:%d\n", 06798 ast_inet_ntoa(debugaddr.sin_addr), ntohs(debugaddr.sin_port)); 06799 06800 ao2_ref(peer, -1); 06801 } else if (!strncasecmp(a->argv[3], "on", 2)) { 06802 iaxdebug = 1; 06803 ast_cli(a->fd, "IAX2 Debugging Enabled\n"); 06804 } else { 06805 iaxdebug = 0; 06806 memset(&debugaddr, 0, sizeof(debugaddr)); 06807 ast_cli(a->fd, "IAX2 Debugging Disabled\n"); 06808 } 06809 return CLI_SUCCESS; 06810 }
| static char* handle_cli_iax2_set_debug_jb | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6838 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), and ast_cli_entry::usage.
06839 { 06840 switch (cmd) { 06841 case CLI_INIT: 06842 e->command = "iax2 set debug jb {on|off}"; 06843 e->usage = 06844 "Usage: iax2 set debug jb {on|off}\n" 06845 " Enables/Disables jitterbuffer debugging information\n"; 06846 return NULL; 06847 case CLI_GENERATE: 06848 return NULL; 06849 } 06850 06851 if (a->argc != e->args) 06852 return CLI_SHOWUSAGE; 06853 06854 if (!strncasecmp(a->argv[e->args -1], "on", 2)) { 06855 jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output); 06856 ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Enabled\n"); 06857 } else { 06858 jb_setoutput(jb_error_output, jb_warning_output, NULL); 06859 ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Disabled\n"); 06860 } 06861 return CLI_SUCCESS; 06862 }
| static char* handle_cli_iax2_set_debug_trunk | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6812 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
06813 { 06814 switch (cmd) { 06815 case CLI_INIT: 06816 e->command = "iax2 set debug trunk {on|off}"; 06817 e->usage = 06818 "Usage: iax2 set debug trunk {on|off}\n" 06819 " Enables/Disables debugging of IAX trunking\n"; 06820 return NULL; 06821 case CLI_GENERATE: 06822 return NULL; 06823 } 06824 06825 if (a->argc != e->args) 06826 return CLI_SHOWUSAGE; 06827 06828 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 06829 iaxtrunkdebug = 1; 06830 ast_cli(a->fd, "IAX2 Trunk Debugging Enabled\n"); 06831 } else { 06832 iaxtrunkdebug = 0; 06833 ast_cli(a->fd, "IAX2 Trunk Debugging Disabled\n"); 06834 } 06835 return CLI_SUCCESS; 06836 }
| static char* handle_cli_iax2_set_mtu | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Set trunk MTU from CLI.
Definition at line 3541 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, MAX_TRUNK_MTU, and ast_cli_entry::usage.
03542 { 03543 int mtuv; 03544 03545 switch (cmd) { 03546 case CLI_INIT: 03547 e->command = "iax2 set mtu"; 03548 e->usage = 03549 "Usage: iax2 set mtu <value>\n" 03550 " Set the system-wide IAX IP mtu to <value> bytes net or\n" 03551 " zero to disable. Disabling means that the operating system\n" 03552 " must handle fragmentation of UDP packets when the IAX2 trunk\n" 03553 " packet exceeds the UDP payload size. This is substantially\n" 03554 " below the IP mtu. Try 1240 on ethernets. Must be 172 or\n" 03555 " greater for G.711 samples.\n"; 03556 return NULL; 03557 case CLI_GENERATE: 03558 return NULL; 03559 } 03560 03561 if (a->argc != 4) 03562 return CLI_SHOWUSAGE; 03563 if (strncasecmp(a->argv[3], "default", strlen(a->argv[3])) == 0) 03564 mtuv = MAX_TRUNK_MTU; 03565 else 03566 mtuv = atoi(a->argv[3]); 03567 03568 if (mtuv == 0) { 03569 ast_cli(a->fd, "Trunk MTU control disabled (mtu was %d)\n", global_max_trunk_mtu); 03570 global_max_trunk_mtu = 0; 03571 return CLI_SUCCESS; 03572 } 03573 if (mtuv < 172 || mtuv > 4000) { 03574 ast_cli(a->fd, "Trunk MTU must be between 172 and 4000\n"); 03575 return CLI_SHOWUSAGE; 03576 } 03577 ast_cli(a->fd, "Trunk MTU changed from %d to %d\n", global_max_trunk_mtu, mtuv); 03578 global_max_trunk_mtu = mtuv; 03579 return CLI_SUCCESS; 03580 }
| static char* handle_cli_iax2_show_cache | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3582 of file chan_iax2.c.
References ARRAY_LEN, ast_cli(), ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, ast_strlen_zero(), ast_tvnow(), CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, CACHE_FLAG_TRANSMITTED, CACHE_FLAG_UNKNOWN, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, iax2_dpcache::expiry, iax2_dpcache::exten, ast_cli_args::fd, iax2_dpcache::flags, iax2_dpcache::peercontext, s, ast_cli_entry::usage, and iax2_dpcache::waiters.
03583 { 03584 struct iax2_dpcache *dp = NULL; 03585 char tmp[1024], *pc = NULL; 03586 int s, x, y; 03587 struct timeval now = ast_tvnow(); 03588 03589 switch (cmd) { 03590 case CLI_INIT: 03591 e->command = "iax2 show cache"; 03592 e->usage = 03593 "Usage: iax2 show cache\n" 03594 " Display currently cached IAX Dialplan results.\n"; 03595 return NULL; 03596 case CLI_GENERATE: 03597 return NULL; 03598 } 03599 03600 AST_LIST_LOCK(&dpcache); 03601 03602 ast_cli(a->fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags"); 03603 03604 AST_LIST_TRAVERSE(&dpcache, dp, cache_list) { 03605 s = dp->expiry.tv_sec - now.tv_sec; 03606 tmp[0] = '\0'; 03607 if (dp->flags & CACHE_FLAG_EXISTS) 03608 strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1); 03609 if (dp->flags & CACHE_FLAG_NONEXISTENT) 03610 strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1); 03611 if (dp->flags & CACHE_FLAG_CANEXIST) 03612 strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1); 03613 if (dp->flags & CACHE_FLAG_PENDING) 03614 strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1); 03615 if (dp->flags & CACHE_FLAG_TIMEOUT) 03616 strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1); 03617 if (dp->flags & CACHE_FLAG_TRANSMITTED) 03618 strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1); 03619 if (dp->flags & CACHE_FLAG_MATCHMORE) 03620 strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1); 03621 if (dp->flags & CACHE_FLAG_UNKNOWN) 03622 strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1); 03623 /* Trim trailing pipe */ 03624 if (!ast_strlen_zero(tmp)) { 03625 tmp[strlen(tmp) - 1] = '\0'; 03626 } else { 03627 ast_copy_string(tmp, "(none)", sizeof(tmp)); 03628 } 03629 y = 0; 03630 pc = strchr(dp->peercontext, '@'); 03631 if (!pc) { 03632 pc = dp->peercontext; 03633 } else { 03634 pc++; 03635 } 03636 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 03637 if (dp->waiters[x] > -1) 03638 y++; 03639 } 03640 if (s > 0) { 03641 ast_cli(a->fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp); 03642 } else { 03643 ast_cli(a->fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp); 03644 } 03645 } 03646 03647 AST_LIST_LOCK(&dpcache); 03648 03649 return CLI_SUCCESS; 03650 }
| static char* handle_cli_iax2_show_callno_limits | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2211 of file chan_iax2.c.
References peercnt::addr, ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_inet_ntoa(), CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, peercnt::cur, ast_cli_args::fd, global_maxcallno_nonval, peercnt::limit, peercnts, total_nonval_callno_used, and ast_cli_entry::usage.
02212 { 02213 struct ao2_iterator i; 02214 struct peercnt *peercnt; 02215 struct sockaddr_in sin; 02216 int found = 0; 02217 02218 switch (cmd) { 02219 case CLI_INIT: 02220 e->command = "iax2 show callnumber usage"; 02221 e->usage = 02222 "Usage: iax2 show callnumber usage <ip address (optional)>\n" 02223 " Shows current ip addresses which are consuming iax2 call numbers\n"; 02224 return NULL; 02225 case CLI_GENERATE: 02226 return NULL; 02227 case CLI_HANDLER: 02228 if (a->argc < 4 || a->argc > 5) 02229 return CLI_SHOWUSAGE; 02230 02231 ast_cli(a->fd, "%-15s %-12s %-12s\n", "Address", "Callno Usage", "Callno Limit"); 02232 i = ao2_iterator_init(peercnts, 0); 02233 while ((peercnt = ao2_iterator_next(&i))) { 02234 sin.sin_addr.s_addr = peercnt->addr; 02235 if (a->argc == 5 && (!strcasecmp(a->argv[4], ast_inet_ntoa(sin.sin_addr)))) { 02236 ast_cli(a->fd, "%-15s %-12d %-12d\n", ast_inet_ntoa(sin.sin_addr), peercnt->cur, peercnt->limit); 02237 found = 1; 02238 break; 02239 } else { 02240 ast_cli(a->fd, "%-15s %-12d %-12d\n", ast_inet_ntoa(sin.sin_addr), peercnt->cur, peercnt->limit); 02241 } 02242 ao2_ref(peercnt, -1); 02243 } 02244 02245 if (a->argc == 4) { 02246 ast_cli(a->fd, "\nNon-CallToken Validation Limit: %d\nNon-CallToken Validated: %d\n", global_maxcallno_nonval, total_nonval_callno_used); 02247 } else if (a->argc == 5 && !found) { 02248 ast_cli(a->fd, "No callnumber table entries for %s found\n", a->argv[4] ); 02249 } 02250 02251 return CLI_SUCCESS; 02252 default: 02253 return NULL; 02254 } 02255 }
| static char* handle_cli_iax2_show_channels | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6590 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_cli_args::argc, ARRAY_LEN, ast_cli(), ast_getformatname(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, jb_info::current, iax_rr::delay, ast_cli_args::fd, FORMAT, FORMAT2, iax_frame_subclass2str(), IAX_USEJITTERBUF, jb_getinfo(), jb_info::jitter, MARK_IAX_SUBCLASS_TX, jb_info::min, chan_iax2_pvt::owner, chan_iax2_pvt::remote_rr, S_OR, and ast_cli_entry::usage.
06591 { 06592 #define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s %s %9s\n" 06593 #define FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s %s%s %3s%s\n" 06594 #define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" 06595 int x; 06596 int numchans = 0; 06597 char first_message[10] = { 0, }; 06598 char last_message[10] = { 0, }; 06599 06600 switch (cmd) { 06601 case CLI_INIT: 06602 e->command = "iax2 show channels"; 06603 e->usage = 06604 "Usage: iax2 show channels\n" 06605 " Lists all currently active IAX channels.\n"; 06606 return NULL; 06607 case CLI_GENERATE: 06608 return NULL; 06609 } 06610 06611 if (a->argc != 3) 06612 return CLI_SHOWUSAGE; 06613 ast_cli(a->fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format", "FirstMsg", "LastMsg"); 06614 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 06615 ast_mutex_lock(&iaxsl[x]); 06616 if (iaxs[x]) { 06617 int lag, jitter, localdelay; 06618 jb_info jbinfo; 06619 if (ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 06620 jb_getinfo(iaxs[x]->jb, &jbinfo); 06621 jitter = jbinfo.jitter; 06622 localdelay = jbinfo.current - jbinfo.min; 06623 } else { 06624 jitter = -1; 06625 localdelay = 0; 06626 } 06627 06628 iax_frame_subclass2str(iaxs[x]->first_iax_message & ~MARK_IAX_SUBCLASS_TX, first_message, sizeof(first_message)); 06629 iax_frame_subclass2str(iaxs[x]->last_iax_message & ~MARK_IAX_SUBCLASS_TX, last_message, sizeof(last_message)); 06630 lag = iaxs[x]->remote_rr.delay; 06631 ast_cli(a->fd, FORMAT, 06632 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 06633 ast_inet_ntoa(iaxs[x]->addr.sin_addr), 06634 S_OR(iaxs[x]->username, "(None)"), 06635 iaxs[x]->callno, iaxs[x]->peercallno, 06636 iaxs[x]->oseqno, iaxs[x]->iseqno, 06637 lag, 06638 jitter, 06639 localdelay, 06640 ast_getformatname(iaxs[x]->voiceformat), 06641 (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 06642 first_message, 06643 (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 06644 last_message); 06645 numchans++; 06646 } 06647 ast_mutex_unlock(&iaxsl[x]); 06648 } 06649 ast_cli(a->fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 06650 return CLI_SUCCESS; 06651 #undef FORMAT 06652 #undef FORMAT2 06653 #undef FORMATB 06654 }
| static char* handle_cli_iax2_show_firmware | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6441 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, ast_cli_args::fd, iax_firmware::fwh, ast_cli_entry::usage, and ast_iax2_firmware_header::version.
06442 { 06443 struct iax_firmware *cur = NULL; 06444 06445 switch (cmd) { 06446 case CLI_INIT: 06447 e->command = "iax2 show firmware"; 06448 e->usage = 06449 "Usage: iax2 show firmware\n" 06450 " Lists all known IAX firmware images.\n"; 06451 return NULL; 06452 case CLI_GENERATE: 06453 return NULL; 06454 } 06455 06456 if (a->argc != 3 && a->argc != 4) 06457 return CLI_SHOWUSAGE; 06458 06459 ast_cli(a->fd, "%-15.15s %-15.15s %-15.15s\n", "Device", "Version", "Size"); 06460 AST_LIST_LOCK(&firmwares); 06461 AST_LIST_TRAVERSE(&firmwares, cur, list) { 06462 if ((a->argc == 3) || (!strcasecmp(a->argv[3], (char *) cur->fwh->devname))) { 06463 ast_cli(a->fd, "%-15.15s %-15d %-15d\n", cur->fwh->devname, 06464 ntohs(cur->fwh->version), (int)ntohl(cur->fwh->datalen)); 06465 } 06466 } 06467 AST_LIST_UNLOCK(&firmwares); 06468 06469 return CLI_SUCCESS; 06470 }
| static char* handle_cli_iax2_show_netstats | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6740 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), ast_cli_netstats(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
06741 { 06742 int numchans = 0; 06743 06744 switch (cmd) { 06745 case CLI_INIT: 06746 e->command = "iax2 show netstats"; 06747 e->usage = 06748 "Usage: iax2 show netstats\n" 06749 " Lists network status for all currently active IAX channels.\n"; 06750 return NULL; 06751 case CLI_GENERATE: 06752 return NULL; 06753 } 06754 if (a->argc != 3) 06755 return CLI_SHOWUSAGE; 06756 ast_cli(a->fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n"); 06757 ast_cli(a->fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts FirstMsg LastMsg\n"); 06758 numchans = ast_cli_netstats(NULL, a->fd, 1); 06759 ast_cli(a->fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 06760 return CLI_SUCCESS; 06761 }
| static char* handle_cli_iax2_show_peer | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Show one peer in detail.
Definition at line 3400 of file chan_iax2.c.
References iax2_peer::addr, ast_cli_args::argc, ast_cli_args::argv, ast_callerid_merge(), ast_cli(), ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, CALLTOKEN_AUTO, iax2_peer::calltoken_required, CALLTOKEN_YES, iax2_peer::capability, iax2_peer::cid_name, iax2_peer::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_peers(), iax2_peer::context, iax2_peer::defaddr, iax2_peer::expire, ast_cli_args::fd, find_peer(), iax2_peer::ha, IAX_DYNAMIC, IAX_TRUNK, ast_cli_args::line, iax2_peer::mailbox, iax2_peer::maxcallno, ast_cli_args::n, iax2_peer::name, iax2_peer::parkinglot, peer_status(), peer_unref(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, ast_cli_args::pos, iax2_peer::prefs, iax2_peer::secret, iax2_peer::smoothing, status, ast_cli_entry::usage, iax2_peer::username, and ast_cli_args::word.
03401 { 03402 char status[30]; 03403 char cbuf[256]; 03404 struct iax2_peer *peer; 03405 char codec_buf[512]; 03406 int x = 0, codec = 0, load_realtime = 0; 03407 03408 switch (cmd) { 03409 case CLI_INIT: 03410 e->command = "iax2 show peer"; 03411 e->usage = 03412 "Usage: iax2 show peer <name>\n" 03413 " Display details on specific IAX peer\n"; 03414 return NULL; 03415 case CLI_GENERATE: 03416 if (a->pos == 3) 03417 return complete_iax2_peers(a->line, a->word, a->pos, a->n); 03418 return NULL; 03419 } 03420 03421 if (a->argc < 4) 03422 return CLI_SHOWUSAGE; 03423 03424 load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? 1 : 0; 03425 03426 peer = find_peer(a->argv[3], load_realtime); 03427 if (peer) { 03428 ast_cli(a->fd, "\n\n"); 03429 ast_cli(a->fd, " * Name : %s\n", peer->name); 03430 ast_cli(a->fd, " Secret : %s\n", ast_strlen_zero(peer->secret) ? "<Not set>" : "<Set>"); 03431 ast_cli(a->fd, " Context : %s\n", peer->context); 03432 ast_cli(a->fd, " Parking lot : %s\n", peer->parkinglot); 03433 ast_cli(a->fd, " Mailbox : %s\n", peer->mailbox); 03434 ast_cli(a->fd, " Dynamic : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No"); 03435 ast_cli(a->fd, " Callnum limit: %d\n", peer->maxcallno); 03436 ast_cli(a->fd, " Calltoken req: %s\n", (peer->calltoken_required == CALLTOKEN_YES) ? "Yes" : ((peer->calltoken_required == CALLTOKEN_AUTO) ? "Auto" : "No")); 03437 ast_cli(a->fd, " Trunk : %s\n", ast_test_flag(peer, IAX_TRUNK) ? "Yes" : "No"); 03438 ast_cli(a->fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 03439 ast_cli(a->fd, " Expire : %d\n", peer->expire); 03440 ast_cli(a->fd, " ACL : %s\n", (peer->ha ? "Yes" : "No")); 03441 ast_cli(a->fd, " Addr->IP : %s Port %d\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port)); 03442 ast_cli(a->fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 03443 ast_cli(a->fd, " Username : %s\n", peer->username); 03444 ast_cli(a->fd, " Codecs : "); 03445 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 03446 ast_cli(a->fd, "%s\n", codec_buf); 03447 03448 ast_cli(a->fd, " Codec Order : ("); 03449 for(x = 0; x < 32 ; x++) { 03450 codec = ast_codec_pref_index(&peer->prefs,x); 03451 if(!codec) 03452 break; 03453 ast_cli(a->fd, "%s", ast_getformatname(codec)); 03454 if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1)) 03455 ast_cli(a->fd, "|"); 03456 } 03457 03458 if (!x) 03459 ast_cli(a->fd, "none"); 03460 ast_cli(a->fd, ")\n"); 03461 03462 ast_cli(a->fd, " Status : "); 03463 peer_status(peer, status, sizeof(status)); 03464 ast_cli(a->fd, "%s\n",status); 03465 ast_cli(a->fd, " Qualify : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off"); 03466 ast_cli(a->fd, "\n"); 03467 peer_unref(peer); 03468 } else { 03469 ast_cli(a->fd, "Peer %s not found.\n", a->argv[3]); 03470 ast_cli(a->fd, "\n"); 03471 } 03472 03473 return CLI_SUCCESS; 03474 }
| static char* handle_cli_iax2_show_peers | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6409 of file chan_iax2.c.
References __iax2_show_peers(), ast_cli_args::argc, ast_cli_args::argv, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and ast_cli_entry::usage.
06410 { 06411 switch (cmd) { 06412 case CLI_INIT: 06413 e->command = "iax2 show peers"; 06414 e->usage = 06415 "Usage: iax2 show peers [registered] [like <pattern>]\n" 06416 " Lists all known IAX2 peers.\n" 06417 " Optional 'registered' argument lists only peers with known addresses.\n" 06418 " Optional regular expression pattern is used to filter the peer list.\n"; 06419 return NULL; 06420 case CLI_GENERATE: 06421 return NULL; 06422 } 06423 06424 switch (__iax2_show_peers(0, a->fd, NULL, a->argc, a->argv)) { 06425 case RESULT_SHOWUSAGE: 06426 return CLI_SHOWUSAGE; 06427 case RESULT_FAILURE: 06428 return CLI_FAILURE; 06429 default: 06430 return CLI_SUCCESS; 06431 } 06432 }
| static char* handle_cli_iax2_show_registry | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6549 of file chan_iax2.c.
References iax2_registry::addr, ast_cli_args::argc, ast_cli(), ast_copy_string(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, iax2_registry::dnsmgr, ast_cli_args::fd, FORMAT, FORMAT2, iax2_registry::refresh, iax2_registry::regstate, regstate2str(), iax2_registry::us, ast_cli_entry::usage, and iax2_registry::username.
06550 { 06551 #define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" 06552 #define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" 06553 struct iax2_registry *reg = NULL; 06554 char host[80]; 06555 char perceived[80]; 06556 int counter = 0; 06557 06558 switch (cmd) { 06559 case CLI_INIT: 06560 e->command = "iax2 show registry"; 06561 e->usage = 06562 "Usage: iax2 show registry\n" 06563 " Lists all registration requests and status.\n"; 06564 return NULL; 06565 case CLI_GENERATE: 06566 return NULL; 06567 } 06568 if (a->argc != 3) 06569 return CLI_SHOWUSAGE; 06570 ast_cli(a->fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State"); 06571 AST_LIST_LOCK(®istrations); 06572 AST_LIST_TRAVERSE(®istrations, reg, entry) { 06573 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port)); 06574 if (reg->us.sin_addr.s_addr) 06575 snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 06576 else 06577 ast_copy_string(perceived, "<Unregistered>", sizeof(perceived)); 06578 ast_cli(a->fd, FORMAT, host, 06579 (reg->dnsmgr) ? "Y" : "N", 06580 reg->username, perceived, reg->refresh, regstate2str(reg->regstate)); 06581 counter++; 06582 } 06583 AST_LIST_UNLOCK(®istrations); 06584 ast_cli(a->fd, "%d IAX2 registrations.\n", counter); 06585 return CLI_SUCCESS; 06586 #undef FORMAT 06587 #undef FORMAT2 06588 }
| static char* handle_cli_iax2_show_stats | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3497 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, iax_frame::final, iax_get_frames(), iax_get_iframes(), iax_get_oframes(), iax_frame::retries, and ast_cli_entry::usage.
03498 { 03499 struct iax_frame *cur; 03500 int cnt = 0, dead = 0, final = 0; 03501 03502 switch (cmd) { 03503 case CLI_INIT: 03504 e->command = "iax2 show stats"; 03505 e->usage = 03506 "Usage: iax2 show stats\n" 03507 " Display statistics on IAX channel driver.\n"; 03508 return NULL; 03509 case CLI_GENERATE: 03510 return NULL; 03511 } 03512 03513 if (a->argc != 3) 03514 return CLI_SHOWUSAGE; 03515 03516 AST_LIST_LOCK(&frame_queue); 03517 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 03518 if (cur->retries < 0) 03519 dead++; 03520 if (cur->final) 03521 final++; 03522 cnt++; 03523 } 03524 AST_LIST_UNLOCK(&frame_queue); 03525 03526 ast_cli(a->fd, " IAX Statistics\n"); 03527 ast_cli(a->fd, "---------------------\n"); 03528 ast_cli(a->fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes()); 03529 ast_cli(a->fd, "%d timed and %d untimed transmits; MTU %d/%d/%d\n", trunk_timed, trunk_untimed, 03530 trunk_maxmtu, trunk_nmaxmtu, global_max_trunk_mtu); 03531 ast_cli(a->fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt); 03532 03533 trunk_timed = trunk_untimed = 0; 03534 if (trunk_maxmtu > trunk_nmaxmtu) 03535 trunk_nmaxmtu = trunk_maxmtu; 03536 03537 return CLI_SUCCESS; 03538 }
| static char* handle_cli_iax2_show_threads | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6273 of file chan_iax2.c.
References iax2_thread::actions, ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax2_thread::checktime, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, iax2_thread::curfunc, ast_cli_args::fd, IAX_THREAD_TYPE_DYNAMIC, iaxthreadcount, iax2_thread::iostate, thread, iax2_thread::threadnum, iax2_thread::type, and ast_cli_entry::usage.
06274 { 06275 struct iax2_thread *thread = NULL; 06276 time_t t; 06277 int threadcount = 0, dynamiccount = 0; 06278 char type; 06279 06280 switch (cmd) { 06281 case CLI_INIT: 06282 e->command = "iax2 show threads"; 06283 e->usage = 06284 "Usage: iax2 show threads\n" 06285 " Lists status of IAX helper threads\n"; 06286 return NULL; 06287 case CLI_GENERATE: 06288 return NULL; 06289 } 06290 if (a->argc != 3) 06291 return CLI_SHOWUSAGE; 06292 06293 ast_cli(a->fd, "IAX2 Thread Information\n"); 06294 time(&t); 06295 ast_cli(a->fd, "Idle Threads:\n"); 06296 AST_LIST_LOCK(&idle_list); 06297 AST_LIST_TRAVERSE(&idle_list, thread, list) { 06298 #ifdef DEBUG_SCHED_MULTITHREAD 06299 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d, func='%s'\n", 06300 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 06301 #else 06302 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d\n", 06303 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 06304 #endif 06305 threadcount++; 06306 } 06307 AST_LIST_UNLOCK(&idle_list); 06308 ast_cli(a->fd, "Active Threads:\n"); 06309 AST_LIST_LOCK(&active_list); 06310 AST_LIST_TRAVERSE(&active_list, thread, list) { 06311 if (thread->type == IAX_THREAD_TYPE_DYNAMIC) 06312 type = 'D'; 06313 else 06314 type = 'P'; 06315 #ifdef DEBUG_SCHED_MULTITHREAD 06316 ast_cli(a->fd, "Thread %c%d: state=%d, update=%d, actions=%d, func='%s'\n", 06317 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 06318 #else 06319 ast_cli(a->fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 06320 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 06321 #endif 06322 threadcount++; 06323 } 06324 AST_LIST_UNLOCK(&active_list); 06325 ast_cli(a->fd, "Dynamic Threads:\n"); 06326 AST_LIST_LOCK(&dynamic_list); 06327 AST_LIST_TRAVERSE(&dynamic_list, thread, list) { 06328 #ifdef DEBUG_SCHED_MULTITHREAD 06329 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d, func='%s'\n", 06330 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 06331 #else 06332 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d\n", 06333 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 06334 #endif 06335 dynamiccount++; 06336 } 06337 AST_LIST_UNLOCK(&dynamic_list); 06338 ast_cli(a->fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount); 06339 return CLI_SUCCESS; 06340 }
| static char* handle_cli_iax2_show_users | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6072 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_strlen_zero(), ast_test_flag, iax2_user::authmethods, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, iax2_context::context, iax2_user::contexts, DEFAULT_CONTEXT, ast_cli_args::fd, FORMAT, FORMAT2, iax2_user::ha, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, iax2_user::inkeys, iax2_user::name, iax2_user::secret, ast_cli_entry::usage, and user_unref().
06073 { 06074 regex_t regexbuf; 06075 int havepattern = 0; 06076 06077 #define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" 06078 #define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" 06079 06080 struct iax2_user *user = NULL; 06081 char auth[90]; 06082 char *pstr = ""; 06083 struct ao2_iterator i; 06084 06085 switch (cmd) { 06086 case CLI_INIT: 06087 e->command = "iax2 show users [like]"; 06088 e->usage = 06089 "Usage: iax2 show users [like <pattern>]\n" 06090 " Lists all known IAX2 users.\n" 06091 " Optional regular expression pattern is used to filter the user list.\n"; 06092 return NULL; 06093 case CLI_GENERATE: 06094 return NULL; 06095 } 06096 06097 switch (a->argc) { 06098 case 5: 06099 if (!strcasecmp(a->argv[3], "like")) { 06100 if (regcomp(®exbuf, a->argv[4], REG_EXTENDED | REG_NOSUB)) 06101 return CLI_SHOWUSAGE; 06102 havepattern = 1; 06103 } else 06104 return CLI_SHOWUSAGE; 06105 case 3: 06106 break; 06107 default: 06108 return CLI_SHOWUSAGE; 06109 } 06110 06111 ast_cli(a->fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref"); 06112 i = ao2_iterator_init(users, 0); 06113 for (user = ao2_iterator_next(&i); user; 06114 user_unref(user), user = ao2_iterator_next(&i)) { 06115 if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) 06116 continue; 06117 06118 if (!ast_strlen_zero(user->secret)) { 06119 ast_copy_string(auth,user->secret, sizeof(auth)); 06120 } else if (!ast_strlen_zero(user->inkeys)) { 06121 snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys); 06122 } else 06123 ast_copy_string(auth, "-no secret-", sizeof(auth)); 06124 06125 if(ast_test_flag(user,IAX_CODEC_NOCAP)) 06126 pstr = "REQ Only"; 06127 else if(ast_test_flag(user,IAX_CODEC_NOPREFS)) 06128 pstr = "Disabled"; 06129 else 06130 pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host"; 06131 06132 ast_cli(a->fd, FORMAT2, user->name, auth, user->authmethods, 06133 user->contexts ? user->contexts->context : DEFAULT_CONTEXT, 06134 user->ha ? "Yes" : "No", pstr); 06135 } 06136 06137 if (havepattern) 06138 regfree(®exbuf); 06139 06140 return CLI_SUCCESS; 06141 #undef FORMAT 06142 #undef FORMAT2 06143 }
| static char* handle_cli_iax2_test_losspct | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3286 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
03287 { 03288 switch (cmd) { 03289 case CLI_INIT: 03290 e->command = "iax2 test losspct"; 03291 e->usage = 03292 "Usage: iax2 test losspct <percentage>\n" 03293 " For testing, throws away <percentage> percent of incoming packets\n"; 03294 return NULL; 03295 case CLI_GENERATE: 03296 return NULL; 03297 } 03298 if (a->argc != 4) 03299 return CLI_SHOWUSAGE; 03300 03301 test_losspct = atoi(a->argv[3]); 03302 03303 return CLI_SUCCESS; 03304 }
| static char* handle_cli_iax2_unregister | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6342 of file chan_iax2.c.
References ao2_find, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_unregister(), iax2_peer::expire, expire_registry(), ast_cli_args::fd, find_peer(), ast_cli_args::line, ast_cli_args::n, iax2_peer::name, OBJ_POINTER, peer_ref(), peer_unref(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
06343 { 06344 struct iax2_peer *p; 06345 06346 switch (cmd) { 06347 case CLI_INIT: 06348 e->command = "iax2 unregister"; 06349 e->usage = 06350 "Usage: iax2 unregister <peername>\n" 06351 " Unregister (force expiration) an IAX2 peer from the registry.\n"; 06352 return NULL; 06353 case CLI_GENERATE: 06354 return complete_iax2_unregister(a->line, a->word, a->pos, a->n); 06355 } 06356 06357 if (a->argc != 3) 06358 return CLI_SHOWUSAGE; 06359 06360 p = find_peer(a->argv[2], 1); 06361 if (p) { 06362 if (p->expire > 0) { 06363 struct iax2_peer tmp_peer = { 06364 .name = a->argv[2], 06365 }; 06366 struct iax2_peer *peer; 06367 06368 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 06369 if (peer) { 06370 expire_registry(peer_ref(peer)); /* will release its own reference when done */ 06371 peer_unref(peer); /* ref from ao2_find() */ 06372 ast_cli(a->fd, "Peer %s unregistered\n", a->argv[2]); 06373 } else { 06374 ast_cli(a->fd, "Peer %s not found\n", a->argv[2]); 06375 } 06376 } else { 06377 ast_cli(a->fd, "Peer %s not registered\n", a->argv[2]); 06378 } 06379 } else { 06380 ast_cli(a->fd, "Peer unknown: %s. Not unregistered\n", a->argv[2]); 06381 } 06382 return CLI_SUCCESS; 06383 }
| static void handle_deferred_full_frames | ( | struct iax2_thread * | thread | ) | [static] |
Handle any deferred full frames for this thread.
Definition at line 8869 of file chan_iax2.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), iax2_pkt_buf::buf, iax2_thread::buf, iax2_thread::buf_len, iax2_thread::buf_size, iax2_thread::full_frames, iax2_pkt_buf::len, iax2_thread::lock, and socket_process().
Referenced by iax2_process_thread().
08870 { 08871 struct iax2_pkt_buf *pkt_buf; 08872 08873 ast_mutex_lock(&thread->lock); 08874 08875 while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) { 08876 ast_mutex_unlock(&thread->lock); 08877 08878 thread->buf = pkt_buf->buf; 08879 thread->buf_len = pkt_buf->len; 08880 thread->buf_size = pkt_buf->len + 1; 08881 08882 socket_process(thread); 08883 08884 thread->buf = NULL; 08885 ast_free(pkt_buf); 08886 08887 ast_mutex_lock(&thread->lock); 08888 } 08889 08890 ast_mutex_unlock(&thread->lock); 08891 }
| static int handle_error | ( | void | ) | [static] |
Definition at line 2954 of file chan_iax2.c.
References ast_inet_ntoa(), ast_log(), errno, LOG_WARNING, and netsocket.
Referenced by send_packet(), socket_read(), and transmit_trunk().
02955 { 02956 /* XXX Ideally we should figure out why an error occurred and then abort those 02957 rather than continuing to try. Unfortunately, the published interface does 02958 not seem to work XXX */ 02959 #if 0 02960 struct sockaddr_in *sin; 02961 int res; 02962 struct msghdr m; 02963 struct sock_extended_err e; 02964 m.msg_name = NULL; 02965 m.msg_namelen = 0; 02966 m.msg_iov = NULL; 02967 m.msg_control = &e; 02968 m.msg_controllen = sizeof(e); 02969 m.msg_flags = 0; 02970 res = recvmsg(netsocket, &m, MSG_ERRQUEUE); 02971 if (res < 0) 02972 ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno)); 02973 else { 02974 if (m.msg_controllen) { 02975 sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e); 02976 if (sin) 02977 ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr)); 02978 else 02979 ast_log(LOG_WARNING, "No address detected??\n"); 02980 } else { 02981 ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno)); 02982 } 02983 } 02984 #endif 02985 return 0; 02986 }
| static int iax2_ack_registry | ( | struct iax_ies * | ies, | |
| struct sockaddr_in * | sin, | |||
| int | callno | |||
| ) | [static] |
Acknowledgment received for OUR registration.
Definition at line 7836 of file chan_iax2.c.
References iax2_registry::addr, iax_ies::apparent_addr, ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_verb, iax_ies::calling_number, EVENT_FLAG_SYSTEM, iax2_registry::expire, iax2_do_register_s(), iax2_sched_replace(), inaddrcmp(), LOG_WARNING, manager_event, iax2_registry::messages, iax_ies::msgcount, iax_ies::refresh, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGISTERED, iax2_registry::regstate, iax2_registry::us, and iax_ies::username.
Referenced by socket_process().
07837 { 07838 struct iax2_registry *reg; 07839 /* Start pessimistic */ 07840 char peer[256] = ""; 07841 char msgstatus[60]; 07842 int refresh = 60; 07843 char ourip[256] = "<Unspecified>"; 07844 struct sockaddr_in oldus; 07845 struct sockaddr_in us; 07846 int oldmsgs; 07847 07848 memset(&us, 0, sizeof(us)); 07849 if (ies->apparent_addr) 07850 memmove(&us, ies->apparent_addr, sizeof(us)); 07851 if (ies->username) 07852 ast_copy_string(peer, ies->username, sizeof(peer)); 07853 if (ies->refresh) 07854 refresh = ies->refresh; 07855 if (ies->calling_number) { 07856 /* We don't do anything with it really, but maybe we should */ 07857 } 07858 reg = iaxs[callno]->reg; 07859 if (!reg) { 07860 ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer); 07861 return -1; 07862 } 07863 memcpy(&oldus, ®->us, sizeof(oldus)); 07864 oldmsgs = reg->messages; 07865 if (inaddrcmp(®->addr, sin)) { 07866 ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 07867 return -1; 07868 } 07869 memcpy(®->us, &us, sizeof(reg->us)); 07870 if (ies->msgcount >= 0) 07871 reg->messages = ies->msgcount & 0xffff; /* only low 16 bits are used in the transmission of the IE */ 07872 /* always refresh the registration at the interval requested by the server 07873 we are registering to 07874 */ 07875 reg->refresh = refresh; 07876 reg->expire = iax2_sched_replace(reg->expire, sched, 07877 (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 07878 if (inaddrcmp(&oldus, ®->us) || (reg->messages != oldmsgs)) { 07879 if (reg->messages > 255) 07880 snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8); 07881 else if (reg->messages > 1) 07882 snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages); 07883 else if (reg->messages > 0) 07884 ast_copy_string(msgstatus, " with 1 new message waiting\n", sizeof(msgstatus)); 07885 else 07886 ast_copy_string(msgstatus, " with no messages waiting\n", sizeof(msgstatus)); 07887 snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 07888 ast_verb(3, "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus); 07889 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr)); 07890 } 07891 reg->regstate = REG_STATE_REGISTERED; 07892 return 0; 07893 }
| static int attribute_pure iax2_allow_new | ( | int | frametype, | |
| int | subclass, | |||
| int | inbound | |||
| ) | [inline, static] |
Definition at line 2393 of file chan_iax2.c.
References AST_FRAME_IAX, IAX_COMMAND_FWDOWNL, IAX_COMMAND_NEW, IAX_COMMAND_POKE, IAX_COMMAND_REGREL, and IAX_COMMAND_REGREQ.
Referenced by resend_with_token(), and socket_process().
02394 { 02395 if (frametype != AST_FRAME_IAX) { 02396 return 0; 02397 } 02398 switch (subclass) { 02399 case IAX_COMMAND_NEW: 02400 case IAX_COMMAND_REGREQ: 02401 case IAX_COMMAND_FWDOWNL: 02402 case IAX_COMMAND_REGREL: 02403 return 1; 02404 case IAX_COMMAND_POKE: 02405 if (!inbound) { 02406 return 1; 02407 } 02408 break; 02409 } 02410 return 0; 02411 }
| static void iax2_ami_channelupdate | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Send manager event at call setup to link between Asterisk channel name and IAX2 call identifiers.
Definition at line 1099 of file chan_iax2.c.
References chan_iax2_pvt::callno, EVENT_FLAG_SYSTEM, manager_event, chan_iax2_pvt::owner, chan_iax2_pvt::peer, and chan_iax2_pvt::peercallno.
Referenced by ast_iax2_new(), and iax2_answer().
01100 { 01101 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 01102 "Channel: %s\r\nChanneltype: IAX2\r\nIAX2-callno-local: %d\r\nIAX2-callno-remote: %d\r\nIAX2-peer: %s\r\n", 01103 pvt->owner ? pvt->owner->name : "", 01104 pvt->callno, pvt->peercallno, pvt->peer ? pvt->peer : ""); 01105 }
| static int iax2_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 5148 of file chan_iax2.c.
References AST_CONTROL_ANSWER, ast_debug, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), iax2_ami_channelupdate(), PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
05149 { 05150 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 05151 ast_debug(1, "Answering IAX2 call\n"); 05152 ast_mutex_lock(&iaxsl[callno]); 05153 if (iaxs[callno]) 05154 iax2_ami_channelupdate(iaxs[callno]); 05155 ast_mutex_unlock(&iaxsl[callno]); 05156 return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1); 05157 }
| static int iax2_append_register | ( | const char * | hostname, | |
| const char * | username, | |||
| const char * | secret, | |||
| const char * | porta | |||
| ) | [static] |
Definition at line 7895 of file chan_iax2.c.
References iax2_registry::addr, ast_calloc, ast_copy_string(), ast_dnsmgr_lookup(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, iax2_registry::dnsmgr, iax2_registry::expire, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, iax2_registry::refresh, iax2_registry::secret, and iax2_registry::username.
Referenced by iax2_register().
07897 { 07898 struct iax2_registry *reg; 07899 07900 if (!(reg = ast_calloc(1, sizeof(*reg)))) 07901 return -1; 07902 07903 if (ast_dnsmgr_lookup(hostname, ®->addr, ®->dnsmgr, srvlookup ? "_iax._udp" : NULL) < 0) { 07904 ast_free(reg); 07905 return -1; 07906 } 07907 07908 ast_copy_string(reg->username, username, sizeof(reg->username)); 07909 07910 if (secret) 07911 ast_copy_string(reg->secret, secret, sizeof(reg->secret)); 07912 07913 reg->expire = -1; 07914 reg->refresh = IAX_DEFAULT_REG_EXPIRE; 07915 reg->addr.sin_family = AF_INET; 07916 reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO); 07917 07918 AST_LIST_LOCK(®istrations); 07919 AST_LIST_INSERT_HEAD(®istrations, reg, entry); 07920 AST_LIST_UNLOCK(®istrations); 07921 07922 return 0; 07923 }
| 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] |
Definition at line 4993 of file chan_iax2.c.
References ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_check_hangup(), AST_CONTROL_SRCUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_getformatname_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), AST_SOFTHANGUP_DEV, ast_test_flag, ast_tvnow(), ast_tvzero(), ast_verb, ast_waitfor_n(), ast_write(), chan_iax2_pvt::bridgecallno, f, ast_frame::frametype, iax2_start_transfer(), IAX_LINGER_TIMEOUT, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, lock_both(), LOG_WARNING, ast_channel::nativeformats, PTR_TO_CALLNO, ast_frame::subclass, ast_channel::tech, ast_channel::tech_pvt, TRANSFER_RELEASED, and unlock_both().
04994 { 04995 struct ast_channel *cs[3]; 04996 struct ast_channel *who, *other; 04997 int to = -1; 04998 int res = -1; 04999 int transferstarted=0; 05000 struct ast_frame *f; 05001 unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt); 05002 unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt); 05003 struct timeval waittimer = {0, 0}; 05004 05005 /* We currently do not support native bridging if a timeoutms value has been provided */ 05006 if (timeoutms > 0) { 05007 return AST_BRIDGE_FAILED; 05008 } 05009 05010 timeoutms = -1; 05011 05012 lock_both(callno0, callno1); 05013 if (!iaxs[callno0] || !iaxs[callno1]) { 05014 unlock_both(callno0, callno1); 05015 return AST_BRIDGE_FAILED; 05016 } 05017 /* Put them in native bridge mode */ 05018 if (!(flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) { 05019 iaxs[callno0]->bridgecallno = callno1; 05020 iaxs[callno1]->bridgecallno = callno0; 05021 } 05022 unlock_both(callno0, callno1); 05023 05024 /* If not, try to bridge until we can execute a transfer, if we can */ 05025 cs[0] = c0; 05026 cs[1] = c1; 05027 for (/* ever */;;) { 05028 /* Check in case we got masqueraded into */ 05029 if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) { 05030 ast_verb(3, "Can't masquerade, we're different...\n"); 05031 /* Remove from native mode */ 05032 if (c0->tech == &iax2_tech) { 05033 ast_mutex_lock(&iaxsl[callno0]); 05034 iaxs[callno0]->bridgecallno = 0; 05035 ast_mutex_unlock(&iaxsl[callno0]); 05036 } 05037 if (c1->tech == &iax2_tech) { 05038 ast_mutex_lock(&iaxsl[callno1]); 05039 iaxs[callno1]->bridgecallno = 0; 05040 ast_mutex_unlock(&iaxsl[callno1]); 05041 } 05042 return AST_BRIDGE_FAILED_NOWARN; 05043 } 05044 if (c0->nativeformats != c1->nativeformats) { 05045 char buf0[255]; 05046 char buf1[255]; 05047 ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats); 05048 ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats); 05049 ast_verb(3, "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1); 05050 /* Remove from native mode */ 05051 lock_both(callno0, callno1); 05052 if (iaxs[callno0]) 05053 iaxs[callno0]->bridgecallno = 0; 05054 if (iaxs[callno1]) 05055 iaxs[callno1]->bridgecallno = 0; 05056 unlock_both(callno0, callno1); 05057 return AST_BRIDGE_FAILED_NOWARN; 05058 } 05059 /* check if transfered and if we really want native bridging */ 05060 if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) { 05061 /* Try the transfer */ 05062 if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) || 05063 ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA))) 05064 ast_log(LOG_WARNING, "Unable to start the transfer\n"); 05065 transferstarted = 1; 05066 } 05067 if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) { 05068 /* Call has been transferred. We're no longer involved */ 05069 struct timeval now = ast_tvnow(); 05070 if (ast_tvzero(waittimer)) { 05071 waittimer = now; 05072 } else if (now.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) { 05073 c0->_softhangup |= AST_SOFTHANGUP_DEV; 05074 c1->_softhangup |= AST_SOFTHANGUP_DEV; 05075 *fo = NULL; 05076 *rc = c0; 05077 res = AST_BRIDGE_COMPLETE; 05078 break; 05079 } 05080 } 05081 to = 1000; 05082 who = ast_waitfor_n(cs, 2, &to); 05083 if (timeoutms > -1) { 05084 timeoutms -= (1000 - to); 05085 if (timeoutms < 0) 05086 timeoutms = 0; 05087 } 05088 if (!who) { 05089 if (!timeoutms) { 05090 res = AST_BRIDGE_RETRY; 05091 break; 05092 } 05093 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 05094 res = AST_BRIDGE_FAILED; 05095 break; 05096 } 05097 continue; 05098 } 05099 f = ast_read(who); 05100 if (!f) { 05101 *fo = NULL; 05102 *rc = who; 05103 res = AST_BRIDGE_COMPLETE; 05104 break; 05105 } 05106 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS) && (f->subclass != AST_CONTROL_SRCUPDATE)) { 05107 *fo = f; 05108 *rc = who; 05109 res = AST_BRIDGE_COMPLETE; 05110 break; 05111 } 05112 other = (who == c0) ? c1 : c0; /* the 'other' channel */ 05113 if ((f->frametype == AST_FRAME_VOICE) || 05114 (f->frametype == AST_FRAME_TEXT) || 05115 (f->frametype == AST_FRAME_VIDEO) || 05116 (f->frametype == AST_FRAME_IMAGE) || 05117 (f->frametype == AST_FRAME_DTMF) || 05118 (f->frametype == AST_FRAME_CONTROL)) { 05119 /* monitored dtmf take out of the bridge. 05120 * check if we monitor the specific source. 05121 */ 05122 int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1; 05123 if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) { 05124 *rc = who; 05125 *fo = f; 05126 res = AST_BRIDGE_COMPLETE; 05127 /* Remove from native mode */ 05128 break; 05129 } 05130 /* everything else goes to the other side */ 05131 ast_write(other, f); 05132 } 05133 ast_frfree(f); 05134 /* Swap who gets priority */ 05135 cs[2] = cs[0]; 05136 cs[0] = cs[1]; 05137 cs[1] = cs[2]; 05138 } 05139 lock_both(callno0, callno1); 05140 if(iaxs[callno0]) 05141 iaxs[callno0]->bridgecallno = 0; 05142 if(iaxs[callno1]) 05143 iaxs[callno1]->bridgecallno = 0; 05144 unlock_both(callno0, callno1); 05145 return res; 05146 }
| static int iax2_call | ( | struct ast_channel * | c, | |
| char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 4604 of file chan_iax2.c.
References ast_channel::_state, add_empty_calltoken_ie(), create_addr_info::adsi, chan_iax2_pvt::adsi, ast_channel::adsicpe, ast_channel_datastore_find(), ast_copy_string(), ast_debug, AST_FRAME_IAX, AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PRES_NUMBER_NOT_AVAILABLE, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_var_name(), ast_var_value(), auto_congest(), iax_ie_data::buf, CALLNO_TO_PTR, capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, context, create_addr_info::context, ast_channel::context, parsed_dial_string::context, create_addr(), ast_datastore::data, chan_iax2_pvt::encmethods, create_addr_info::encmethods, parsed_dial_string::exten, iax2_datetime(), iax2_sched_add(), IAX_COMMAND_NEW, IAX_IE_ADSICPE, iax_ie_append(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_raw(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTOANSWER, IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CALLING_ANI, IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_CALLINGPRES, IAX_IE_CALLINGTNS, IAX_IE_CALLINGTON, IAX_IE_CAPABILITY, IAX_IE_CODEC_PREFS, IAX_IE_DATETIME, IAX_IE_DNID, IAX_IE_ENCRYPTION, IAX_IE_FORMAT, IAX_IE_LANGUAGE, IAX_IE_OSPTOKEN, IAX_IE_RDNIS, IAX_IE_USERNAME, IAX_IE_VARIABLE, IAX_IE_VERSION, IAX_MAX_OSPBLOCK_SIZE, IAX_MAX_OSPTOKEN_SIZE, IAX_PROTO_VERSION, IAX_SENDANI, chan_iax2_pvt::initid, parsed_dial_string::key, LOG_WARNING, chan_iax2_pvt::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, parsed_dial_string::options, chan_iax2_pvt::osptoken, create_addr_info::outkey, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, create_addr_info::peercontext, chan_iax2_pvt::pingtime, parsed_dial_string::port, iax_ie_data::pos, create_addr_info::prefs, PTR_TO_CALLNO, secret, create_addr_info::secret, send_command(), create_addr_info::sockfd, chan_iax2_pvt::sockfd, ast_channel::tech_pvt, create_addr_info::timezone, create_addr_info::username, parsed_dial_string::username, and var.
04605 { 04606 struct sockaddr_in sin; 04607 char *l=NULL, *n=NULL, *tmpstr; 04608 struct iax_ie_data ied; 04609 char *defaultrdest = "s"; 04610 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04611 struct parsed_dial_string pds; 04612 struct create_addr_info cai; 04613 struct ast_var_t *var; 04614 struct ast_datastore *variablestore = ast_channel_datastore_find(c, &iax2_variable_datastore_info, NULL); 04615 const char* osp_token_ptr; 04616 unsigned int osp_token_length; 04617 unsigned char osp_block_index; 04618 unsigned int osp_block_length; 04619 unsigned char osp_buffer[256]; 04620 04621 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { 04622 ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name); 04623 return -1; 04624 } 04625 04626 memset(&cai, 0, sizeof(cai)); 04627 cai.encmethods = iax2_encryption; 04628 04629 memset(&pds, 0, sizeof(pds)); 04630 tmpstr = ast_strdupa(dest); 04631 parse_dial_string(tmpstr, &pds); 04632 04633 if (ast_strlen_zero(pds.peer)) { 04634 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest); 04635 return -1; 04636 } 04637 04638 if (!pds.exten) { 04639 pds.exten = defaultrdest; 04640 } 04641 04642 if (create_addr(pds.peer, c, &sin, &cai)) { 04643 ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer); 04644 return -1; 04645 } 04646 04647 if (!pds.username && !ast_strlen_zero(cai.username)) 04648 pds.username = cai.username; 04649 if (!pds.password && !ast_strlen_zero(cai.secret)) 04650 pds.password = cai.secret; 04651 if (!pds.key && !ast_strlen_zero(cai.outkey)) 04652 pds.key = cai.outkey; 04653 if (!pds.context && !ast_strlen_zero(cai.peercontext)) 04654 pds.context = cai.peercontext; 04655 04656 /* Keep track of the context for outgoing calls too */ 04657 ast_copy_string(c->context, cai.context, sizeof(c->context)); 04658 04659 if (pds.port) 04660 sin.sin_port = htons(atoi(pds.port)); 04661 04662 l = c->cid.cid_num; 04663 n = c->cid.cid_name; 04664 04665 /* Now build request */ 04666 memset(&ied, 0, sizeof(ied)); 04667 04668 /* On new call, first IE MUST be IAX version of caller */ 04669 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 04670 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten); 04671 if (pds.options && strchr(pds.options, 'a')) { 04672 /* Request auto answer */ 04673 iax_ie_append(&ied, IAX_IE_AUTOANSWER); 04674 } 04675 04676 iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs); 04677 04678 if (l) { 04679 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l); 04680 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 04681 } else { 04682 if (n) 04683 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 04684 else 04685 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE); 04686 } 04687 04688 iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton); 04689 iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns); 04690 04691 if (n) 04692 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n); 04693 if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani) 04694 iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani); 04695 04696 if (!ast_strlen_zero(c->language)) 04697 iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language); 04698 if (!ast_strlen_zero(c->cid.cid_dnid)) 04699 iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid); 04700 if (!ast_strlen_zero(c->cid.cid_rdnis)) 04701 iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis); 04702 04703 if (pds.context) 04704 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context); 04705 04706 if (pds.username) 04707 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 04708 04709 if (cai.encmethods) 04710 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods); 04711 04712 ast_mutex_lock(&iaxsl[callno]); 04713 04714 if (!ast_strlen_zero(c->context)) 04715 ast_string_field_set(iaxs[callno], context, c->context); 04716 04717 if (pds.username) 04718 ast_string_field_set(iaxs[callno], username, pds.username); 04719 04720 iaxs[callno]->encmethods = cai.encmethods; 04721 04722 iaxs[callno]->adsi = cai.adsi; 04723 04724 ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret); 04725 ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest); 04726 04727 if (pds.key) 04728 ast_string_field_set(iaxs[callno], outkey, pds.key); 04729 if (pds.password) 04730 ast_string_field_set(iaxs[callno], secret, pds.password); 04731 04732 iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats); 04733 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability); 04734 iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe); 04735 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone)); 04736 04737 if (iaxs[callno]->maxtime) { 04738 /* Initialize pingtime and auto-congest time */ 04739 iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2; 04740 iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno)); 04741 } else if (autokill) { 04742 iaxs[callno]->pingtime = autokill / 2; 04743 iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno)); 04744 } 04745 04746 /* Check if there is an OSP token set by IAXCHANINFO function */ 04747 osp_token_ptr = iaxs[callno]->osptoken; 04748 if (!ast_strlen_zero(osp_token_ptr)) { 04749 if ((osp_token_length = strlen(osp_token_ptr)) <= IAX_MAX_OSPTOKEN_SIZE) { 04750 osp_block_index = 0; 04751 while (osp_token_length > 0) { 04752 osp_block_length = IAX_MAX_OSPBLOCK_SIZE < osp_token_length ? IAX_MAX_OSPBLOCK_SIZE : osp_token_length; 04753 osp_buffer[0] = osp_block_index; 04754 memcpy(osp_buffer + 1, osp_token_ptr, osp_block_length); 04755 iax_ie_append_raw(&ied, IAX_IE_OSPTOKEN, osp_buffer, osp_block_length + 1); 04756 osp_block_index++; 04757 osp_token_ptr += osp_block_length; 04758 osp_token_length -= osp_block_length; 04759 } 04760 } else 04761 ast_log(LOG_WARNING, "OSP token is too long\n"); 04762 } else if (iaxdebug) 04763 ast_debug(1, "OSP token is undefined\n"); 04764 04765 /* send the command using the appropriate socket for this peer */ 04766 iaxs[callno]->sockfd = cai.sockfd; 04767 04768 /* Add remote vars */ 04769 if (variablestore) { 04770 AST_LIST_HEAD(, ast_var_t) *variablelist = variablestore->data; 04771 ast_debug(1, "Found an IAX variable store on this channel\n"); 04772 AST_LIST_LOCK(variablelist); 04773 AST_LIST_TRAVERSE(variablelist, var, entries) { 04774 char tmp[256]; 04775 int i; 04776 ast_debug(1, "Found IAXVAR '%s' with value '%s' (to transmit)\n", ast_var_name(var), ast_var_value(var)); 04777 /* Automatically divide the value up into sized chunks */ 04778 for (i = 0; i < strlen(ast_var_value(var)); i += 255 - (strlen(ast_var_name(var)) + 1)) { 04779 snprintf(tmp, sizeof(tmp), "%s=%s", ast_var_name(var), ast_var_value(var) + i); 04780 iax_ie_append_str(&ied, IAX_IE_VARIABLE, tmp); 04781 } 04782 } 04783 AST_LIST_UNLOCK(variablelist); 04784 } 04785 04786 /* Transmit the string in a "NEW" request */ 04787 add_empty_calltoken_ie(iaxs[callno], &ied); /* this _MUST_ be the last ie added */ 04788 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 04789 04790 ast_mutex_unlock(&iaxsl[callno]); 04791 ast_setstate(c, AST_STATE_RINGING); 04792 04793 return 0; 04794 }
| static int iax2_canmatch | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
part of the IAX2 dial plan switch interface
Definition at line 12914 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_CANEXIST, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
12915 { 12916 int res = 0; 12917 struct iax2_dpcache *dp = NULL; 12918 #if 0 12919 ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 12920 #endif 12921 if ((priority != 1) && (priority != 2)) 12922 return 0; 12923 12924 AST_LIST_LOCK(&dpcache); 12925 if ((dp = find_cache(chan, data, context, exten, priority))) { 12926 if (dp->flags & CACHE_FLAG_CANEXIST) 12927 res = 1; 12928 } else { 12929 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 12930 } 12931 AST_LIST_UNLOCK(&dpcache); 12932 12933 return res; 12934 }
| static unsigned int iax2_datetime | ( | const char * | tz | ) | [static] |
Definition at line 4275 of file chan_iax2.c.
References ast_localtime(), ast_strlen_zero(), ast_tvnow(), ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, and ast_tm::tm_year.
Referenced by iax2_call(), and update_registry().
04276 { 04277 struct timeval t = ast_tvnow(); 04278 struct ast_tm tm; 04279 unsigned int tmp; 04280 ast_localtime(&t, &tm, ast_strlen_zero(tz) ? NULL : tz); 04281 tmp = (tm.tm_sec >> 1) & 0x1f; /* 5 bits of seconds */ 04282 tmp |= (tm.tm_min & 0x3f) << 5; /* 6 bits of minutes */ 04283 tmp |= (tm.tm_hour & 0x1f) << 11; /* 5 bits of hours */ 04284 tmp |= (tm.tm_mday & 0x1f) << 16; /* 5 bits of day of month */ 04285 tmp |= ((tm.tm_mon + 1) & 0xf) << 21; /* 4 bits of month */ 04286 tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */ 04287 return tmp; 04288 }
| static void iax2_destroy | ( | int | callno | ) | [static] |
Definition at line 3060 of file chan_iax2.c.
References ao2_ref, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_queue_hangup(), DEADLOCK_AVOIDANCE, iax2_destroy_helper(), chan_iax2_pvt::owner, chan_iax2_pvt::peercallno, remove_by_peercallno(), remove_by_transfercallno(), chan_iax2_pvt::transfercallno, and update_max_trunk().
Referenced by __attempt_transmit(), __iax2_poke_noanswer(), __unload_module(), delete_users(), iax2_do_register(), iax2_hangup(), iax2_poke_peer(), peer_destructor(), scheduled_destroy(), and socket_process().
03061 { 03062 struct chan_iax2_pvt *pvt = NULL; 03063 struct ast_channel *owner = NULL; 03064 03065 retry: 03066 if ((pvt = iaxs[callno])) { 03067 iax2_destroy_helper(pvt); 03068 } 03069 03070 owner = pvt ? pvt->owner : NULL; 03071 03072 if (owner) { 03073 if (ast_channel_trylock(owner)) { 03074 ast_debug(3, "Avoiding IAX destroy deadlock\n"); 03075 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 03076 goto retry; 03077 } 03078 } 03079 03080 if (!owner) { 03081 iaxs[callno] = NULL; 03082 } 03083 03084 if (pvt) { 03085 if (!owner) { 03086 pvt->owner = NULL; 03087 } else { 03088 /* If there's an owner, prod it to give up */ 03089 /* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup() 03090 * because we already hold the owner channel lock. */ 03091 ast_queue_hangup(owner); 03092 } 03093 03094 if (pvt->peercallno) { 03095 remove_by_peercallno(pvt); 03096 } 03097 03098 if (pvt->transfercallno) { 03099 remove_by_transfercallno(pvt); 03100 } 03101 03102 if (!owner) { 03103 ao2_ref(pvt, -1); 03104 pvt = NULL; 03105 } 03106 } 03107 03108 if (owner) { 03109 ast_channel_unlock(owner); 03110 } 03111 03112 if (callno & 0x4000) { 03113 update_max_trunk(); 03114 } 03115 }
| static void iax2_destroy_helper | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1517 of file chan_iax2.c.
References ao2_find, ast_atomic_fetchadd_int(), ast_clear_flag, AST_SCHED_DEL, AST_SCHED_DEL_SPINLOCK, ast_test_flag, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, chan_iax2_pvt::callno, iax2_user::curauthreq, IAX_MAXAUTHREQ, chan_iax2_pvt::initid, chan_iax2_pvt::jbid, chan_iax2_pvt::keyrotateid, chan_iax2_pvt::lagid, iax2_user::name, OBJ_POINTER, chan_iax2_pvt::pingid, user_unref(), and chan_iax2_pvt::username.
Referenced by iax2_destroy(), iax2_predestroy(), pvt_destructor(), and stop_stuff().
01518 { 01519 /* Decrement AUTHREQ count if needed */ 01520 if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) { 01521 struct iax2_user *user; 01522 struct iax2_user tmp_user = { 01523 .name = pvt->username, 01524 }; 01525 01526 user = ao2_find(users, &tmp_user, OBJ_POINTER); 01527 if (user) { 01528 ast_atomic_fetchadd_int(&user->curauthreq, -1); 01529 user_unref(user); 01530 } 01531 01532 ast_clear_flag(pvt, IAX_MAXAUTHREQ); 01533 } 01534 /* No more pings or lagrq's */ 01535 AST_SCHED_DEL_SPINLOCK(sched, pvt->pingid, &iaxsl[pvt->callno]); 01536 AST_SCHED_DEL_SPINLOCK(sched, pvt->lagid, &iaxsl[pvt->callno]); 01537 AST_SCHED_DEL(sched, pvt->autoid); 01538 AST_SCHED_DEL(sched, pvt->authid); 01539 AST_SCHED_DEL(sched, pvt->initid); 01540 AST_SCHED_DEL(sched, pvt->jbid); 01541 AST_SCHED_DEL(sched, pvt->keyrotateid); 01542 }
| static int iax2_devicestate | ( | void * | data | ) | [static] |
Part of the device state notification system ---.
Definition at line 13161 of file chan_iax2.c.
References iax2_peer::addr, ast_debug, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::defaddr, find_peer(), iax2_peer::historicms, iax2_peer::lastms, LOG_WARNING, iax2_peer::maxms, parse_dial_string(), parsed_dial_string::peer, and peer_unref().
13162 { 13163 struct parsed_dial_string pds; 13164 char *tmp = ast_strdupa(data); 13165 struct iax2_peer *p; 13166 int res = AST_DEVICE_INVALID; 13167 13168 memset(&pds, 0, sizeof(pds)); 13169 parse_dial_string(tmp, &pds); 13170 13171 if (ast_strlen_zero(pds.peer)) { 13172 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 13173 return res; 13174 } 13175 13176 ast_debug(3, "Checking device state for device %s\n", pds.peer); 13177 13178 /* SLD: FIXME: second call to find_peer during registration */ 13179 if (!(p = find_peer(pds.peer, 1))) 13180 return res; 13181 13182 res = AST_DEVICE_UNAVAILABLE; 13183 ast_debug(3, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n", 13184 pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms); 13185 13186 if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) && 13187 (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) { 13188 /* Peer is registered, or have default IP address 13189 and a valid registration */ 13190 if (p->historicms == 0 || p->historicms <= p->maxms) 13191 /* let the core figure out whether it is in use or not */ 13192 res = AST_DEVICE_UNKNOWN; 13193 } 13194 13195 peer_unref(p); 13196 13197 return res; 13198 }
| static int iax2_digit_begin | ( | struct ast_channel * | c, | |
| char | digit | |||
| ) | [static] |
Definition at line 3899 of file chan_iax2.c.
References AST_FRAME_DTMF_BEGIN, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03900 { 03901 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1); 03902 }
| static int iax2_digit_end | ( | struct ast_channel * | c, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 3904 of file chan_iax2.c.
References AST_FRAME_DTMF_END, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03905 { 03906 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1); 03907 }
| static int iax2_do_register | ( | struct iax2_registry * | reg | ) | [static] |
Definition at line 10979 of file chan_iax2.c.
References add_empty_calltoken_ie(), iax2_registry::addr, ast_debug, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax_ie_data::buf, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno_locked(), iax2_destroy(), iax2_do_register_s(), iax2_sched_replace(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, LOG_WARNING, NEW_FORCE, iax_ie_data::pos, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, send_command(), and iax2_registry::username.
Referenced by __iax2_do_register_s(), load_module(), and reload_config().
10980 { 10981 struct iax_ie_data ied; 10982 if (iaxdebug) 10983 ast_debug(1, "Sending registration request for '%s'\n", reg->username); 10984 10985 if (reg->dnsmgr && 10986 ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) { 10987 /* Maybe the IP has changed, force DNS refresh */ 10988 ast_dnsmgr_refresh(reg->dnsmgr); 10989 } 10990 10991 /* 10992 * if IP has Changed, free allocated call to create a new one with new IP 10993 * call has the pointer to IP and must be updated to the new one 10994 */ 10995 if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) { 10996 int callno = reg->callno; 10997 ast_mutex_lock(&iaxsl[callno]); 10998 iax2_destroy(callno); 10999 ast_mutex_unlock(&iaxsl[callno]); 11000 reg->callno = 0; 11001 } 11002 if (!reg->addr.sin_addr.s_addr) { 11003 if (iaxdebug) 11004 ast_debug(1, "Unable to send registration request for '%s' without IP address\n", reg->username); 11005 /* Setup the next registration attempt */ 11006 reg->expire = iax2_sched_replace(reg->expire, sched, 11007 (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 11008 return -1; 11009 } 11010 11011 if (!reg->callno) { 11012 ast_debug(3, "Allocate call number\n"); 11013 reg->callno = find_callno_locked(0, 0, ®->addr, NEW_FORCE, defaultsockfd, 0); 11014 if (reg->callno < 1) { 11015 ast_log(LOG_WARNING, "Unable to create call for registration\n"); 11016 return -1; 11017 } else 11018 ast_debug(3, "Registration created on call %d\n", reg->callno); 11019 iaxs[reg->callno]->reg = reg; 11020 ast_mutex_unlock(&iaxsl[reg->callno]); 11021 } 11022 /* Setup the next registration a little early */ 11023 reg->expire = iax2_sched_replace(reg->expire, sched, 11024 (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 11025 /* Send the request */ 11026 memset(&ied, 0, sizeof(ied)); 11027 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 11028 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 11029 add_empty_calltoken_ie(iaxs[reg->callno], &ied); /* this _MUST_ be the last ie added */ 11030 send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 11031 reg->regstate = REG_STATE_REGSENT; 11032 return 0; 11033 }
| static int iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 7685 of file chan_iax2.c.
References __iax2_do_register_s(), and schedule_action.
Referenced by iax2_ack_registry(), and iax2_do_register().
07686 { 07687 #ifdef SCHED_MULTITHREADED 07688 if (schedule_action(__iax2_do_register_s, data)) 07689 #endif 07690 __iax2_do_register_s(data); 07691 return 0; 07692 }
| static void iax2_dprequest | ( | struct iax2_dpcache * | dp, | |
| int | callno | |||
| ) | [static] |
Definition at line 8430 of file chan_iax2.c.
References AST_FRAME_IAX, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, iax2_dpcache::exten, iax2_dpcache::flags, iax2_sched_replace(), IAX_COMMAND_DPREQ, iax_ie_append_str(), IAX_IE_CALLED_NUMBER, iax_ie_data::pos, and send_command().
Referenced by find_cache(), and socket_process().
08431 { 08432 struct iax_ie_data ied; 08433 /* Auto-hangup with 30 seconds of inactivity */ 08434 iaxs[callno]->autoid = iax2_sched_replace(iaxs[callno]->autoid, 08435 sched, 30000, auto_hangup, (void *)(long)callno); 08436 memset(&ied, 0, sizeof(ied)); 08437 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten); 08438 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1); 08439 dp->flags |= CACHE_FLAG_TRANSMITTED; 08440 }
| static void * iax2_dup_variable_datastore | ( | void * | old | ) | [static] |
Definition at line 1114 of file chan_iax2.c.
References ast_calloc, AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_var_assign(), ast_var_name(), ast_var_value(), and LOG_ERROR.
01115 { 01116 AST_LIST_HEAD(, ast_var_t) *oldlist = old, *newlist; 01117 struct ast_var_t *oldvar, *newvar; 01118 01119 newlist = ast_calloc(sizeof(*newlist), 1); 01120 if (!newlist) { 01121 ast_log(LOG_ERROR, "Unable to duplicate iax2 variables\n"); 01122 return NULL; 01123 } 01124 01125 AST_LIST_HEAD_INIT(newlist); 01126 AST_LIST_LOCK(oldlist); 01127 AST_LIST_TRAVERSE(oldlist, oldvar, entries) { 01128 newvar = ast_var_assign(ast_var_name(oldvar), ast_var_value(oldvar)); 01129 if (newvar) 01130 AST_LIST_INSERT_TAIL(newlist, newvar, entries); 01131 else 01132 ast_log(LOG_ERROR, "Unable to duplicate iax2 variable '%s'\n", ast_var_name(oldvar)); 01133 } 01134 AST_LIST_UNLOCK(oldlist); 01135 return newlist; 01136 }
| static int iax2_exec | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Execute IAX2 dialplan switch.
Definition at line 12960 of file chan_iax2.c.
References ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_verb, CACHE_FLAG_EXISTS, find_cache(), iax2_dpcache::flags, LOG_NOTICE, LOG_WARNING, pbx_builtin_getvar_helper(), pbx_exec(), and pbx_findapp().
12961 { 12962 char odata[256]; 12963 char req[256]; 12964 char *ncontext; 12965 struct iax2_dpcache *dp = NULL; 12966 struct ast_app *dial = NULL; 12967 #if 0 12968 ast_log(LOG_NOTICE, "iax2_exec: con: %s, exten: %s, pri: %d, cid: %s, data: %s, newstack: %d\n", context, exten, priority, callerid ? callerid : "<unknown>", data, newstack); 12969 #endif 12970 if (priority == 2) { 12971 /* Indicate status, can be overridden in dialplan */ 12972 const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS"); 12973 if (dialstatus) { 12974 dial = pbx_findapp(dialstatus); 12975 if (dial) 12976 pbx_exec(chan, dial, ""); 12977 } 12978 return -1; 12979 } else if (priority != 1) 12980 return -1; 12981 12982 AST_LIST_LOCK(&dpcache); 12983 if ((dp = find_cache(chan, data, context, exten, priority))) { 12984 if (dp->flags & CACHE_FLAG_EXISTS) { 12985 ast_copy_string(odata, data, sizeof(odata)); 12986 ncontext = strchr(odata, '/'); 12987 if (ncontext) { 12988 *ncontext = '\0'; 12989 ncontext++; 12990 snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext); 12991 } else { 12992 snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten); 12993 } 12994 ast_verb(3, "Executing Dial('%s')\n", req); 12995 } else { 12996 AST_LIST_UNLOCK(&dpcache); 12997 ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data); 12998 return -1; 12999 } 13000 } 13001 AST_LIST_UNLOCK(&dpcache); 13002 13003 if ((dial = pbx_findapp("Dial"))) 13004 return pbx_exec(chan, dial, req); 13005 else 13006 ast_log(LOG_WARNING, "No dial application registered\n"); 13007 13008 return -1; 13009 }
| static int iax2_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Part of the IAX2 switch interface.
Definition at line 12891 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_EXISTS, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
12892 { 12893 int res = 0; 12894 struct iax2_dpcache *dp = NULL; 12895 #if 0 12896 ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 12897 #endif 12898 if ((priority != 1) && (priority != 2)) 12899 return 0; 12900 12901 AST_LIST_LOCK(&dpcache); 12902 if ((dp = find_cache(chan, data, context, exten, priority))) { 12903 if (dp->flags & CACHE_FLAG_EXISTS) 12904 res = 1; 12905 } else { 12906 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 12907 } 12908 AST_LIST_UNLOCK(&dpcache); 12909 12910 return res; 12911 }
| static int iax2_fixup | ( | struct ast_channel * | oldchannel, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 3926 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, chan_iax2_pvt::owner, PTR_TO_CALLNO, and ast_channel::tech_pvt.
03927 { 03928 unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt); 03929 ast_mutex_lock(&iaxsl[callno]); 03930 if (iaxs[callno]) 03931 iaxs[callno]->owner = newchan; 03932 else 03933 ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n"); 03934 ast_mutex_unlock(&iaxsl[callno]); 03935 return 0; 03936 }
| static void iax2_frame_free | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 1544 of file chan_iax2.c.
References AST_SCHED_DEL, iax_frame_free(), and iax_frame::retrans.
Referenced by __attempt_transmit(), __do_deliver(), __get_from_jb(), complete_transfer(), pvt_destructor(), resend_with_token(), and schedule_delivery().
01545 { 01546 AST_SCHED_DEL(sched, fr->retrans); 01547 iax_frame_free(fr); 01548 }
| static void iax2_free_variable_datastore | ( | void * | old | ) | [static] |
Definition at line 1138 of file chan_iax2.c.
References ast_free, AST_LIST_HEAD, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.
01139 { 01140 AST_LIST_HEAD(, ast_var_t) *oldlist = old; 01141 struct ast_var_t *oldvar; 01142 01143 AST_LIST_LOCK(oldlist); 01144 while ((oldvar = AST_LIST_REMOVE_HEAD(oldlist, entries))) { 01145 ast_free(oldvar); 01146 } 01147 AST_LIST_UNLOCK(oldlist); 01148 AST_LIST_HEAD_DESTROY(oldlist); 01149 ast_free(oldlist); 01150 }
| static int iax2_getpeername | ( | struct sockaddr_in | sin, | |
| char * | host, | |||
| int | len | |||
| ) | [static] |
Definition at line 1485 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next, ast_copy_string(), iax2_peer::name, peer_unref(), and realtime_peer().
Referenced by __find_callno().
01486 { 01487 struct iax2_peer *peer = NULL; 01488 int res = 0; 01489 struct ao2_iterator i; 01490 01491 i = ao2_iterator_init(peers, 0); 01492 while ((peer = ao2_iterator_next(&i))) { 01493 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 01494 (peer->addr.sin_port == sin.sin_port)) { 01495 ast_copy_string(host, peer->name, len); 01496 peer_unref(peer); 01497 res = 1; 01498 break; 01499 } 01500 peer_unref(peer); 01501 } 01502 01503 if (!peer) { 01504 peer = realtime_peer(NULL, &sin); 01505 if (peer) { 01506 ast_copy_string(host, peer->name, len); 01507 peer_unref(peer); 01508 res = 1; 01509 } 01510 } 01511 01512 return res; 01513 }
| static int iax2_getpeertrunk | ( | struct sockaddr_in | sin | ) | [static] |
Definition at line 5216 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next, ast_test_flag, IAX_TRUNK, and peer_unref().
Referenced by check_access().
05217 { 05218 struct iax2_peer *peer; 05219 int res = 0; 05220 struct ao2_iterator i; 05221 05222 i = ao2_iterator_init(peers, 0); 05223 while ((peer = ao2_iterator_next(&i))) { 05224 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 05225 (peer->addr.sin_port == sin.sin_port)) { 05226 res = ast_test_flag(peer, IAX_TRUNK); 05227 peer_unref(peer); 05228 break; 05229 } 05230 peer_unref(peer); 05231 } 05232 05233 return res; 05234 }
| static int iax2_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 4796 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_test_flag, ast_verb, iax_ie_data::buf, CALLNO_TO_PTR, ast_channel::hangupcause, iax2_destroy(), iax2_predestroy(), IAX_ALREADYGONE, IAX_COMMAND_HANGUP, iax_ie_append_byte(), IAX_IE_CAUSECODE, LOG_ERROR, LOG_WARNING, iax_ie_data::pos, PTR_TO_CALLNO, scheduled_destroy(), send_command_final(), and ast_channel::tech_pvt.
04797 { 04798 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04799 struct iax_ie_data ied; 04800 int alreadygone; 04801 memset(&ied, 0, sizeof(ied)); 04802 ast_mutex_lock(&iaxsl[callno]); 04803 if (callno && iaxs[callno]) { 04804 ast_debug(1, "We're hanging up %s now...\n", c->name); 04805 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE); 04806 /* Send the hangup unless we have had a transmission error or are already gone */ 04807 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause); 04808 if (!iaxs[callno]->error && !alreadygone) { 04809 if (send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1)) { 04810 ast_log(LOG_WARNING, "No final packet could be sent for callno %d\n", callno); 04811 } 04812 if (!iaxs[callno]) { 04813 ast_mutex_unlock(&iaxsl[callno]); 04814 return 0; 04815 } 04816 } 04817 /* Explicitly predestroy it */ 04818 iax2_predestroy(callno); 04819 /* If we were already gone to begin with, destroy us now */ 04820 if (iaxs[callno] && alreadygone) { 04821 ast_debug(1, "Really destroying %s now...\n", c->name); 04822 iax2_destroy(callno); 04823 } else if (iaxs[callno]) { 04824 if (ast_sched_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno)) < 0) { 04825 ast_log(LOG_ERROR, "Unable to schedule iax2 callno %d destruction?!! Destroying immediately.\n", callno); 04826 iax2_destroy(callno); 04827 } 04828 } 04829 } else if (c->tech_pvt) { 04830 /* If this call no longer exists, but the channel still 04831 * references it we need to set the channel's tech_pvt to null 04832 * to avoid ast_channel_free() trying to free it. 04833 */ 04834 c->tech_pvt = NULL; 04835 } 04836 ast_mutex_unlock(&iaxsl[callno]); 04837 ast_verb(3, "Hungup '%s'\n", c->name); 04838 return 0; 04839 }
| static int iax2_indicate | ( | struct ast_channel * | c, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 5159 of file chan_iax2.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_CONTROL, ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::mohinterpret, PTR_TO_CALLNO, send_command(), ast_channel::tech_pvt, and wait_for_peercallno().
05160 { 05161 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 05162 struct chan_iax2_pvt *pvt; 05163 int res = 0; 05164 05165 if (iaxdebug) 05166 ast_debug(1, "Indicating condition %d\n", condition); 05167 05168 ast_mutex_lock(&iaxsl[callno]); 05169 pvt = iaxs[callno]; 05170 05171 if (wait_for_peercallno(pvt)) { 05172 res = -1; 05173 goto done; 05174 } 05175 05176 switch (condition) { 05177 case AST_CONTROL_HOLD: 05178 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 05179 ast_moh_start(c, data, pvt->mohinterpret); 05180 goto done; 05181 } 05182 break; 05183 case AST_CONTROL_UNHOLD: 05184 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 05185 ast_moh_stop(c); 05186 goto done; 05187 } 05188 } 05189 05190 res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1); 05191 05192 done: 05193 ast_mutex_unlock(&iaxsl[callno]); 05194 05195 return res; 05196 }
| static int iax2_key_rotate | ( | const void * | vpvt | ) | [static] |
Definition at line 4911 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_sched_add(), iax_ie_data::buf, build_ecx_key(), chan_iax2_pvt::callno, IAX_COMMAND_RTKEY, IAX_DEBUGDIGEST, iax_ie_append_raw(), IAX_IE_CHALLENGE, chan_iax2_pvt::keyrotateid, MD5Final(), MD5Init(), MD5Update(), iax_ie_data::pos, and send_command().
Referenced by iax2_send().
04912 { 04913 int res = 0; 04914 struct chan_iax2_pvt *pvt = (void *) vpvt; 04915 struct MD5Context md5; 04916 char key[17] = ""; 04917 struct iax_ie_data ied = { 04918 .pos = 0, 04919 }; 04920 04921 ast_mutex_lock(&iaxsl[pvt->callno]); 04922 pvt->keyrotateid = 04923 ast_sched_add(sched, 120000 + (ast_random() % 180001), iax2_key_rotate, vpvt); 04924 04925 snprintf(key, sizeof(key), "%lX", ast_random()); 04926 04927 MD5Init(&md5); 04928 MD5Update(&md5, (unsigned char *) key, strlen(key)); 04929 MD5Final((unsigned char *) key, &md5); 04930 04931 IAX_DEBUGDIGEST("Sending", key); 04932 04933 iax_ie_append_raw(&ied, IAX_IE_CHALLENGE, key, 16); 04934 04935 res = send_command(pvt, AST_FRAME_IAX, IAX_COMMAND_RTKEY, 0, ied.buf, ied.pos, -1); 04936 04937 build_ecx_key((unsigned char *) key, pvt); 04938 04939 ast_mutex_unlock(&iaxsl[pvt->callno]); 04940 04941 return res; 04942 }
| static int iax2_matchmore | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Part of the IAX2 Switch interface.
Definition at line 12937 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_MATCHMORE, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
12938 { 12939 int res = 0; 12940 struct iax2_dpcache *dp = NULL; 12941 #if 0 12942 ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 12943 #endif 12944 if ((priority != 1) && (priority != 2)) 12945 return 0; 12946 12947 AST_LIST_LOCK(&dpcache); 12948 if ((dp = find_cache(chan, data, context, exten, priority))) { 12949 if (dp->flags & CACHE_FLAG_MATCHMORE) 12950 res = 1; 12951 } else { 12952 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 12953 } 12954 AST_LIST_UNLOCK(&dpcache); 12955 12956 return res; 12957 }
| static int iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 11183 of file chan_iax2.c.
References __iax2_poke_noanswer(), peer_unref(), iax2_peer::pokeexpire, and schedule_action.
Referenced by iax2_poke_peer().
11184 { 11185 struct iax2_peer *peer = (struct iax2_peer *)data; 11186 peer->pokeexpire = -1; 11187 #ifdef SCHED_MULTITHREADED 11188 if (schedule_action(__iax2_poke_noanswer, data)) 11189 #endif 11190 __iax2_poke_noanswer(data); 11191 peer_unref(peer); 11192 return 0; 11193 }
| static int iax2_poke_peer | ( | struct iax2_peer * | peer, | |
| int | heldcall | |||
| ) | [static] |
Definition at line 11204 of file chan_iax2.c.
References add_empty_calltoken_ie(), iax2_peer::addr, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), iax_ie_data::buf, iax2_peer::callno, DEFAULT_MAXMS, iax2_peer::dnsmgr, find_callno(), iax2_peer::historicms, iax2_destroy(), iax2_poke_noanswer(), iax2_sched_add(), IAX_COMMAND_POKE, iax2_peer::lastms, LOG_NOTICE, LOG_WARNING, iax2_peer::maxms, iax2_peer::name, NEW_FORCE, peer_ref(), peer_unref(), chan_iax2_pvt::peerpoke, chan_iax2_pvt::pingtime, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax_ie_data::pos, send_command(), and iax2_peer::sockfd.
Referenced by __iax2_poke_peer_s(), iax2_poke_peer_cb(), poke_all_peers(), reg_source_db(), and update_registry().
11205 { 11206 int callno; 11207 if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) { 11208 /* IF we have no IP without dnsmgr, or this isn't to be monitored, return 11209 immediately after clearing things out */ 11210 peer->lastms = 0; 11211 peer->historicms = 0; 11212 peer->pokeexpire = -1; 11213 peer->callno = 0; 11214 return 0; 11215 } 11216 11217 /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */ 11218 if ((callno = peer->callno) > 0) { 11219 ast_log(LOG_NOTICE, "Still have a callno...\n"); 11220 ast_mutex_lock(&iaxsl[callno]); 11221 iax2_destroy(callno); 11222 ast_mutex_unlock(&iaxsl[callno]); 11223 } 11224 if (heldcall) 11225 ast_mutex_unlock(&iaxsl[heldcall]); 11226 callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0); 11227 if (heldcall) 11228 ast_mutex_lock(&iaxsl[heldcall]); 11229 if (peer->callno < 1) { 11230 ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name); 11231 return -1; 11232 } 11233 11234 /* Speed up retransmission times for this qualify call */ 11235 iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1; 11236 iaxs[peer->callno]->peerpoke = peer; 11237 11238 if (peer->pokeexpire > -1) { 11239 if (!ast_sched_del(sched, peer->pokeexpire)) { 11240 peer->pokeexpire = -1; 11241 peer_unref(peer); 11242 } 11243 } 11244 11245 /* Queue up a new task to handle no reply */ 11246 /* If the host is already unreachable then use the unreachable interval instead */ 11247 if (peer->lastms < 0) 11248 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer)); 11249 else 11250 peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer)); 11251 11252 if (peer->pokeexpire == -1) 11253 peer_unref(peer); 11254 11255 /* And send the poke */ 11256 ast_mutex_lock(&iaxsl[callno]); 11257 if (iaxs[callno]) { 11258 struct iax_ie_data ied = { 11259 .buf = { 0 }, 11260 .pos = 0, 11261 }; 11262 add_empty_calltoken_ie(iaxs[callno], &ied); /* this _MUST_ be the last ie added */ 11263 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, ied.buf, ied.pos, -1); 11264 } 11265 ast_mutex_unlock(&iaxsl[callno]); 11266 11267 return 0; 11268 }
| static int iax2_poke_peer_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 11195 of file chan_iax2.c.
References iax2_poke_peer().
Referenced by load_module().
11196 { 11197 struct iax2_peer *peer = obj; 11198 11199 iax2_poke_peer(peer, 0); 11200 11201 return 0; 11202 }
| static int iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 8470 of file chan_iax2.c.
References __iax2_poke_peer_s(), iax2_peer::pokeexpire, and schedule_action.
Referenced by __iax2_poke_noanswer(), and socket_process().
08471 { 08472 struct iax2_peer *peer = (struct iax2_peer *)data; 08473 peer->pokeexpire = -1; 08474 #ifdef SCHED_MULTITHREADED 08475 if (schedule_action(__iax2_poke_peer_s, data)) 08476 #endif 08477 __iax2_poke_peer_s(data); 08478 return 0; 08479 }
| static int iax2_predestroy | ( | int | callno | ) | [static] |
Definition at line 3037 of file chan_iax2.c.
References ast_module_unref(), ast_set_flag, ast_test_flag, iax2_destroy_helper(), iax2_queue_hangup(), IAX_ALREADYGONE, chan_iax2_pvt::owner, and ast_channel::tech_pvt.
Referenced by iax2_hangup(), and send_command_final().
03038 { 03039 struct ast_channel *c = NULL; 03040 struct chan_iax2_pvt *pvt = iaxs[callno]; 03041 03042 if (!pvt) 03043 return -1; 03044 03045 if (!ast_test_flag(pvt, IAX_ALREADYGONE)) { 03046 iax2_destroy_helper(pvt); 03047 ast_set_flag(pvt, IAX_ALREADYGONE); 03048 } 03049 03050 if ((c = pvt->owner)) { 03051 c->tech_pvt = NULL; 03052 iax2_queue_hangup(callno); 03053 pvt->owner = NULL; 03054 ast_module_unref(ast_module_info->self); 03055 } 03056 03057 return 0; 03058 }
| static void * iax2_process_thread | ( | void * | data | ) | [static] |
Definition at line 10850 of file chan_iax2.c.
References iax2_thread::actions, ast_atomic_fetchadd_int(), ast_cond_timedwait(), ast_cond_wait(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_tvadd(), ast_tvnow(), iax2_thread::checktime, iax2_thread::cond, iax2_thread::curfunc, handle_deferred_full_frames(), iax2_process_thread_cleanup(), IAX_IOSTATE_IDLE, IAX_IOSTATE_PROCESSING, IAX_IOSTATE_READY, IAX_IOSTATE_SCHEDREADY, IAX_THREAD_TYPE_DYNAMIC, iaxactivethreadcount, iaxdynamicthreadcount, iax2_thread::init_cond, iax2_thread::init_lock, insert_idle_thread(), iax2_thread::iostate, iax2_thread::lock, iax2_thread::scheddata, iax2_thread::schedfunc, signal_condition(), socket_process(), thread, and iax2_thread::type.
Referenced by find_idle_thread(), and start_network_thread().
10851 { 10852 struct iax2_thread *thread = data; 10853 struct timeval wait; 10854 struct timespec ts; 10855 int put_into_idle = 0; 10856 int first_time = 1; 10857 10858 ast_atomic_fetchadd_int(&iaxactivethreadcount,1); 10859 pthread_cleanup_push(iax2_process_thread_cleanup, data); 10860 for(;;) { 10861 /* Wait for something to signal us to be awake */ 10862 ast_mutex_lock(&thread->lock); 10863 10864 /* Flag that we're ready to accept signals */ 10865 if (first_time) { 10866 signal_condition(&thread->init_lock, &thread->init_cond); 10867 first_time = 0; 10868 } 10869 10870 /* Put into idle list if applicable */ 10871 if (put_into_idle) 10872 insert_idle_thread(thread); 10873 10874 if (thread->type == IAX_THREAD_TYPE_DYNAMIC) { 10875 struct iax2_thread *t = NULL; 10876 /* Wait to be signalled or time out */ 10877 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 10878 ts.tv_sec = wait.tv_sec; 10879 ts.tv_nsec = wait.tv_usec * 1000; 10880 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) { 10881 /* This thread was never put back into the available dynamic 10882 * thread list, so just go away. */ 10883 if (!put_into_idle) { 10884 ast_mutex_unlock(&thread->lock); 10885 break; 10886 } 10887 AST_LIST_LOCK(&dynamic_list); 10888 /* Account for the case where this thread is acquired *right* after a timeout */ 10889 if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list))) 10890 ast_atomic_fetchadd_int(&iaxdynamicthreadcount, -1); 10891 AST_LIST_UNLOCK(&dynamic_list); 10892 if (t) { 10893 /* This dynamic thread timed out waiting for a task and was 10894 * not acquired immediately after the timeout, 10895 * so it's time to go away. */ 10896 ast_mutex_unlock(&thread->lock); 10897 break; 10898 } 10899 /* Someone grabbed our thread *right* after we timed out. 10900 * Wait for them to set us up with something to do and signal 10901 * us to continue. */ 10902 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 10903 ts.tv_sec = wait.tv_sec; 10904 ts.tv_nsec = wait.tv_usec * 1000; 10905 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) 10906 { 10907 ast_mutex_unlock(&thread->lock); 10908 break; 10909 } 10910 } 10911 } else { 10912 ast_cond_wait(&thread->cond, &thread->lock); 10913 } 10914 10915 /* Go back into our respective list */ 10916 put_into_idle = 1; 10917 10918 ast_mutex_unlock(&thread->lock); 10919 10920 if (thread->iostate == IAX_IOSTATE_IDLE) 10921 continue; 10922 10923 /* Add ourselves to the active list now */ 10924 AST_LIST_LOCK(&active_list); 10925 AST_LIST_INSERT_HEAD(&active_list, thread, list); 10926 AST_LIST_UNLOCK(&active_list); 10927 10928 /* See what we need to do */ 10929 switch(thread->iostate) { 10930 case IAX_IOSTATE_READY: 10931 thread->actions++; 10932 thread->iostate = IAX_IOSTATE_PROCESSING; 10933 socket_process(thread); 10934 handle_deferred_full_frames(thread); 10935 break; 10936 case IAX_IOSTATE_SCHEDREADY: 10937 thread->actions++; 10938 thread->iostate = IAX_IOSTATE_PROCESSING; 10939 #ifdef SCHED_MULTITHREADED 10940 thread->schedfunc(thread->scheddata); 10941 #endif 10942 default: 10943 break; 10944 } 10945 time(&thread->checktime); 10946 thread->iostate = IAX_IOSTATE_IDLE; 10947 #ifdef DEBUG_SCHED_MULTITHREAD 10948 thread->curfunc[0]='\0'; 10949 #endif 10950 10951 /* Now... remove ourselves from the active list, and return to the idle list */ 10952 AST_LIST_LOCK(&active_list); 10953 AST_LIST_REMOVE(&active_list, thread, list); 10954 AST_LIST_UNLOCK(&active_list); 10955 10956 /* Make sure another frame didn't sneak in there after we thought we were done. */ 10957 handle_deferred_full_frames(thread); 10958 } 10959 10960 /*!\note For some reason, idle threads are exiting without being removed 10961 * from an idle list, which is causing memory corruption. Forcibly remove 10962 * it from the list, if it's there. 10963 */ 10964 AST_LIST_LOCK(&idle_list); 10965 AST_LIST_REMOVE(&idle_list, thread, list); 10966 AST_LIST_UNLOCK(&idle_list); 10967 10968 AST_LIST_LOCK(&dynamic_list); 10969 AST_LIST_REMOVE(&dynamic_list, thread, list); 10970 AST_LIST_UNLOCK(&dynamic_list); 10971 10972 /* I am exiting here on my own volition, I need to clean up my own data structures 10973 * Assume that I am no longer in any of the lists (idle, active, or dynamic) 10974 */ 10975 pthread_cleanup_pop(1); 10976 return NULL; 10977 }
| static void iax2_process_thread_cleanup | ( | void * | data | ) | [static] |
Definition at line 10839 of file chan_iax2.c.
References ast_atomic_dec_and_test(), ast_cond_destroy(), ast_free, ast_mutex_destroy(), iax2_thread::cond, iaxactivethreadcount, iax2_thread::init_cond, iax2_thread::init_lock, iax2_thread::lock, and thread.
Referenced by iax2_process_thread().
10840 { 10841 struct iax2_thread *thread = data; 10842 ast_mutex_destroy(&thread->lock); 10843 ast_cond_destroy(&thread->cond); 10844 ast_mutex_destroy(&thread->init_lock); 10845 ast_cond_destroy(&thread->init_cond); 10846 ast_free(thread); 10847 ast_atomic_dec_and_test(&iaxactivethreadcount); 10848 }
| static int iax2_provision | ( | struct sockaddr_in * | end, | |
| int | sockfd, | |||
| char * | dest, | |||
| const char * | template, | |||
| int | force | |||
| ) | [static] |
Definition at line 11035 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_mutex_unlock(), ast_set_flag, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, create_addr(), find_callno_locked(), iax2_sched_replace(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), NEW_FORCE, iax_ie_data::pos, send_command(), and create_addr_info::sockfd.
Referenced by check_provisioning(), handle_cli_iax2_provision(), and iax2_prov_app().
11036 { 11037 /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning 11038 is found for template */ 11039 struct iax_ie_data provdata; 11040 struct iax_ie_data ied; 11041 unsigned int sig; 11042 struct sockaddr_in sin; 11043 int callno; 11044 struct create_addr_info cai; 11045 11046 memset(&cai, 0, sizeof(cai)); 11047 11048 ast_debug(1, "Provisioning '%s' from template '%s'\n", dest, template); 11049 11050 if (iax_provision_build(&provdata, &sig, template, force)) { 11051 ast_debug(1, "No provisioning found for template '%s'\n", template); 11052 return 0; 11053 } 11054 11055 if (end) { 11056 memcpy(&sin, end, sizeof(sin)); 11057 cai.sockfd = sockfd; 11058 } else if (create_addr(dest, NULL, &sin, &cai)) 11059 return -1; 11060 11061 /* Build the rest of the message */ 11062 memset(&ied, 0, sizeof(ied)); 11063 iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos); 11064 11065 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 11066 if (!callno) 11067 return -1; 11068 11069 if (iaxs[callno]) { 11070 /* Schedule autodestruct in case they don't ever give us anything back */ 11071 iaxs[callno]->autoid = iax2_sched_replace(iaxs[callno]->autoid, 11072 sched, 15000, auto_hangup, (void *)(long)callno); 11073 ast_set_flag(iaxs[callno], IAX_PROVISION); 11074 /* Got a call number now, so go ahead and send the provisioning information */ 11075 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1); 11076 } 11077 ast_mutex_unlock(&iaxsl[callno]); 11078 11079 return 1; 11080 }
| static int iax2_queue_control_data | ( | int | callno, | |
| enum ast_control_frame_type | control, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Queue a control frame on the ast_channel owner.
This function queues a control frame on the owner of the IAX2 pvt struct that is active for the given call number.
Definition at line 2662 of file chan_iax2.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_control_data(), and DEADLOCK_AVOIDANCE.
Referenced by socket_process().
02664 { 02665 for (;;) { 02666 if (iaxs[callno] && iaxs[callno]->owner) { 02667 if (ast_channel_trylock(iaxs[callno]->owner)) { 02668 /* Avoid deadlock by pausing and trying again */ 02669 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 02670 } else { 02671 ast_queue_control_data(iaxs[callno]->owner, control, data, datalen); 02672 ast_channel_unlock(iaxs[callno]->owner); 02673 break; 02674 } 02675 } else 02676 break; 02677 } 02678 return 0; 02679 }
| static int iax2_queue_frame | ( | int | callno, | |
| struct ast_frame * | f | |||
| ) | [static] |
Queue a frame to a call's owning asterisk channel.
Definition at line 2600 of file chan_iax2.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), and DEADLOCK_AVOIDANCE.
Referenced by __attempt_transmit(), __auto_congest(), __do_deliver(), __get_from_jb(), and socket_process().
02601 { 02602 for (;;) { 02603 if (iaxs[callno] && iaxs[callno]->owner) { 02604 if (ast_channel_trylock(iaxs[callno]->owner)) { 02605 /* Avoid deadlock by pausing and trying again */ 02606 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 02607 } else { 02608 ast_queue_frame(iaxs[callno]->owner, f); 02609 ast_channel_unlock(iaxs[callno]->owner); 02610 break; 02611 } 02612 } else 02613 break; 02614 } 02615 return 0; 02616 }
| static int iax2_queue_hangup | ( | int | callno | ) | [static] |
Queue a hangup frame on the ast_channel owner.
This function queues a hangup frame on the owner of the IAX2 pvt struct that is active for the given call number.
Definition at line 2631 of file chan_iax2.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_hangup(), and DEADLOCK_AVOIDANCE.
Referenced by iax2_predestroy().
02632 { 02633 for (;;) { 02634 if (iaxs[callno] && iaxs[callno]->owner) { 02635 if (ast_channel_trylock(iaxs[callno]->owner)) { 02636 /* Avoid deadlock by pausing and trying again */ 02637 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 02638 } else { 02639 ast_queue_hangup(iaxs[callno]->owner); 02640 ast_channel_unlock(iaxs[callno]->owner); 02641 break; 02642 } 02643 } else 02644 break; 02645 } 02646 return 0; 02647 }
| static struct ast_frame * iax2_read | ( | struct ast_channel * | c | ) | [static, read] |
Definition at line 4905 of file chan_iax2.c.
References ast_log(), ast_null_frame, and LOG_NOTICE.
04906 { 04907 ast_log(LOG_NOTICE, "I should never be called!\n"); 04908 return &ast_null_frame; 04909 }
| static int iax2_register | ( | const char * | value, | |
| int | lineno | |||
| ) | [static] |
Definition at line 7925 of file chan_iax2.c.
References ast_copy_string(), ast_log(), copy(), hostname, iax2_append_register(), LOG_WARNING, secret, and strsep().
Referenced by set_config().
07926 { 07927 char copy[256]; 07928 char *username, *hostname, *secret; 07929 char *porta; 07930 char *stringp=NULL; 07931 07932 if (!value) 07933 return -1; 07934 07935 ast_copy_string(copy, value, sizeof(copy)); 07936 stringp = copy; 07937 username = strsep(&stringp, "@"); 07938 hostname = strsep(&stringp, "@"); 07939 07940 if (!hostname) { 07941 ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno); 07942 return -1; 07943 } 07944 07945 stringp = username; 07946 username = strsep(&stringp, ":"); 07947 secret = strsep(&stringp, ":"); 07948 stringp = hostname; 07949 hostname = strsep(&stringp, ":"); 07950 porta = strsep(&stringp, ":"); 07951 07952 if (porta && !atoi(porta)) { 07953 ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno); 07954 return -1; 07955 } 07956 07957 return iax2_append_register(hostname, username, secret, porta); 07958 }
| static struct ast_channel * iax2_request | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 11280 of file chan_iax2.c.
References ast_best_codec(), AST_CAUSE_CONGESTION, AST_CAUSE_UNREGISTERED, ast_copy_flags, ast_getformatname(), ast_hangup(), ast_iax2_new(), ast_log(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_translator_best_choice(), create_addr_info::capability, create_addr(), find_callno_locked(), create_addr_info::found, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, LOG_WARNING, make_trunk(), create_addr_info::maxtime, chan_iax2_pvt::maxtime, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), parsed_dial_string::peer, parsed_dial_string::port, ast_channel::readformat, create_addr_info::sockfd, and ast_channel::writeformat.
11281 { 11282 int callno; 11283 int res; 11284 int fmt, native; 11285 struct sockaddr_in sin; 11286 struct ast_channel *c; 11287 struct parsed_dial_string pds; 11288 struct create_addr_info cai; 11289 char *tmpstr; 11290 11291 memset(&pds, 0, sizeof(pds)); 11292 tmpstr = ast_strdupa(data); 11293 parse_dial_string(tmpstr, &pds); 11294 11295 if (ast_strlen_zero(pds.peer)) { 11296 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 11297 return NULL; 11298 } 11299 11300 memset(&cai, 0, sizeof(cai)); 11301 cai.capability = iax2_capability; 11302 11303 ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 11304 11305 /* Populate our address from the given */ 11306 if (create_addr(pds.peer, NULL, &sin, &cai)) { 11307 *cause = AST_CAUSE_UNREGISTERED; 11308 return NULL; 11309 } 11310 11311 if (pds.port) 11312 sin.sin_port = htons(atoi(pds.port)); 11313 11314 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 11315 if (callno < 1) { 11316 ast_log(LOG_WARNING, "Unable to create call\n"); 11317 *cause = AST_CAUSE_CONGESTION; 11318 return NULL; 11319 } 11320 11321 /* If this is a trunk, update it now */ 11322 ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 11323 if (ast_test_flag(&cai, IAX_TRUNK)) { 11324 int new_callno; 11325 if ((new_callno = make_trunk(callno, 1)) != -1) 11326 callno = new_callno; 11327 } 11328 iaxs[callno]->maxtime = cai.maxtime; 11329 if (cai.found) 11330 ast_string_field_set(iaxs[callno], host, pds.peer); 11331 11332 c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability); 11333 11334 ast_mutex_unlock(&iaxsl[callno]); 11335 11336 if (c) { 11337 /* Choose a format we can live with */ 11338 if (c->nativeformats & format) 11339 c->nativeformats &= format; 11340 else { 11341 native = c->nativeformats; 11342 fmt = format; 11343 res = ast_translator_best_choice(&fmt, &native); 11344 if (res < 0) { 11345 ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", 11346 ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name); 11347 ast_hangup(c); 11348 return NULL; 11349 } 11350 c->nativeformats = native; 11351 } 11352 c->readformat = ast_best_codec(c->nativeformats); 11353 c->writeformat = c->readformat; 11354 } 11355 11356 return c; 11357 }
| static int iax2_sched_add | ( | struct sched_context * | con, | |
| int | when, | |||
| ast_sched_cb | callback, | |||
| const void * | data | |||
| ) | [static] |
Definition at line 1271 of file chan_iax2.c.
References ast_sched_add(), sched_lock, and signal_condition().
Referenced by __attempt_transmit(), __find_callno(), __iax2_poke_noanswer(), __send_lagrq(), __send_ping(), iax2_call(), iax2_poke_peer(), make_trunk(), network_thread(), realtime_peer(), reg_source_db(), sched_delay_remove(), socket_process(), and update_registry().
01272 { 01273 int res; 01274 01275 res = ast_sched_add(con, when, callback, data); 01276 signal_condition(&sched_lock, &sched_cond); 01277 01278 return res; 01279 }
| static int iax2_sched_replace | ( | int | id, | |
| struct sched_context * | con, | |||
| int | when, | |||
| ast_sched_cb | callback, | |||
| const void * | data | |||
| ) | [static] |
Definition at line 1263 of file chan_iax2.c.
References AST_SCHED_REPLACE, sched_lock, and signal_condition().
Referenced by auth_fail(), iax2_ack_registry(), iax2_do_register(), iax2_dprequest(), iax2_provision(), and update_jbsched().
01264 { 01265 AST_SCHED_REPLACE(id, con, when, callback, data); 01266 signal_condition(&sched_lock, &sched_cond); 01267 01268 return id; 01269 }
| 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] |
Definition at line 5867 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, chan_iax2_pvt::aseqno, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_test_flag, calc_timestamp(), ast_iax2_mini_hdr::callno, ast_iax2_video_hdr::callno, chan_iax2_pvt::callno, iax_frame::callno, compress_subclass(), ast_iax2_full_hdr::csub, iax_frame::data, ast_frame::data, iax_frame::datalen, ast_frame::datalen, ast_iax2_full_hdr::dcallno, iax_frame::dcallno, DIRECTION_OUTGRESS, iax_frame::ecx, chan_iax2_pvt::ecx, chan_iax2_pvt::encmethods, iax_frame::encmethods, encrypt_frame(), iax_frame::final, chan_iax2_pvt::first_iax_message, ast_frame::frametype, iax2_key_rotate(), iax2_transmit(), iax2_trunk_queue(), IAX_CALLENCRYPTED, IAX_COMMAND_ACK, IAX_ENCRYPTED, IAX_FLAG_FULL, iax_frame_new(), iax_frame_wrap(), IAX_KEYPOPULATED, iax_outputframe(), IAX_TRUNK, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, chan_iax2_pvt::keyrotateid, chan_iax2_pvt::last_iax_message, chan_iax2_pvt::lastsent, iax2_trunk_peer::lastsent, chan_iax2_pvt::lastvsent, LOG_NOTICE, LOG_WARNING, MARK_IAX_SUBCLASS_TX, MAX_RETRY_TIME, MIN_RETRY_TIME, chan_iax2_pvt::mydcx, iax_frame::mydcx, ast_iax2_full_hdr::oseqno, chan_iax2_pvt::oseqno, iax_frame::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, ast_frame::ptr, iax_frame::retries, iax_frame::retrytime, ast_iax2_full_hdr::scallno, iax_frame::semirand, chan_iax2_pvt::semirand, send_packet(), ast_frame::subclass, chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, iax_frame::transfer, TRANSFER_MEDIAPASS, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, ast_iax2_mini_hdr::ts, ast_iax2_video_hdr::ts, ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_full_hdr::type, and ast_iax2_video_hdr::zeros.
Referenced by __send_command(), iax2_write(), and socket_process().
05868 { 05869 /* Queue a packet for delivery on a given private structure. Use "ts" for 05870 timestamp, or calculate if ts is 0. Send immediately without retransmission 05871 or delayed, with retransmission */ 05872 struct ast_iax2_full_hdr *fh; 05873 struct ast_iax2_mini_hdr *mh; 05874 struct ast_iax2_video_hdr *vh; 05875 struct { 05876 struct iax_frame fr2; 05877 unsigned char buffer[4096]; 05878 } frb; 05879 struct iax_frame *fr; 05880 int res; 05881 int sendmini=0; 05882 unsigned int lastsent; 05883 unsigned int fts; 05884 05885 frb.fr2.afdatalen = sizeof(frb.buffer); 05886 05887 if (!pvt) { 05888 ast_log(LOG_WARNING, "No private structure for packet?\n"); 05889 return -1; 05890 } 05891 05892 lastsent = pvt->lastsent; 05893 05894 /* Calculate actual timestamp */ 05895 fts = calc_timestamp(pvt, ts, f); 05896 05897 /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out 05898 * (the endpoint should detect the lost packet itself). But, we want to do this here, so that we 05899 * increment the "predicted timestamps" for voice, if we're predicting */ 05900 if(f->frametype == AST_FRAME_VOICE && f->datalen == 0) 05901 return 0; 05902 #if 0 05903 ast_log(LOG_NOTICE, 05904 "f->frametype %c= AST_FRAME_VOICE, %sencrypted, %srotation scheduled...\n", 05905 *("=!" + (f->frametype == AST_FRAME_VOICE)), 05906 IAX_CALLENCRYPTED(pvt) ? "" : "not ", 05907 pvt->keyrotateid != -1 ? "" : "no " 05908 ); 05909 #endif 05910 if (pvt->keyrotateid == -1 && f->frametype == AST_FRAME_VOICE && IAX_CALLENCRYPTED(pvt)) { 05911 iax2_key_rotate(pvt); 05912 } 05913 05914 if ((ast_test_flag(pvt, IAX_TRUNK) || 05915 (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) || 05916 ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L)))) 05917 /* High two bytes are the same on timestamp, or sending on a trunk */ && 05918 (f->frametype == AST_FRAME_VOICE) 05919 /* is a voice frame */ && 05920 (f->subclass == pvt->svoiceformat) 05921 /* is the same type */ ) { 05922 /* Force immediate rather than delayed transmission */ 05923 now = 1; 05924 /* Mark that mini-style frame is appropriate */ 05925 sendmini = 1; 05926 } 05927 if ( f->frametype == AST_FRAME_VIDEO ) { 05928 /* 05929 * If the lower 15 bits of the timestamp roll over, or if 05930 * the video format changed then send a full frame. 05931 * Otherwise send a mini video frame 05932 */ 05933 if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) && 05934 ((f->subclass & ~0x1) == pvt->svideoformat) 05935 ) { 05936 now = 1; 05937 sendmini = 1; 05938 } else { 05939 now = 0; 05940 sendmini = 0; 05941 } 05942 pvt->lastvsent = fts; 05943 } 05944 if (f->frametype == AST_FRAME_IAX) { 05945 /* 0x8000 marks this message as TX:, this bit will be stripped later */ 05946 pvt->last_iax_message = f->subclass | MARK_IAX_SUBCLASS_TX; 05947 if (!pvt->first_iax_message) { 05948 pvt->first_iax_message = pvt->last_iax_message; 05949 } 05950 } 05951 /* Allocate an iax_frame */ 05952 if (now) { 05953 fr = &frb.fr2; 05954 } else 05955 fr = iax_frame_new(DIRECTION_OUTGRESS, ast_test_flag(pvt, IAX_ENCRYPTED) ? f->datalen + 32 : f->datalen, (f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_VIDEO)); 05956 if (!fr) { 05957 ast_log(LOG_WARNING, "Out of memory\n"); 05958 return -1; 05959 } 05960 /* Copy our prospective frame into our immediate or retransmitted wrapper */ 05961 iax_frame_wrap(fr, f); 05962 05963 fr->ts = fts; 05964 fr->callno = pvt->callno; 05965 fr->transfer = transfer; 05966 fr->final = final; 05967 fr->encmethods = 0; 05968 if (!sendmini) { 05969 /* We need a full frame */ 05970 if (seqno > -1) 05971 fr->oseqno = seqno; 05972 else 05973 fr->oseqno = pvt->oseqno++; 05974 fr->iseqno = pvt->iseqno; 05975 fh = (struct ast_iax2_full_hdr *)(fr->af.data.ptr - sizeof(struct ast_iax2_full_hdr)); 05976 fh->scallno = htons(fr->callno | IAX_FLAG_FULL); 05977 fh->ts = htonl(fr->ts); 05978 fh->oseqno = fr->oseqno; 05979 if (transfer) { 05980 fh->iseqno = 0; 05981 } else 05982 fh->iseqno = fr->iseqno; 05983 /* Keep track of the last thing we've acknowledged */ 05984 if (!transfer) 05985 pvt->aseqno = fr->iseqno; 05986 fh->type = fr->af.frametype & 0xFF; 05987 if (fr->af.frametype == AST_FRAME_VIDEO) 05988 fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6); 05989 else 05990 fh->csub = compress_subclass(fr->af.subclass); 05991 if (transfer) { 05992 fr->dcallno = pvt->transfercallno; 05993 } else 05994 fr->dcallno = pvt->peercallno; 05995 fh->dcallno = htons(fr->dcallno); 05996 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr); 05997 fr->data = fh; 05998 fr->retries = 0; 05999 /* Retry after 2x the ping time has passed */ 06000 fr->retrytime = pvt->pingtime * 2; 06001 if (fr->retrytime < MIN_RETRY_TIME) 06002 fr->retrytime = MIN_RETRY_TIME; 06003 if (fr->retrytime > MAX_RETRY_TIME) 06004 fr->retrytime = MAX_RETRY_TIME; 06005 /* Acks' don't get retried */ 06006 if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK)) 06007 fr->retries = -1; 06008 else if (f->frametype == AST_FRAME_VOICE) 06009 pvt->svoiceformat = f->subclass; 06010 else if (f->frametype == AST_FRAME_VIDEO) 06011 pvt->svideoformat = f->subclass & ~0x1; 06012 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 06013 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 06014 if (fr->transfer) 06015 iax_outputframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 06016 else 06017 iax_outputframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 06018 encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen); 06019 fr->encmethods = pvt->encmethods; 06020 fr->ecx = pvt->ecx; 06021 fr->mydcx = pvt->mydcx; 06022 memcpy(fr->semirand, pvt->semirand, sizeof(fr->semirand)); 06023 } else 06024 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 06025 } 06026 06027 if (now) { 06028 res = send_packet(fr); 06029 } else 06030 res = iax2_transmit(fr); 06031 } else { 06032 if (ast_test_flag(pvt, IAX_TRUNK)) { 06033 iax2_trunk_queue(pvt, fr); 06034 res = 0; 06035 } else if (fr->af.frametype == AST_FRAME_VIDEO) { 06036 /* Video frame have no sequence number */ 06037 fr->oseqno = -1; 06038 fr->iseqno = -1; 06039 vh = (struct ast_iax2_video_hdr *)(fr->af.data.ptr - sizeof(struct ast_iax2_video_hdr)); 06040 vh->zeros = 0; 06041 vh->callno = htons(0x8000 | fr->callno); 06042 vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0)); 06043 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr); 06044 fr->data = vh; 06045 fr->retries = -1; 06046 res = send_packet(fr); 06047 } else { 06048 /* Mini-frames have no sequence number */ 06049 fr->oseqno = -1; 06050 fr->iseqno = -1; 06051 /* Mini frame will do */ 06052 mh = (struct ast_iax2_mini_hdr *)(fr->af.data.ptr - sizeof(struct ast_iax2_mini_hdr)); 06053 mh->callno = htons(fr->callno); 06054 mh->ts = htons(fr->ts & 0xFFFF); 06055 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr); 06056 fr->data = mh; 06057 fr->retries = -1; 06058 if (pvt->transferring == TRANSFER_MEDIAPASS) 06059 fr->transfer = 1; 06060 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 06061 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 06062 encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen); 06063 } else 06064 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 06065 } 06066 res = send_packet(fr); 06067 } 06068 } 06069 return res; 06070 }
| static int iax2_sendhtml | ( | struct ast_channel * | c, | |
| int | subclass, | |||
| const char * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 3921 of file chan_iax2.c.
References AST_FRAME_HTML, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03922 { 03923 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1); 03924 }
| static int iax2_sendimage | ( | struct ast_channel * | c, | |
| struct ast_frame * | img | |||
| ) | [static] |
Definition at line 3916 of file chan_iax2.c.
References AST_FRAME_IMAGE, ast_frame::data, ast_frame::datalen, ast_frame::ptr, PTR_TO_CALLNO, send_command_locked(), ast_frame::subclass, and ast_channel::tech_pvt.
03917 { 03918 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data.ptr, img->datalen, -1); 03919 }
| static int iax2_sendtext | ( | struct ast_channel * | c, | |
| const char * | text | |||
| ) | [static] |
Definition at line 3909 of file chan_iax2.c.
References AST_FRAME_TEXT, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03910 { 03911 03912 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT, 03913 0, 0, (unsigned char *)text, strlen(text) + 1, -1); 03914 }
| static int iax2_setoption | ( | struct ast_channel * | c, | |
| int | option, | |||
| void * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 4863 of file chan_iax2.c.
References AST_CONTROL_OPTION, AST_FRAME_CONTROL, ast_free, ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_FLAG_REQUEST, AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, ast_option_header::data, errno, PTR_TO_CALLNO, send_command_locked(), ast_channel::tech_pvt, and wait_for_peercallno().
04864 { 04865 struct ast_option_header *h; 04866 int res; 04867 04868 switch (option) { 04869 case AST_OPTION_TXGAIN: 04870 case AST_OPTION_RXGAIN: 04871 /* these two cannot be sent, because they require a result */ 04872 errno = ENOSYS; 04873 return -1; 04874 default: 04875 { 04876 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04877 struct chan_iax2_pvt *pvt; 04878 04879 ast_mutex_lock(&iaxsl[callno]); 04880 pvt = iaxs[callno]; 04881 04882 if (wait_for_peercallno(pvt)) { 04883 ast_mutex_unlock(&iaxsl[callno]); 04884 return -1; 04885 } 04886 04887 ast_mutex_unlock(&iaxsl[callno]); 04888 04889 if (!(h = ast_malloc(datalen + sizeof(*h)))) { 04890 return -1; 04891 } 04892 04893 h->flag = AST_OPTION_FLAG_REQUEST; 04894 h->option = htons(option); 04895 memcpy(h->data, data, datalen); 04896 res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL, 04897 AST_CONTROL_OPTION, 0, (unsigned char *) h, 04898 datalen + sizeof(*h), -1); 04899 ast_free(h); 04900 return res; 04901 } 04902 } 04903 }
| static int iax2_start_transfer | ( | unsigned short | callno0, | |
| unsigned short | callno1, | |||
| int | mediaonly | |||
| ) | [static] |
Definition at line 4944 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_debug, AST_FRAME_IAX, ast_random(), ast_set_flag, iax_ie_data::buf, IAX_CALLENCRYPTED, IAX_COMMAND_TXREQ, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), IAX_IE_CALLNO, IAX_IE_TRANSFERID, IAX_NOTRANSFER, iax_ie_data::pos, send_command(), TRANSFER_BEGIN, TRANSFER_MBEGIN, and chan_iax2_pvt::transferring.
Referenced by iax2_bridge().
04945 { 04946 int res; 04947 struct iax_ie_data ied0; 04948 struct iax_ie_data ied1; 04949 unsigned int transferid = (unsigned int)ast_random(); 04950 04951 if (IAX_CALLENCRYPTED(iaxs[callno0]) || IAX_CALLENCRYPTED(iaxs[callno1])) { 04952 ast_debug(1, "transfers are not supported for encrypted calls at this time"); 04953 ast_set_flag(iaxs[callno0], IAX_NOTRANSFER); 04954 ast_set_flag(iaxs[callno1], IAX_NOTRANSFER); 04955 return 0; 04956 } 04957 04958 memset(&ied0, 0, sizeof(ied0)); 04959 iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr); 04960 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno); 04961 iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid); 04962 04963 memset(&ied1, 0, sizeof(ied1)); 04964 iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr); 04965 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno); 04966 iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid); 04967 04968 res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1); 04969 if (res) 04970 return -1; 04971 res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1); 04972 if (res) 04973 return -1; 04974 iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 04975 iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 04976 return 0; 04977 }
| static int iax2_transfer | ( | struct ast_channel * | c, | |
| const char * | dest | |||
| ) | [static] |
Definition at line 5198 of file chan_iax2.c.
References ast_copy_string(), ast_debug, AST_FRAME_IAX, iax_ie_data::buf, chan_iax2_pvt::callno, context, IAX_COMMAND_TRANSFER, iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, iax_ie_data::pos, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
05199 { 05200 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 05201 struct iax_ie_data ied = { "", }; 05202 char tmp[256], *context; 05203 ast_copy_string(tmp, dest, sizeof(tmp)); 05204 context = strchr(tmp, '@'); 05205 if (context) { 05206 *context = '\0'; 05207 context++; 05208 } 05209 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp); 05210 if (context) 05211 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context); 05212 ast_debug(1, "Transferring '%s' to '%s'\n", c->name, dest); 05213 return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1); 05214 }
| static int iax2_transmit | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 3881 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, sched_lock, iax_frame::sentyet, and signal_condition().
Referenced by iax2_send().
03882 { 03883 /* Lock the queue and place this packet at the end */ 03884 /* By setting this to 0, the network thread will send it for us, and 03885 queue retransmission if necessary */ 03886 fr->sentyet = 0; 03887 AST_LIST_LOCK(&frame_queue); 03888 AST_LIST_INSERT_TAIL(&frame_queue, fr, list); 03889 AST_LIST_UNLOCK(&frame_queue); 03890 /* Wake up the network and scheduler thread */ 03891 if (netthreadid != AST_PTHREADT_NULL) 03892 pthread_kill(netthreadid, SIGURG); 03893 signal_condition(&sched_lock, &sched_cond); 03894 return 0; 03895 }
| static int iax2_trunk_expired | ( | struct iax2_trunk_peer * | tpeer, | |
| struct timeval * | now | |||
| ) | [inline, static] |
Definition at line 8524 of file chan_iax2.c.
References iax2_trunk_peer::trunkact.
Referenced by timing_read().
08525 { 08526 /* Drop when trunk is about 5 seconds idle */ 08527 if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 08528 return 1; 08529 return 0; 08530 }
| static int iax2_trunk_queue | ( | struct chan_iax2_pvt * | pvt, | |
| struct iax_frame * | fr | |||
| ) | [static] |
Definition at line 5606 of file chan_iax2.c.
References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, ast_tvnow(), ast_iax2_meta_trunk_entry::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, iax2_trunk_peer::calls, ast_frame::data, ast_frame::datalen, DEFAULT_TRUNKDATA, f, find_tpeer(), IAX2_TRUNK_PREFACE, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_WARNING, ast_iax2_meta_trunk_mini::mini, ast_frame::ptr, send_trunk(), chan_iax2_pvt::sockfd, iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdataalloc, iax2_trunk_peer::trunkdatalen, iax_frame::ts, and ast_iax2_mini_hdr::ts.
Referenced by iax2_send().
05607 { 05608 struct ast_frame *f; 05609 struct iax2_trunk_peer *tpeer; 05610 void *tmp, *ptr; 05611 struct timeval now; 05612 int res; 05613 struct ast_iax2_meta_trunk_entry *met; 05614 struct ast_iax2_meta_trunk_mini *mtm; 05615 05616 f = &fr->af; 05617 tpeer = find_tpeer(&pvt->addr, pvt->sockfd); 05618 if (tpeer) { 05619 if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) { 05620 /* Need to reallocate space */ 05621 if (tpeer->trunkdataalloc < trunkmaxsize) { 05622 if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) { 05623 ast_mutex_unlock(&tpeer->lock); 05624 return -1; 05625 } 05626 05627 tpeer->trunkdataalloc += DEFAULT_TRUNKDATA; 05628 tpeer->trunkdata = tmp; 05629 ast_debug(1, "Expanded trunk '%s:%d' to %d bytes\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), tpeer->trunkdataalloc); 05630 } else { 05631 ast_log(LOG_WARNING, "Maximum trunk data space exceeded to %s:%d\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port)); 05632 ast_mutex_unlock(&tpeer->lock); 05633 return -1; 05634 } 05635 } 05636 05637 /* Append to meta frame */ 05638 ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen; 05639 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) { 05640 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 05641 mtm->len = htons(f->datalen); 05642 mtm->mini.callno = htons(pvt->callno); 05643 mtm->mini.ts = htons(0xffff & fr->ts); 05644 ptr += sizeof(struct ast_iax2_meta_trunk_mini); 05645 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini); 05646 } else { 05647 met = (struct ast_iax2_meta_trunk_entry *)ptr; 05648 /* Store call number and length in meta header */ 05649 met->callno = htons(pvt->callno); 05650 met->len = htons(f->datalen); 05651 /* Advance pointers/decrease length past trunk entry header */ 05652 ptr += sizeof(struct ast_iax2_meta_trunk_entry); 05653 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry); 05654 } 05655 /* Copy actual trunk data */ 05656 memcpy(ptr, f->data.ptr, f->datalen); 05657 tpeer->trunkdatalen += f->datalen; 05658 05659 tpeer->calls++; 05660 05661 /* track the largest mtu we actually have sent */ 05662 if (tpeer->trunkdatalen + f->datalen + 4 > trunk_maxmtu) 05663 trunk_maxmtu = tpeer->trunkdatalen + f->datalen + 4 ; 05664 05665 /* if we have enough for a full MTU, ship it now without waiting */ 05666 if (global_max_trunk_mtu > 0 && tpeer->trunkdatalen + f->datalen + 4 >= global_max_trunk_mtu) { 05667 now = ast_tvnow(); 05668 res = send_trunk(tpeer, &now); 05669 trunk_untimed ++; 05670 } 05671 05672 ast_mutex_unlock(&tpeer->lock); 05673 } 05674 return 0; 05675 }
| static int iax2_vnak | ( | int | callno | ) | [static] |
Definition at line 8442 of file chan_iax2.c.
References AST_FRAME_IAX, IAX_COMMAND_VNAK, and send_command_immediate().
Referenced by socket_process(), and socket_process_meta().
08443 { 08444 return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno); 08445 }
| static int iax2_write | ( | struct ast_channel * | c, | |
| struct ast_frame * | f | |||
| ) | [static] |
Definition at line 6864 of file chan_iax2.c.
References ast_debug, AST_FRAME_NULL, AST_FRAME_VOICE, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_peer::callno, errno, ast_frame::frametype, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, PTR_TO_CALLNO, and ast_channel::tech_pvt.
06865 { 06866 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 06867 int res = -1; 06868 ast_mutex_lock(&iaxsl[callno]); 06869 if (iaxs[callno]) { 06870 /* If there's an outstanding error, return failure now */ 06871 if (!iaxs[callno]->error) { 06872 if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) 06873 res = 0; 06874 /* Don't waste bandwidth sending null frames */ 06875 else if (f->frametype == AST_FRAME_NULL) 06876 res = 0; 06877 else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH)) 06878 res = 0; 06879 else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 06880 res = 0; 06881 else 06882 /* Simple, just queue for transmission */ 06883 res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0); 06884 } else { 06885 ast_debug(1, "Write error: %s\n", strerror(errno)); 06886 } 06887 } 06888 /* If it's already gone, just return */ 06889 ast_mutex_unlock(&iaxsl[callno]); 06890 return res; 06891 }
| static int iax_check_version | ( | char * | dev | ) | [static] |
Definition at line 2829 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_iax2_firmware_header::devname, iax_firmware::fwh, and ast_iax2_firmware_header::version.
Referenced by update_registry().
02830 { 02831 int res = 0; 02832 struct iax_firmware *cur = NULL; 02833 02834 if (ast_strlen_zero(dev)) 02835 return 0; 02836 02837 AST_LIST_LOCK(&firmwares); 02838 AST_LIST_TRAVERSE(&firmwares, cur, list) { 02839 if (!strcmp(dev, (char *)cur->fwh->devname)) { 02840 res = ntohs(cur->fwh->version); 02841 break; 02842 } 02843 } 02844 AST_LIST_UNLOCK(&firmwares); 02845 02846 return res; 02847 }
| static void iax_debug_output | ( | const char * | data | ) | [static] |
Definition at line 967 of file chan_iax2.c.
References ast_verbose.
Referenced by load_module().
00968 { 00969 if (iaxdebug) 00970 ast_verbose("%s", data); 00971 }
| static void iax_error_output | ( | const char * | data | ) | [static] |
Definition at line 973 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by load_module().
00974 { 00975 ast_log(LOG_WARNING, "%s", data); 00976 }
| static int iax_firmware_append | ( | struct iax_ie_data * | ied, | |
| const unsigned char * | dev, | |||
| unsigned int | desc | |||
| ) | [static] |
Definition at line 2849 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, iax_firmware::fwh, iax_ie_append(), iax_ie_append_int(), iax_ie_append_raw(), IAX_IE_FWBLOCKDATA, and IAX_IE_FWBLOCKDESC.
Referenced by socket_process().
02850 { 02851 int res = -1; 02852 unsigned int bs = desc & 0xff; 02853 unsigned int start = (desc >> 8) & 0xffffff; 02854 unsigned int bytes; 02855 struct iax_firmware *cur; 02856 02857 if (ast_strlen_zero((char *)dev) || !bs) 02858 return -1; 02859 02860 start *= bs; 02861 02862 AST_LIST_LOCK(&firmwares); 02863 AST_LIST_TRAVERSE(&firmwares, cur, list) { 02864 if (strcmp((char *)dev, (char *)cur->fwh->devname)) 02865 continue; 02866 iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc); 02867 if (start < ntohl(cur->fwh->datalen)) { 02868 bytes = ntohl(cur->fwh->datalen) - start; 02869 if (bytes > bs) 02870 bytes = bs; 02871 iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes); 02872 } else { 02873 bytes = 0; 02874 iax_ie_append(ied, IAX_IE_FWBLOCKDATA); 02875 } 02876 if (bytes == bs) 02877 res = 0; 02878 else 02879 res = 1; 02880 break; 02881 } 02882 AST_LIST_UNLOCK(&firmwares); 02883 02884 return res; 02885 }
| static void iax_outputframe | ( | struct iax_frame * | f, | |
| struct ast_iax2_full_hdr * | fhi, | |||
| int | rx, | |||
| struct sockaddr_in * | sin, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 950 of file chan_iax2.c.
References debugaddr, and iax_showframe().
Referenced by iax2_send(), raw_hangup(), and socket_process().
00951 { 00952 if (iaxdebug || 00953 (sin && debugaddr.sin_addr.s_addr && 00954 (!ntohs(debugaddr.sin_port) || 00955 debugaddr.sin_port == sin->sin_port) && 00956 debugaddr.sin_addr.s_addr == sin->sin_addr.s_addr)) { 00957 if (iaxdebug) { 00958 iax_showframe(f, fhi, rx, sin, datalen); 00959 } else { 00960 iaxdebug = 1; 00961 iax_showframe(f, fhi, rx, sin, datalen); 00962 iaxdebug = 0; 00963 } 00964 } 00965 }
| static int iax_park | ( | struct ast_channel * | chan1, | |
| struct ast_channel * | chan2 | |||
| ) | [static] |
Definition at line 8686 of file chan_iax2.c.
References ast_channel::amaflags, ast_calloc, ast_channel_alloc, ast_channel_masquerade(), ast_copy_string(), ast_do_masquerade(), ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached_background, AST_STATE_DOWN, iax_dual::chan1, iax_dual::chan2, ast_channel::context, ast_channel::exten, iax_park_thread(), LOG_WARNING, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.
Referenced by socket_process().
08687 { 08688 struct iax_dual *d; 08689 struct ast_channel *chan1m, *chan2m; 08690 pthread_t th; 08691 chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name); 08692 chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name); 08693 if (chan2m && chan1m) { 08694 /* Make formats okay */ 08695 chan1m->readformat = chan1->readformat; 08696 chan1m->writeformat = chan1->writeformat; 08697 ast_channel_masquerade(chan1m, chan1); 08698 /* Setup the extensions and such */ 08699 ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context)); 08700 ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten)); 08701 chan1m->priority = chan1->priority; 08702 08703 /* We make a clone of the peer channel too, so we can play 08704 back the announcement */ 08705 /* Make formats okay */ 08706 chan2m->readformat = chan2->readformat; 08707 chan2m->writeformat = chan2->writeformat; 08708 ast_channel_masquerade(chan2m, chan2); 08709 /* Setup the extensions and such */ 08710 ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context)); 08711 ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten)); 08712 chan2m->priority = chan2->priority; 08713 if (ast_do_masquerade(chan2m)) { 08714 ast_log(LOG_WARNING, "Masquerade failed :(\n"); 08715 ast_hangup(chan2m); 08716 return -1; 08717 } 08718 } else { 08719 if (chan1m) 08720 ast_hangup(chan1m); 08721 if (chan2m) 08722 ast_hangup(chan2m); 08723 return -1; 08724 } 08725 if ((d = ast_calloc(1, sizeof(*d)))) { 08726 d->chan1 = chan1m; 08727 d->chan2 = chan2m; 08728 if (!ast_pthread_create_detached_background(&th, NULL, iax_park_thread, d)) { 08729 return 0; 08730 } 08731 ast_free(d); 08732 } 08733 return -1; 08734 }
| static void* iax_park_thread | ( | void * | stuff | ) | [static] |
Definition at line 8666 of file chan_iax2.c.
References ast_free, ast_frfree, ast_hangup(), ast_log(), ast_park_call(), ast_read(), iax_dual::chan1, iax_dual::chan2, ext, f, and LOG_NOTICE.
Referenced by iax_park().
08667 { 08668 struct ast_channel *chan1, *chan2; 08669 struct iax_dual *d; 08670 struct ast_frame *f; 08671 int ext; 08672 int res; 08673 d = stuff; 08674 chan1 = d->chan1; 08675 chan2 = d->chan2; 08676 ast_free(d); 08677 f = ast_read(chan1); 08678 if (f) 08679 ast_frfree(f); 08680 res = ast_park_call(chan1, chan2, 0, &ext); 08681 ast_hangup(chan2); 08682 ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext); 08683 return NULL; 08684 }
Definition at line 1646 of file chan_iax2.c.
References iax_frame::af, iax_frame::afdatalen, iax_frame::cacheable, ast_frame::datalen, DIRECTION_INGRESS, iax_frame_new(), and iax_frame_wrap().
Referenced by socket_process(), and socket_process_meta().
01647 { 01648 struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable); 01649 if (new) { 01650 size_t afdatalen = new->afdatalen; 01651 memcpy(new, fr, sizeof(*new)); 01652 iax_frame_wrap(new, &fr->af); 01653 new->afdatalen = afdatalen; 01654 new->data = NULL; 01655 new->datalen = 0; 01656 new->direction = DIRECTION_INGRESS; 01657 new->retrans = -1; 01658 } 01659 return new; 01660 }
| static void insert_idle_thread | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 1156 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, IAX_THREAD_TYPE_DYNAMIC, and iax2_thread::type.
Referenced by iax2_process_thread().
01157 { 01158 if (thread->type == IAX_THREAD_TYPE_DYNAMIC) { 01159 AST_LIST_LOCK(&dynamic_list); 01160 AST_LIST_INSERT_TAIL(&dynamic_list, thread, list); 01161 AST_LIST_UNLOCK(&dynamic_list); 01162 } else { 01163 AST_LIST_LOCK(&idle_list); 01164 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 01165 AST_LIST_UNLOCK(&idle_list); 01166 } 01167 01168 return; 01169 }
| static void jb_debug_output | ( | const char * | fmt, | |
| ... | ||||
| ) | [static] |
Definition at line 1002 of file chan_iax2.c.
References ast_verbose.
Referenced by handle_cli_iax2_set_debug_jb().
01003 { 01004 va_list args; 01005 char buf[1024]; 01006 01007 va_start(args, fmt); 01008 vsnprintf(buf, sizeof(buf), fmt, args); 01009 va_end(args); 01010 01011 ast_verbose("%s", buf); 01012 }
| static void jb_error_output | ( | const char * | fmt, | |
| ... | ||||
| ) | [static] |
Definition at line 978 of file chan_iax2.c.
References ast_log(), and LOG_ERROR.
Referenced by handle_cli_iax2_set_debug_jb(), and load_module().
| static void jb_warning_output | ( | const char * | fmt, | |
| ... | ||||
| ) | [static] |
Definition at line 990 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by handle_cli_iax2_set_debug_jb(), and load_module().
00991 { 00992 va_list args; 00993 char buf[1024]; 00994 00995 va_start(args, fmt); 00996 vsnprintf(buf, sizeof(buf), fmt, args); 00997 va_end(args); 00998 00999 ast_log(LOG_WARNING, "%s", buf); 01000 }
| static int load_module | ( | void | ) | [static] |
Load IAX2 module, load configuraiton ---.
Definition at line 13544 of file chan_iax2.c.
References __unload_module(), ao2_callback, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_custom_function_register, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_mutex_init(), ast_netsock_init(), ast_netsock_list_alloc(), ast_random(), ast_realtime_require_field(), ast_register_application, ast_register_switch(), ast_timer_close(), ast_timer_open(), ast_timer_set_rate(), ast_verb, config, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, iax2_do_register(), iax2_poke_peer_cb(), iax2_prov_app(), iax_debug_output(), iax_error_output(), iax_provision_reload(), iax_set_error(), iax_set_output(), io_context_create(), io_context_destroy(), jb_error_output(), jb_setoutput(), jb_warning_output(), load_objects(), LOG_ERROR, manager_iax2_show_netstats(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), peer_set_sock_cb(), reload_firmware(), RQ_CHAR, RQ_UINTEGER2, sched_context_create(), sched_context_destroy(), SENTINEL, set_config(), and start_network_thread().
13545 { 13546 13547 static const char config[] = "iax.conf"; 13548 int x = 0; 13549 struct iax2_registry *reg = NULL; 13550 13551 if (load_objects()) { 13552 return AST_MODULE_LOAD_FAILURE; 13553 } 13554 13555 randomcalltokendata = ast_random(); 13556 ast_custom_function_register(&iaxpeer_function); 13557 ast_custom_function_register(&iaxvar_function); 13558 13559 iax_set_output(iax_debug_output); 13560 iax_set_error(iax_error_output); 13561 jb_setoutput(jb_error_output, jb_warning_output, NULL); 13562 13563 memset(iaxs, 0, sizeof(iaxs)); 13564 13565 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 13566 ast_mutex_init(&iaxsl[x]); 13567 } 13568 13569 ast_cond_init(&sched_cond, NULL); 13570 13571 if (!(sched = sched_context_create())) { 13572 ast_log(LOG_ERROR, "Failed to create scheduler context\n"); 13573 return AST_MODULE_LOAD_FAILURE; 13574 } 13575 13576 if (!(io = io_context_create())) { 13577 ast_log(LOG_ERROR, "Failed to create I/O context\n"); 13578 sched_context_destroy(sched); 13579 return AST_MODULE_LOAD_FAILURE; 13580 } 13581 13582 if (!(netsock = ast_netsock_list_alloc())) { 13583 ast_log(LOG_ERROR, "Failed to create netsock list\n"); 13584 io_context_destroy(io); 13585 sched_context_destroy(sched); 13586 return AST_MODULE_LOAD_FAILURE; 13587 } 13588 ast_netsock_init(netsock); 13589 13590 outsock = ast_netsock_list_alloc(); 13591 if (!outsock) { 13592 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 13593 io_context_destroy(io); 13594 sched_context_destroy(sched); 13595 return AST_MODULE_LOAD_FAILURE; 13596 } 13597 ast_netsock_init(outsock); 13598 13599 ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 13600 13601 ast_register_application(papp, iax2_prov_app, psyn, pdescrip); 13602 13603 ast_manager_register( "IAXpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peers, "List IAX Peers" ); 13604 ast_manager_register( "IAXpeerlist", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peer_list, "List IAX Peers" ); 13605 ast_manager_register( "IAXnetstats", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_netstats, "Show IAX Netstats" ); 13606 13607 if ((timer = ast_timer_open())) { 13608 ast_timer_set_rate(timer, trunkfreq); 13609 } 13610 13611 if (set_config(config, 0) == -1) { 13612 if (timer) { 13613 ast_timer_close(timer); 13614 } 13615 return AST_MODULE_LOAD_DECLINE; 13616 } 13617 13618 if (ast_channel_register(&iax2_tech)) { 13619 ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2"); 13620 __unload_module(); 13621 return AST_MODULE_LOAD_FAILURE; 13622 } 13623 13624 if (ast_register_switch(&iax2_switch)) 13625 ast_log(LOG_ERROR, "Unable to register IAX switch\n"); 13626 13627 if (start_network_thread()) { 13628 ast_log(LOG_ERROR, "Unable to start network thread\n"); 13629 __unload_module(); 13630 return AST_MODULE_LOAD_FAILURE; 13631 } else 13632 ast_verb(2, "IAX Ready and Listening\n"); 13633 13634 AST_LIST_LOCK(®istrations); 13635 AST_LIST_TRAVERSE(®istrations, reg, entry) 13636 iax2_do_register(reg); 13637 AST_LIST_UNLOCK(®istrations); 13638 13639 ao2_callback(peers, 0, peer_set_sock_cb, NULL); 13640 ao2_callback(peers, 0, iax2_poke_peer_cb, NULL); 13641 13642 13643 reload_firmware(0); 13644 iax_provision_reload(0); 13645 13646 ast_realtime_require_field("iaxpeers", "name", RQ_CHAR, 10, "ipaddr", RQ_CHAR, 15, "port", RQ_UINTEGER2, 5, "regseconds", RQ_UINTEGER2, 6, SENTINEL); 13647 13648 return AST_MODULE_LOAD_SUCCESS; 13649 }
| static int load_objects | ( | void | ) | [static] |
Definition at line 13485 of file chan_iax2.c.
References addr_range_cmp_cb(), addr_range_hash_cb(), ao2_container_alloc, ao2_ref, AST_MODULE_LOAD_FAILURE, callno_limits, calltoken_ignores, create_callno_pools(), IAX_MAX_CALLS, MAX_PEER_BUCKETS, MAX_USER_BUCKETS, peer_cmp_cb(), peer_hash_cb(), peercnt_cmp_cb(), peercnt_hash_cb(), peercnts, pvt_cmp_cb(), pvt_hash_cb(), transfercallno_pvt_cmp_cb(), transfercallno_pvt_hash_cb(), user_cmp_cb(), and user_hash_cb().
Referenced by load_module().
13486 { 13487 peers = users = iax_peercallno_pvts = iax_transfercallno_pvts = NULL; 13488 peercnts = callno_limits = calltoken_ignores = callno_pool = callno_pool_trunk = NULL; 13489 13490 if (!(peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb))) { 13491 goto container_fail; 13492 } else if (!(users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb))) { 13493 goto container_fail; 13494 } else if (!(iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb))) { 13495 goto container_fail; 13496 } else if (!(iax_transfercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, transfercallno_pvt_hash_cb, transfercallno_pvt_cmp_cb))) { 13497 goto container_fail; 13498 } else if (!(peercnts = ao2_container_alloc(MAX_PEER_BUCKETS, peercnt_hash_cb, peercnt_cmp_cb))) { 13499 goto container_fail; 13500 } else if (!(callno_limits = ao2_container_alloc(MAX_PEER_BUCKETS, addr_range_hash_cb, addr_range_cmp_cb))) { 13501 goto container_fail; 13502 } else if (!(calltoken_ignores = ao2_container_alloc(MAX_PEER_BUCKETS, addr_range_hash_cb, addr_range_cmp_cb))) { 13503 goto container_fail; 13504 } else if (create_callno_pools()) { 13505 goto container_fail; 13506 } 13507 13508 return 0; 13509 13510 container_fail: 13511 if (peers) { 13512 ao2_ref(peers, -1); 13513 } 13514 if (users) { 13515 ao2_ref(users, -1); 13516 } 13517 if (iax_peercallno_pvts) { 13518 ao2_ref(iax_peercallno_pvts, -1); 13519 } 13520 if (iax_transfercallno_pvts) { 13521 ao2_ref(iax_transfercallno_pvts, -1); 13522 } 13523 if (peercnts) { 13524 ao2_ref(peercnts, -1); 13525 } 13526 if (callno_limits) { 13527 ao2_ref(callno_limits, -1); 13528 } 13529 if (calltoken_ignores) { 13530 ao2_ref(calltoken_ignores, -1); 13531 } 13532 if (callno_pool) { 13533 ao2_ref(callno_pool, -1); 13534 } 13535 if (callno_pool_trunk) { 13536 ao2_ref(callno_pool_trunk, -1); 13537 } 13538 return AST_MODULE_LOAD_FAILURE; 13539 }
| static void lock_both | ( | unsigned short | callno0, | |
| unsigned short | callno1 | |||
| ) | [static] |
Definition at line 4979 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_trylock(), and DEADLOCK_AVOIDANCE.
Referenced by iax2_bridge().
04980 { 04981 ast_mutex_lock(&iaxsl[callno0]); 04982 while (ast_mutex_trylock(&iaxsl[callno1])) { 04983 DEADLOCK_AVOIDANCE(&iaxsl[callno0]); 04984 } 04985 }
| static void log_jitterstats | ( | unsigned short | callno | ) | [static] |
Definition at line 8809 of file chan_iax2.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, jb_info::current, iax_rr::delay, iax_rr::dropped, EVENT_FLAG_REPORTING, jb_info::frames_dropped, jb_info::frames_in, jb_info::frames_lost, jb_info::frames_ooo, IAX_USEJITTERBUF, ast_channel::jb, jb_getinfo(), iax_rr::jitter, jb_info::jitter, iax_rr::losscnt, iax_rr::losspct, jb_info::losspct, manager_event, jb_info::min, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::pingtime, and chan_iax2_pvt::remote_rr.
Referenced by socket_process().
08810 { 08811 int localjitter = -1, localdelay = 0, locallost = -1, locallosspct = -1, localdropped = 0, localooo = -1, localpackets = -1; 08812 jb_info jbinfo; 08813 08814 ast_mutex_lock(&iaxsl[callno]); 08815 if (iaxs[callno] && iaxs[callno]->owner && iaxs[callno]->owner->name) { 08816 if(ast_test_flag(iaxs[callno], IAX_USEJITTERBUF)) { 08817 jb_getinfo(iaxs[callno]->jb, &jbinfo); 08818 localjitter = jbinfo.jitter; 08819 localdelay = jbinfo.current - jbinfo.min; 08820 locallost = jbinfo.frames_lost; 08821 locallosspct = jbinfo.losspct/1000; 08822 localdropped = jbinfo.frames_dropped; 08823 localooo = jbinfo.frames_ooo; 08824 localpackets = jbinfo.frames_in; 08825 } 08826 ast_debug(3, "JB STATS:%s ping=%d ljitterms=%d ljbdelayms=%d ltotlost=%d lrecentlosspct=%d ldropped=%d looo=%d lrecvd=%d rjitterms=%d rjbdelayms=%d rtotlost=%d rrecentlosspct=%d rdropped=%d rooo=%d rrecvd=%d\n", 08827 iaxs[callno]->owner->name, 08828 iaxs[callno]->pingtime, 08829 localjitter, 08830 localdelay, 08831 locallost, 08832 locallosspct, 08833 localdropped, 08834 localooo, 08835 localpackets, 08836 iaxs[callno]->remote_rr.jitter, 08837 iaxs[callno]->remote_rr.delay, 08838 iaxs[callno]->remote_rr.losscnt, 08839 iaxs[callno]->remote_rr.losspct/1000, 08840 iaxs[callno]->remote_rr.dropped, 08841 iaxs[callno]->remote_rr.ooo, 08842 iaxs[callno]->remote_rr.packets); 08843 manager_event(EVENT_FLAG_REPORTING, "JitterBufStats", "Owner: %s\r\nPing: %d\r\nLocalJitter: %d\r\nLocalJBDelay: %d\r\nLocalTotalLost: %d\r\nLocalLossPercent: %d\r\nLocalDropped: %d\r\nLocalooo: %d\r\nLocalReceived: %d\r\nRemoteJitter: %d\r\nRemoteJBDelay: %d\r\nRemoteTotalLost: %d\r\nRemoteLossPercent: %d\r\nRemoteDropped: %d\r\nRemoteooo: %d\r\nRemoteReceived: %d\r\n", 08844 iaxs[callno]->owner->name, 08845 iaxs[callno]->pingtime, 08846 localjitter, 08847 localdelay, 08848 locallost, 08849 locallosspct, 08850 localdropped, 08851 localooo, 08852 localpackets, 08853 iaxs[callno]->remote_rr.jitter, 08854 iaxs[callno]->remote_rr.delay, 08855 iaxs[callno]->remote_rr.losscnt, 08856 iaxs[callno]->remote_rr.losspct/1000, 08857 iaxs[callno]->remote_rr.dropped, 08858 iaxs[callno]->remote_rr.ooo, 08859 iaxs[callno]->remote_rr.packets); 08860 } 08861 ast_mutex_unlock(&iaxsl[callno]); 08862 }
| static int make_trunk | ( | unsigned short | callno, | |
| int | locked | |||
| ) | [static] |
Definition at line 1726 of file chan_iax2.c.
References ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, chan_iax2_pvt::callno, callno_entry::callno, chan_iax2_pvt::callno_entry, get_unused_callno(), iax2_sched_add(), chan_iax2_pvt::lagid, LOG_WARNING, MIN_REUSE_TIME, chan_iax2_pvt::pingid, replace_callno(), send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), update_max_trunk(), and callno_entry::validated.
Referenced by iax2_request(), and socket_process().
01727 { 01728 int x; 01729 int res= 0; 01730 struct callno_entry *callno_entry; 01731 if (iaxs[callno]->oseqno) { 01732 ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n"); 01733 return -1; 01734 } 01735 if (callno & TRUNK_CALL_START) { 01736 ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno); 01737 return -1; 01738 } 01739 01740 if (!(callno_entry = get_unused_callno(1, iaxs[callno]->callno_entry->validated))) { 01741 ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n"); 01742 return -1; 01743 } 01744 01745 x = callno_entry->callno; 01746 ast_mutex_lock(&iaxsl[x]); 01747 01748 /*! 01749 * \note We delete these before switching the slot, because if 01750 * they fire in the meantime, they will generate a warning. 01751 */ 01752 AST_SCHED_DEL(sched, iaxs[callno]->pingid); 01753 AST_SCHED_DEL(sched, iaxs[callno]->lagid); 01754 iaxs[x] = iaxs[callno]; 01755 iaxs[x]->callno = x; 01756 01757 /* since we copied over the pvt from a different callno, make sure the old entry is replaced 01758 * before assigning the new one */ 01759 if (iaxs[x]->callno_entry) { 01760 iax2_sched_add(sched, MIN_REUSE_TIME * 1000, replace_callno, iaxs[x]->callno_entry); 01761 } 01762 iaxs[x]->callno_entry = callno_entry; 01763 01764 iaxs[callno] = NULL; 01765 /* Update the two timers that should have been started */ 01766 iaxs[x]->pingid = iax2_sched_add(sched, 01767 ping_time * 1000, send_ping, (void *)(long)x); 01768 iaxs[x]->lagid = iax2_sched_add(sched, 01769 lagrq_time * 1000, send_lagrq, (void *)(long)x); 01770 01771 if (locked) 01772 ast_mutex_unlock(&iaxsl[callno]); 01773 res = x; 01774 if (!locked) 01775 ast_mutex_unlock(&iaxsl[x]); 01776 01777 ast_debug(1, "Made call %d into trunk call %d\n", callno, x); 01778 /* We move this call from a non-trunked to a trunked call */ 01779 update_max_trunk(); 01780 update_max_nontrunk(); 01781 return res; 01782 }
| static int manager_iax2_show_netstats | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 6434 of file chan_iax2.c.
References ast_cli_netstats(), astman_append(), and RESULT_SUCCESS.
Referenced by load_module().
06435 { 06436 ast_cli_netstats(s, -1, 0); 06437 astman_append(s, "\r\n"); 06438 return RESULT_SUCCESS; 06439 }
| static int manager_iax2_show_peer_list | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
callback to display iax peers in manager format
Definition at line 6486 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next, ast_copy_string(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), IAX_DYNAMIC, iax2_peer::mask, iax2_peer::name, peer_status(), peer_unref(), RESULT_SUCCESS, status, and iax2_peer::username.
Referenced by load_module().
06487 { 06488 struct iax2_peer *peer = NULL; 06489 int peer_count = 0; 06490 char nm[20]; 06491 char status[20]; 06492 const char *id = astman_get_header(m,"ActionID"); 06493 char idtext[256] = ""; 06494 struct ao2_iterator i; 06495 06496 if (!ast_strlen_zero(id)) 06497 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 06498 06499 astman_append(s, "Response: Success\r\n%sMessage: IAX Peer status list will follow\r\n\r\n", idtext); 06500 06501 06502 i = ao2_iterator_init(peers, 0); 06503 for (peer = ao2_iterator_next(&i); peer; peer_unref(peer), peer = ao2_iterator_next(&i)) { 06504 06505 astman_append(s, "Event: PeerEntry\r\n%sChanneltype: IAX\r\n", idtext); 06506 if (!ast_strlen_zero(peer->username)) { 06507 astman_append(s, "ObjectName: %s\r\nObjectUsername: %s\r\n", peer->name, peer->username); 06508 } else { 06509 astman_append(s, "ObjectName: %s\r\n", peer->name); 06510 } 06511 astman_append(s, "ChanObjectType: peer\r\n"); 06512 astman_append(s, "IPaddress: %s\r\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-"); 06513 ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); 06514 astman_append(s, "Mask: %s\r\n", nm); 06515 astman_append(s, "Port: %d\r\n", ntohs(peer->addr.sin_port)); 06516 astman_append(s, "Dynamic: %s\r\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No"); 06517 peer_status(peer, status, sizeof(status)); 06518 astman_append(s, "Status: %s\r\n\r\n", status); 06519 peer_count++; 06520 } 06521 06522 astman_append(s, "Event: PeerlistComplete\r\n%sListItems: %d\r\n\r\n", idtext, peer_count); 06523 return RESULT_SUCCESS; 06524 }
| static int manager_iax2_show_peers | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
callback to display iax peers in manager
Definition at line 6473 of file chan_iax2.c.
References __iax2_show_peers(), ast_strlen_zero(), astman_get_header(), and astman_send_ack().
Referenced by load_module().
06474 { 06475 char *a[] = { "iax2", "show", "users" }; 06476 const char *id = astman_get_header(m,"ActionID"); 06477 char idtext[256] = ""; 06478 06479 if (!ast_strlen_zero(id)) 06480 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 06481 astman_send_ack(s, m, "Peer status list will follow"); 06482 return __iax2_show_peers(1, -1, s, 3, a ); 06483 }
| static int match | ( | struct sockaddr_in * | sin, | |
| unsigned short | callno, | |||
| unsigned short | dcallno, | |||
| const struct chan_iax2_pvt * | cur, | |||
| int | check_dcallno | |||
| ) | [static] |
Definition at line 1675 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::callno, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, TRANSFER_MEDIAPASS, chan_iax2_pvt::transfercallno, and chan_iax2_pvt::transferring.
Referenced by __ao2_callback(), __find_callno(), ast_parse_device_state(), check_blacklist(), find_command(), handle_updates(), lua_find_extension(), pbx_find_extension(), pvt_cmp_cb(), realtime_switch_common(), and transfercallno_pvt_cmp_cb().
01676 { 01677 if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) && 01678 (cur->addr.sin_port == sin->sin_port)) { 01679 /* This is the main host */ 01680 if ( (cur->peercallno == 0 || cur->peercallno == callno) && 01681 (check_dcallno ? dcallno == cur->callno : 1) ) { 01682 /* That's us. Be sure we keep track of the peer call number */ 01683 return 1; 01684 } 01685 } 01686 if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) && 01687 (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) { 01688 /* We're transferring */ 01689 if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno)) 01690 return 1; 01691 } 01692 return 0; 01693 }
| static void memcpy_decrypt | ( | unsigned char * | dst, | |
| const unsigned char * | src, | |||
| int | len, | |||
| ast_aes_decrypt_key * | dcx | |||
| ) | [static] |
Definition at line 5705 of file chan_iax2.c.
References ast_aes_decrypt, ast_log(), and LOG_WARNING.
Referenced by decode_frame().
05706 { 05707 #if 0 05708 /* Debug with "fake encryption" */ 05709 int x; 05710 if (len % 16) 05711 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 05712 for (x=0;x<len;x++) 05713 dst[x] = src[x] ^ 0xff; 05714 #else 05715 unsigned char lastblock[16] = { 0 }; 05716 int x; 05717 while(len > 0) { 05718 ast_aes_decrypt(src, dst, dcx); 05719 for (x=0;x<16;x++) 05720 dst[x] ^= lastblock[x]; 05721 memcpy(lastblock, src, sizeof(lastblock)); 05722 dst += 16; 05723 src += 16; 05724 len -= 16; 05725 } 05726 #endif 05727 }
| static void memcpy_encrypt | ( | unsigned char * | dst, | |
| const unsigned char * | src, | |||
| int | len, | |||
| ast_aes_encrypt_key * | ecx | |||
| ) | [static] |
Definition at line 5729 of file chan_iax2.c.
References ast_aes_encrypt, ast_log(), and LOG_WARNING.
Referenced by encrypt_frame().
05730 { 05731 #if 0 05732 /* Debug with "fake encryption" */ 05733 int x; 05734 if (len % 16) 05735 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 05736 for (x=0;x<len;x++) 05737 dst[x] = src[x] ^ 0xff; 05738 #else 05739 unsigned char curblock[16] = { 0 }; 05740 int x; 05741 while(len > 0) { 05742 for (x=0;x<16;x++) 05743 curblock[x] ^= src[x]; 05744 ast_aes_encrypt(curblock, dst, ecx); 05745 memcpy(curblock, dst, sizeof(curblock)); 05746 dst += 16; 05747 src += 16; 05748 len -= 16; 05749 } 05750 #endif 05751 }
| static void merge_encryption | ( | struct chan_iax2_pvt * | p, | |
| unsigned int | enc | |||
| ) | [static] |
Definition at line 7200 of file chan_iax2.c.
References chan_iax2_pvt::encmethods, IAX_ENCRYPT_AES128, IAX_ENCRYPT_KEYROTATE, and chan_iax2_pvt::keyrotateid.
Referenced by authenticate_reply(), and socket_process().
07201 { 07202 /* Select exactly one common encryption if there are any */ 07203 p->encmethods &= enc; 07204 if (p->encmethods) { 07205 if (!(p->encmethods & IAX_ENCRYPT_KEYROTATE)){ /* if key rotation is not supported, turn off keyrotation. */ 07206 p->keyrotateid = -2; 07207 } 07208 if (p->encmethods & IAX_ENCRYPT_AES128) 07209 p->encmethods = IAX_ENCRYPT_AES128; 07210 else 07211 p->encmethods = 0; 07212 } 07213 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 1090 of file chan_iax2.c.
Referenced by build_peer().
| static void* network_thread | ( | void * | ignore | ) | [static] |
Definition at line 11387 of file chan_iax2.c.
References ast_debug, ast_io_add(), AST_IO_IN, AST_IO_PRI, ast_io_wait(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_mutex_trylock(), ast_mutex_unlock(), ast_timer_fd(), attempt_transmit(), iax_frame::callno, f, iax2_sched_add(), iax_frame_free(), iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_packet(), iax_frame::sentyet, and timing_read().
Referenced by start_network_thread().
11388 { 11389 /* Our job is simple: Send queued messages, retrying if necessary. Read frames 11390 from the network, and queue them for delivery to the channels */ 11391 int res, count, wakeup; 11392 struct iax_frame *f; 11393 11394 if (timer) 11395 ast_io_add(io, ast_timer_fd(timer), timing_read, AST_IO_IN | AST_IO_PRI, NULL); 11396 11397 for(;;) { 11398 pthread_testcancel(); 11399 11400 /* Go through the queue, sending messages which have not yet been 11401 sent, and scheduling retransmissions if appropriate */ 11402 AST_LIST_LOCK(&frame_queue); 11403 count = 0; 11404 wakeup = -1; 11405 AST_LIST_TRAVERSE_SAFE_BEGIN(&frame_queue, f, list) { 11406 if (f->sentyet) 11407 continue; 11408 11409 /* Try to lock the pvt, if we can't... don't fret - defer it till later */ 11410 if (ast_mutex_trylock(&iaxsl[f->callno])) { 11411 wakeup = 1; 11412 continue; 11413 } 11414 11415 f->sentyet = 1; 11416 11417 if (iaxs[f->callno]) { 11418 send_packet(f); 11419 count++; 11420 } 11421 11422 ast_mutex_unlock(&iaxsl[f->callno]); 11423 11424 if (f->retries < 0) { 11425 /* This is not supposed to be retransmitted */ 11426 AST_LIST_REMOVE_CURRENT(list); 11427 /* Free the iax frame */ 11428 iax_frame_free(f); 11429 } else { 11430 /* We need reliable delivery. Schedule a retransmission */ 11431 f->retries++; 11432 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 11433 } 11434 } 11435 AST_LIST_TRAVERSE_SAFE_END; 11436 AST_LIST_UNLOCK(&frame_queue); 11437 11438 pthread_testcancel(); 11439 if (count >= 20) 11440 ast_debug(1, "chan_iax2: Sent %d queued outbound frames all at once\n", count); 11441 11442 /* Now do the IO, and run scheduled tasks */ 11443 res = ast_io_wait(io, wakeup); 11444 if (res >= 0) { 11445 if (res >= 20) 11446 ast_debug(1, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res); 11447 } 11448 } 11449 return NULL; 11450 }
| static struct chan_iax2_pvt* new_iax | ( | struct sockaddr_in * | sin, | |
| const char * | host | |||
| ) | [static, read] |
Definition at line 1607 of file chan_iax2.c.
References ao2_alloc, ao2_ref, AST_LIST_HEAD_INIT_NOLOCK, ast_string_field_init, ast_string_field_set, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, chan_iax2_pvt::dpentries, exten, chan_iax2_pvt::initid, chan_iax2_pvt::jb, jb_new(), jb_setconf(), chan_iax2_pvt::jbid, chan_iax2_pvt::keyrotateid, chan_iax2_pvt::lagid, jb_conf::max_contig_interp, jb_conf::max_jitterbuf, chan_iax2_pvt::pingid, prefs, chan_iax2_pvt::prefs, pvt_destructor(), jb_conf::resync_threshold, and jb_conf::target_extra.
Referenced by __find_callno().
01608 { 01609 struct chan_iax2_pvt *tmp; 01610 jb_conf jbconf; 01611 01612 if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) { 01613 return NULL; 01614 } 01615 01616 if (ast_string_field_init(tmp, 32)) { 01617 ao2_ref(tmp, -1); 01618 tmp = NULL; 01619 return NULL; 01620 } 01621 01622 tmp->prefs = prefs; 01623 tmp->pingid = -1; 01624 tmp->lagid = -1; 01625 tmp->autoid = -1; 01626 tmp->authid = -1; 01627 tmp->initid = -1; 01628 tmp->keyrotateid = -1; 01629 01630 ast_string_field_set(tmp,exten, "s"); 01631 ast_string_field_set(tmp,host, host); 01632 01633 tmp->jb = jb_new(); 01634 tmp->jbid = -1; 01635 jbconf.max_jitterbuf = maxjitterbuffer; 01636 jbconf.resync_threshold = resyncthreshold; 01637 jbconf.max_contig_interp = maxjitterinterps; 01638 jbconf.target_extra = jittertargetextra; 01639 jb_setconf(tmp->jb,&jbconf); 01640 01641 AST_LIST_HEAD_INIT_NOLOCK(&tmp->dpentries); 01642 01643 return tmp; 01644 }
| static void parse_dial_string | ( | char * | data, | |
| struct parsed_dial_string * | pds | |||
| ) | [static] |
Parses an IAX dial string into its component parts.
| data | the string to be parsed | |
| pds | pointer to a struct parsed_dial_string to be filled in |
This function parses the string and fills the structure with pointers to its component parts. The input string will be modified.
Definition at line 4564 of file chan_iax2.c.
References ast_strip_quoted(), ast_strlen_zero(), parsed_dial_string::context, parsed_dial_string::exten, parsed_dial_string::key, parsed_dial_string::options, parsed_dial_string::password, parsed_dial_string::peer, parsed_dial_string::port, strsep(), and parsed_dial_string::username.
Referenced by cache_get_callno_locked(), iax2_call(), iax2_devicestate(), and iax2_request().
04565 { 04566 if (ast_strlen_zero(data)) 04567 return; 04568 04569 pds->peer = strsep(&data, "/"); 04570 pds->exten = strsep(&data, "/"); 04571 pds->options = data; 04572 04573 if (pds->exten) { 04574 data = pds->exten; 04575 pds->exten = strsep(&data, "@"); 04576 pds->context = data; 04577 } 04578 04579 if (strchr(pds->peer, '@')) { 04580 data = pds->peer; 04581 pds->username = strsep(&data, "@"); 04582 pds->peer = data; 04583 } 04584 04585 if (pds->username) { 04586 data = pds->username; 04587 pds->username = strsep(&data, ":"); 04588 pds->password = data; 04589 } 04590 04591 data = pds->peer; 04592 pds->peer = strsep(&data, ":"); 04593 pds->port = data; 04594 04595 /* check for a key name wrapped in [] in the secret position, if found, 04596 move it to the key field instead 04597 */ 04598 if (pds->password && (pds->password[0] == '[')) { 04599 pds->key = ast_strip_quoted(pds->password, "[", "]"); 04600 pds->password = NULL; 04601 } 04602 }
| static int peer_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1406 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, and iax2_peer::name.
Referenced by load_objects().
| static int peer_delme_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 12118 of file chan_iax2.c.
References ast_set_flag, and IAX_DELME.
Referenced by delete_users().
12119 { 12120 struct iax2_peer *peer = obj; 12121 12122 ast_set_flag(peer, IAX_DELME); 12123 12124 return 0; 12125 }
| static void peer_destructor | ( | void * | obj | ) | [static] |
Definition at line 11603 of file chan_iax2.c.
References ast_dnsmgr_release(), ast_event_unsubscribe(), ast_free_ha(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_free_memory, iax2_peer::callno, iax2_peer::dnsmgr, iax2_peer::ha, iax2_destroy(), iax2_peer::mwi_event_sub, and register_peer_exten().
Referenced by build_peer().
11604 { 11605 struct iax2_peer *peer = obj; 11606 int callno = peer->callno; 11607 11608 ast_free_ha(peer->ha); 11609 11610 if (callno > 0) { 11611 ast_mutex_lock(&iaxsl[callno]); 11612 iax2_destroy(callno); 11613 ast_mutex_unlock(&iaxsl[callno]); 11614 } 11615 11616 register_peer_exten(peer, 0); 11617 11618 if (peer->dnsmgr) 11619 ast_dnsmgr_release(peer->dnsmgr); 11620 11621 if (peer->mwi_event_sub) 11622 ast_event_unsubscribe(peer->mwi_event_sub); 11623 11624 ast_string_field_free_memory(peer); 11625 }
| static int peer_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1396 of file chan_iax2.c.
References ast_str_hash(), and iax2_peer::name.
Referenced by load_objects().
01397 { 01398 const struct iax2_peer *peer = obj; 01399 01400 return ast_str_hash(peer->name); 01401 }
Definition at line 1453 of file chan_iax2.c.
References ao2_ref.
Referenced by __iax2_poke_noanswer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_unregister(), iax2_poke_peer(), realtime_peer(), reg_source_db(), socket_process(), and update_registry().
01454 { 01455 ao2_ref(peer, +1); 01456 return peer; 01457 }
| static int peer_set_sock_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 13439 of file chan_iax2.c.
References iax2_peer::sockfd.
Referenced by load_module().
13440 { 13441 struct iax2_peer *peer = obj; 13442 13443 if (peer->sockfd < 0) 13444 peer->sockfd = defaultsockfd; 13445 13446 return 0; 13447 }
| static int peer_set_srcaddr | ( | struct iax2_peer * | peer, | |
| const char * | srcaddr | |||
| ) | [static] |
Parse the "sourceaddress" value, lookup in netsock list and set peer's sockfd. Defaults to defaultsockfd if not found.
Definition at line 11531 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_debug, ast_get_ip(), ast_log(), ast_netsock_bind(), ast_netsock_find(), ast_netsock_sockfd(), ast_netsock_unref(), ast_strdupa, check_srcaddr(), IAX_DEFAULT_PORTNO, LOG_WARNING, iax2_peer::name, qos, socket_read(), iax2_peer::sockfd, iax2_trunk_peer::sockfd, and strsep().
Referenced by build_peer().
11532 { 11533 struct sockaddr_in sin; 11534 int nonlocal = 1; 11535 int port = IAX_DEFAULT_PORTNO; 11536 int sockfd = defaultsockfd; 11537 char *tmp; 11538 char *addr; 11539 char *portstr; 11540 11541 if (!(tmp = ast_strdupa(srcaddr))) 11542 return -1; 11543 11544 addr = strsep(&tmp, ":"); 11545 portstr = tmp; 11546 11547 if (portstr) { 11548 port = atoi(portstr); 11549 if (port < 1) 11550 port = IAX_DEFAULT_PORTNO; 11551 } 11552 11553 if (!ast_get_ip(&sin, addr)) { 11554 struct ast_netsock *sock; 11555 int res; 11556 11557 sin.sin_port = 0; 11558 sin.sin_family = AF_INET; 11559 res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin)); 11560 if (res == 0) { 11561 /* ip address valid. */ 11562 sin.sin_port = htons(port); 11563 if (!(sock = ast_netsock_find(netsock, &sin))) 11564 sock = ast_netsock_find(outsock, &sin); 11565 if (sock) { 11566 sockfd = ast_netsock_sockfd(sock); 11567 nonlocal = 0; 11568 } else { 11569 unsigned int orig_saddr = sin.sin_addr.s_addr; 11570 /* INADDR_ANY matches anyway! */ 11571 sin.sin_addr.s_addr = INADDR_ANY; 11572 if (ast_netsock_find(netsock, &sin)) { 11573 sin.sin_addr.s_addr = orig_saddr; 11574 sock = ast_netsock_bind(outsock, io, srcaddr, port, qos.tos, qos.cos, socket_read, NULL); 11575 if (sock) { 11576 sockfd = ast_netsock_sockfd(sock); 11577 ast_netsock_unref(sock); 11578 nonlocal = 0; 11579 } else { 11580 nonlocal = 2; 11581 } 11582 } 11583 } 11584 } 11585 } 11586 11587 peer->sockfd = sockfd; 11588 11589 if (nonlocal == 1) { 11590 ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n", 11591 srcaddr, peer->name); 11592 return -1; 11593 } else if (nonlocal == 2) { 11594 ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n", 11595 srcaddr, peer->name); 11596 return -1; 11597 } else { 11598 ast_debug(1, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name); 11599 return 0; 11600 } 11601 }
| static int peer_status | ( | struct iax2_peer * | peer, | |
| char * | status, | |||
| int | statuslen | |||
| ) | [static] |
peer_status: Report Peer status in character string
Definition at line 3377 of file chan_iax2.c.
References ast_copy_string(), iax2_peer::lastms, and iax2_peer::maxms.
Referenced by __iax2_show_peers(), function_iaxpeer(), handle_cli_iax2_show_peer(), and manager_iax2_show_peer_list().
03378 { 03379 int res = 0; 03380 if (peer->maxms) { 03381 if (peer->lastms < 0) { 03382 ast_copy_string(status, "UNREACHABLE", statuslen); 03383 } else if (peer->lastms > peer->maxms) { 03384 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 03385 res = 1; 03386 } else if (peer->lastms) { 03387 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 03388 res = 1; 03389 } else { 03390 ast_copy_string(status, "UNKNOWN", statuslen); 03391 } 03392 } else { 03393 ast_copy_string(status, "Unmonitored", statuslen); 03394 res = -1; 03395 } 03396 return res; 03397 }
Definition at line 1459 of file chan_iax2.c.
References ao2_ref.
Referenced by __expire_registry(), __iax2_poke_noanswer(), __iax2_poke_peer_s(), __iax2_show_peers(), authenticate_reply(), build_peer(), calltoken_required(), complete_iax2_peers(), complete_iax2_unregister(), create_addr(), function_iaxpeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), iax2_devicestate(), iax2_getpeername(), iax2_getpeertrunk(), iax2_poke_noanswer(), iax2_poke_peer(), manager_iax2_show_peer_list(), poke_all_peers(), prune_peers(), realtime_peer(), reg_source_db(), register_verify(), registry_authrequest(), requirecalltoken_mark_auto(), set_config(), socket_process(), unlink_peer(), and update_registry().
01460 { 01461 ao2_ref(peer, -1); 01462 return NULL; 01463 }
| static int peercnt_add | ( | struct sockaddr_in * | sin | ) | [static] |
Definition at line 2006 of file chan_iax2.c.
References peercnt::addr, iax2_trunk_peer::addr, ao2_alloc, ao2_find, ao2_link, ao2_lock(), ao2_ref, ao2_unlock(), ast_debug, ast_inet_ntoa(), ast_log(), peercnt::cur, peercnt::limit, LOG_ERROR, OBJ_POINTER, peercnts, and set_peercnt_limit().
Referenced by __find_callno(), and complete_transfer().
02007 { 02008 struct peercnt *peercnt; 02009 unsigned long addr = sin->sin_addr.s_addr; 02010 int res = 0; 02011 struct peercnt tmp = { 02012 .addr = addr, 02013 }; 02014 02015 /* Reasoning for peercnts container lock: Two identical ip addresses 02016 * could be added by different threads at the "same time". Without the container 02017 * lock, both threads could alloc space for the same object and attempt 02018 * to link to table. With the lock, one would create the object and link 02019 * to table while the other would find the already created peercnt object 02020 * rather than creating a new one. */ 02021 ao2_lock(peercnts); 02022 if ((peercnt = ao2_find(peercnts, &tmp, OBJ_POINTER))) { 02023 ao2_lock(peercnt); 02024 } else if ((peercnt = ao2_alloc(sizeof(*peercnt), NULL))) { 02025 ao2_lock(peercnt); 02026 /* create and set defaults */ 02027 peercnt->addr = addr; 02028 set_peercnt_limit(peercnt); 02029 /* guarantees it does not go away after unlocking table 02030 * ao2_find automatically adds this */ 02031 ao2_link(peercnts, peercnt); 02032 } else { 02033 ao2_unlock(peercnts); 02034 return -1; 02035 } 02036 02037 /* check to see if the address has hit its callno limit. If not increment cur. */ 02038 if (peercnt->limit > peercnt->cur) { 02039 peercnt->cur++; 02040 ast_debug(1, "ip callno count incremented to %d for %s\n", peercnt->cur, ast_inet_ntoa(sin->sin_addr)); 02041 } else { /* max num call numbers for this peer has been reached! */ 02042 ast_log(LOG_ERROR, "maxcallnumber limit of %d for %s has been reached!\n", peercnt->limit, ast_inet_ntoa(sin->sin_addr)); 02043 res = -1; 02044 } 02045 02046 /* clean up locks and ref count */ 02047 ao2_unlock(peercnt); 02048 ao2_unlock(peercnts); 02049 ao2_ref(peercnt, -1); /* decrement ref from find/alloc, only the container ref remains. */ 02050 02051 return res; 02052 }
| static int peercnt_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1850 of file chan_iax2.c.
References peercnt::addr, CMP_MATCH, and CMP_STOP.
Referenced by load_objects().
| static int peercnt_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1844 of file chan_iax2.c.
References peercnt::addr.
Referenced by load_objects().
| static void peercnt_modify | ( | unsigned char | reg, | |
| uint16_t | limit, | |||
| struct sockaddr_in * | sin | |||
| ) | [static] |
Definition at line 1978 of file chan_iax2.c.
References peercnt::addr, ao2_find, ao2_ref, ast_debug, ast_inet_ntoa(), peercnt::limit, OBJ_POINTER, peercnts, peercnt::reg, and set_peercnt_limit().
Referenced by __expire_registry(), build_peer(), and update_registry().
01979 { 01980 /* this function turns off and on custom callno limits set by peer registration */ 01981 struct peercnt *peercnt; 01982 struct peercnt tmp = { 01983 .addr = sin->sin_addr.s_addr, 01984 }; 01985 01986 if ((peercnt = ao2_find(peercnts, &tmp, OBJ_POINTER))) { 01987 peercnt->reg = reg; 01988 if (limit) { 01989 peercnt->limit = limit; 01990 } else { 01991 set_peercnt_limit(peercnt); 01992 } 01993 ast_debug(1, "peercnt entry %s modified limit:%d registered:%d", ast_inet_ntoa(sin->sin_addr), peercnt->limit, peercnt->reg); 01994 ao2_ref(peercnt, -1); /* decrement ref from find */ 01995 } 01996 }
| static void peercnt_remove | ( | struct peercnt * | peercnt | ) | [static] |
Definition at line 2058 of file chan_iax2.c.
References peercnt::addr, ao2_lock(), ao2_unlink, ao2_unlock(), ast_debug, ast_inet_ntoa(), peercnt::cur, and peercnts.
Referenced by peercnt_remove_by_addr(), and peercnt_remove_cb().
02059 { 02060 struct sockaddr_in sin = { 02061 .sin_addr.s_addr = peercnt->addr, 02062 }; 02063 02064 if (peercnt) { 02065 /* Container locked here since peercnt may be unlinked from list. If left unlocked, 02066 * peercnt_add could try and grab this entry from the table and modify it at the 02067 * "same time" this thread attemps to unlink it.*/ 02068 ao2_lock(peercnts); 02069 peercnt->cur--; 02070 ast_debug(1, "ip callno count decremented to %d for %s\n", peercnt->cur, ast_inet_ntoa(sin.sin_addr)); 02071 /* if this was the last connection from the peer remove it from table */ 02072 if (peercnt->cur == 0) { 02073 ao2_unlink(peercnts, peercnt);/* decrements ref from table, last ref is left to scheduler */ 02074 } 02075 ao2_unlock(peercnts); 02076 } 02077 }
| static int peercnt_remove_by_addr | ( | struct sockaddr_in * | sin | ) | [static] |
Definition at line 2097 of file chan_iax2.c.
References peercnt::addr, ao2_find, ao2_ref, OBJ_POINTER, peercnt_remove(), and peercnts.
Referenced by __find_callno(), and complete_transfer().
02098 { 02099 struct peercnt *peercnt; 02100 struct peercnt tmp = { 02101 .addr = sin->sin_addr.s_addr, 02102 }; 02103 02104 if ((peercnt = ao2_find(peercnts, &tmp, OBJ_POINTER))) { 02105 peercnt_remove(peercnt); 02106 ao2_ref(peercnt, -1); /* decrement ref from find */ 02107 } 02108 return 0; 02109 }
| static int peercnt_remove_cb | ( | const void * | obj | ) | [static] |
Definition at line 2083 of file chan_iax2.c.
References ao2_ref, and peercnt_remove().
Referenced by sched_delay_remove().
02084 { 02085 struct peercnt *peercnt = (struct peercnt *) obj; 02086 02087 peercnt_remove(peercnt); 02088 ao2_ref(peercnt, -1); /* decrement ref from scheduler */ 02089 02090 return 0; 02091 }
| static void poke_all_peers | ( | void | ) | [static] |
Definition at line 12623 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, iax2_poke_peer(), and peer_unref().
Referenced by reload_config().
12624 { 12625 struct ao2_iterator i; 12626 struct iax2_peer *peer; 12627 12628 i = ao2_iterator_init(peers, 0); 12629 while ((peer = ao2_iterator_next(&i))) { 12630 iax2_poke_peer(peer, 0); 12631 peer_unref(peer); 12632 } 12633 }
| static int prune_addr_range_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1967 of file chan_iax2.c.
References CMP_MATCH, and addr_range::delme.
Referenced by reload_config().
01968 { 01969 struct addr_range *addr_range = obj; 01970 01971 return addr_range->delme ? CMP_MATCH : 0; 01972 }
| static void prune_peers | ( | void | ) | [static] |
Definition at line 12178 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, ast_test_flag, IAX_DELME, IAX_RTCACHEFRIENDS, peer_unref(), and unlink_peer().
Referenced by handle_cli_iax2_prune_realtime(), and reload_config().
12179 { 12180 struct iax2_peer *peer; 12181 struct ao2_iterator i; 12182 12183 i = ao2_iterator_init(peers, 0); 12184 while ((peer = ao2_iterator_next(&i))) { 12185 if (ast_test_flag(peer, IAX_DELME) || ast_test_flag(peer, IAX_RTCACHEFRIENDS)) { 12186 unlink_peer(peer); 12187 } 12188 peer_unref(peer); 12189 } 12190 }
| static void prune_users | ( | void | ) | [static] |
Definition at line 12163 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, ao2_unlink, ast_test_flag, IAX_DELME, IAX_RTCACHEFRIENDS, and user_unref().
Referenced by handle_cli_iax2_prune_realtime(), and reload_config().
12164 { 12165 struct iax2_user *user; 12166 struct ao2_iterator i; 12167 12168 i = ao2_iterator_init(users, 0); 12169 while ((user = ao2_iterator_next(&i))) { 12170 if (ast_test_flag(user, IAX_DELME) || ast_test_flag(user, IAX_RTCACHEFRIENDS)) { 12171 ao2_unlink(users, user); 12172 } 12173 user_unref(user); 12174 } 12175 }
| static int pvt_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 13456 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, chan_iax2_pvt::frames_received, and match().
Referenced by load_objects().
13457 { 13458 struct chan_iax2_pvt *pvt = obj, *pvt2 = arg; 13459 13460 /* The frames_received field is used to hold whether we're matching 13461 * against a full frame or not ... */ 13462 13463 return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 13464 pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0; 13465 }
| static void pvt_destructor | ( | void * | obj | ) | [static] |
Definition at line 1564 of file chan_iax2.c.
References chan_iax2_pvt::addr, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_string_field_free_memory, ast_variables_destroy(), iax2_registry::callno, iax_frame::callno, chan_iax2_pvt::callno, chan_iax2_pvt::callno_entry, jb_frame::data, iax2_destroy_helper(), iax2_frame_free(), IAX_ALREADYGONE, chan_iax2_pvt::jb, jb_destroy(), jb_getall(), JB_OK, chan_iax2_pvt::owner, chan_iax2_pvt::reg, iax_frame::retries, sched_delay_remove(), and chan_iax2_pvt::vars.
Referenced by new_iax().
01565 { 01566 struct chan_iax2_pvt *pvt = obj; 01567 struct iax_frame *cur = NULL; 01568 01569 ast_mutex_lock(&iaxsl[pvt->callno]); 01570 iax2_destroy_helper(pvt); 01571 sched_delay_remove(&pvt->addr, pvt->callno_entry); 01572 pvt->callno_entry = NULL; 01573 ast_mutex_unlock(&iaxsl[pvt->callno]); 01574 01575 /* Already gone */ 01576 ast_set_flag(pvt, IAX_ALREADYGONE); 01577 01578 AST_LIST_LOCK(&frame_queue); 01579 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 01580 /* Cancel any pending transmissions */ 01581 if (cur->callno == pvt->callno) { 01582 cur->retries = -1; 01583 } 01584 } 01585 AST_LIST_UNLOCK(&frame_queue); 01586 01587 if (pvt->reg) { 01588 pvt->reg->callno = 0; 01589 } 01590 01591 if (!pvt->owner) { 01592 jb_frame frame; 01593 if (pvt->vars) { 01594 ast_variables_destroy(pvt->vars); 01595 pvt->vars = NULL; 01596 } 01597 01598 while (jb_getall(pvt->jb, &frame) == JB_OK) { 01599 iax2_frame_free(frame.data); 01600 } 01601 01602 jb_destroy(pvt->jb); 01603 ast_string_field_free_memory(pvt); 01604 } 01605 }
| static int pvt_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 13449 of file chan_iax2.c.
References chan_iax2_pvt::peercallno.
Referenced by load_objects().
13450 { 13451 const struct chan_iax2_pvt *pvt = obj; 13452 13453 return pvt->peercallno; 13454 }
| static int raw_hangup | ( | struct sockaddr_in * | sin, | |
| unsigned short | src, | |||
| unsigned short | dst, | |||
| int | sockfd | |||
| ) | [static] |
Definition at line 7181 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_inet_ntoa(), compress_subclass(), ast_iax2_full_hdr::csub, ast_iax2_full_hdr::dcallno, IAX_COMMAND_INVAL, IAX_FLAG_FULL, iax_outputframe(), ast_iax2_full_hdr::iseqno, option_debug, ast_iax2_full_hdr::oseqno, ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::ts, and ast_iax2_full_hdr::type.
Referenced by socket_process().
07182 { 07183 struct ast_iax2_full_hdr fh; 07184 fh.scallno = htons(src | IAX_FLAG_FULL); 07185 fh.dcallno = htons(dst); 07186 fh.ts = 0; 07187 fh.oseqno = 0; 07188 fh.iseqno = 0; 07189 fh.type = AST_FRAME_IAX; 07190 fh.csub = compress_subclass(IAX_COMMAND_INVAL); 07191 iax_outputframe(NULL, &fh, 0, sin, 0); 07192 #if 0 07193 if (option_debug) 07194 #endif 07195 ast_debug(1, "Raw Hangup %s:%d, src=%d, dst=%d\n", 07196 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst); 07197 return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin)); 07198 }
| static struct iax2_peer * realtime_peer | ( | const char * | peername, | |
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 3942 of file chan_iax2.c.
References iax2_peer::addr, ao2_link, ast_copy_flags, ast_debug, ast_get_time_t(), ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_sched_del(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_peer(), iax2_peer::expire, expire_registry(), hp, iax2_sched_add(), IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_TEMPONLY, iax2_peer::name, ast_variable::name, ast_variable::next, peer_ref(), peer_unref(), realtime_update_peer(), reg_source_db(), SENTINEL, ast_variable::value, and var.
Referenced by authenticate_reply(), find_peer(), and iax2_getpeername().
03943 { 03944 struct ast_variable *var = NULL; 03945 struct ast_variable *tmp; 03946 struct iax2_peer *peer=NULL; 03947 time_t regseconds = 0, nowtime; 03948 int dynamic=0; 03949 03950 if (peername) { 03951 var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", SENTINEL); 03952 if (!var && sin) 03953 var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), SENTINEL); 03954 } else if (sin) { 03955 char porta[25]; 03956 sprintf(porta, "%d", ntohs(sin->sin_port)); 03957 var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, SENTINEL); 03958 if (var) { 03959 /* We'll need the peer name in order to build the structure! */ 03960 for (tmp = var; tmp; tmp = tmp->next) { 03961 if (!strcasecmp(tmp->name, "name")) 03962 peername = tmp->value; 03963 } 03964 } 03965 } 03966 if (!var && peername) { /* Last ditch effort */ 03967 var = ast_load_realtime("iaxpeers", "name", peername, SENTINEL); 03968 /*!\note 03969 * If this one loaded something, then we need to ensure that the host 03970 * field matched. The only reason why we can't have this as a criteria 03971 * is because we only have the IP address and the host field might be 03972 * set as a name (and the reverse PTR might not match). 03973 */ 03974 if (var && sin) { 03975 for (tmp = var; tmp; tmp = tmp->next) { 03976 if (!strcasecmp(tmp->name, "host")) { 03977 struct ast_hostent ahp; 03978 struct hostent *hp; 03979 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 03980 /* No match */ 03981 ast_variables_destroy(var); 03982 var = NULL; 03983 } 03984 break; 03985 } 03986 } 03987 } 03988 } 03989 if (!var) 03990 return NULL; 03991 03992 peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1); 03993 03994 if (!peer) { 03995 ast_variables_destroy(var); 03996 return NULL; 03997 } 03998 03999 for (tmp = var; tmp; tmp = tmp->next) { 04000 /* Make sure it's not a user only... */ 04001 if (!strcasecmp(tmp->name, "type")) { 04002 if (strcasecmp(tmp->value, "friend") && 04003 strcasecmp(tmp->value, "peer")) { 04004 /* Whoops, we weren't supposed to exist! */ 04005 peer = peer_unref(peer); 04006 break; 04007 } 04008 } else if (!strcasecmp(tmp->name, "regseconds")) { 04009 ast_get_time_t(tmp->value, ®seconds, 0, NULL); 04010 } else if (!strcasecmp(tmp->name, "ipaddr")) { 04011 inet_aton(tmp->value, &(peer->addr.sin_addr)); 04012 } else if (!strcasecmp(tmp->name, "port")) { 04013 peer->addr.sin_port = htons(atoi(tmp->value)); 04014 } else if (!strcasecmp(tmp->name, "host")) { 04015 if (!strcasecmp(tmp->value, "dynamic")) 04016 dynamic = 1; 04017 } 04018 } 04019 04020 ast_variables_destroy(var); 04021 04022 if (!peer) 04023 return NULL; 04024 04025 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 04026 ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS); 04027 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) { 04028 if (peer->expire > -1) { 04029 if (!ast_sched_del(sched, peer->expire)) { 04030 peer->expire = -1; 04031 peer_unref(peer); 04032 } 04033 } 04034 peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer)); 04035 if (peer->expire == -1) 04036 peer_unref(peer); 04037 } 04038 ao2_link(peers, peer); 04039 if (ast_test_flag(peer, IAX_DYNAMIC)) 04040 reg_source_db(peer); 04041 } else { 04042 ast_set_flag(peer, IAX_TEMPONLY); 04043 } 04044 04045 if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) { 04046 time(&nowtime); 04047 if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) { 04048 memset(&peer->addr, 0, sizeof(peer->addr)); 04049 realtime_update_peer(peer->name, &peer->addr, 0); 04050 ast_debug(1, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n", 04051 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 04052 } 04053 else { 04054 ast_debug(1, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n", 04055 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 04056 } 04057 } 04058 04059 return peer; 04060 }
| static void realtime_update_peer | ( | const char * | peername, | |
| struct sockaddr_in * | sin, | |||
| time_t | regtime | |||
| ) | [static] |
Definition at line 4133 of file chan_iax2.c.
References ast_inet_ntoa(), ast_update_realtime(), and SENTINEL.
Referenced by __expire_registry(), realtime_peer(), and update_registry().
04134 { 04135 char port[10]; 04136 char regseconds[20]; 04137 04138 snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime); 04139 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 04140 ast_update_realtime("iaxpeers", "name", peername, 04141 "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 04142 "regseconds", regseconds, SENTINEL); 04143 }
| static struct iax2_user* realtime_user | ( | const char * | username, | |
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 4062 of file chan_iax2.c.
References ao2_link, ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_user(), hp, IAX_RTCACHEFRIENDS, IAX_TEMPONLY, ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.
Referenced by check_access().
04063 { 04064 struct ast_variable *var; 04065 struct ast_variable *tmp; 04066 struct iax2_user *user=NULL; 04067 04068 var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", SENTINEL); 04069 if (!var) 04070 var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), SENTINEL); 04071 if (!var && sin) { 04072 char porta[6]; 04073 snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port)); 04074 var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, SENTINEL); 04075 if (!var) 04076 var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, SENTINEL); 04077 } 04078 if (!var) { /* Last ditch effort */ 04079 var = ast_load_realtime("iaxusers", "name", username, SENTINEL); 04080 /*!\note 04081 * If this one loaded something, then we need to ensure that the host 04082 * field matched. The only reason why we can't have this as a criteria 04083 * is because we only have the IP address and the host field might be 04084 * set as a name (and the reverse PTR might not match). 04085 */ 04086 if (var) { 04087 for (tmp = var; tmp; tmp = tmp->next) { 04088 if (!strcasecmp(tmp->name, "host")) { 04089 struct ast_hostent ahp; 04090 struct hostent *hp; 04091 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 04092 /* No match */ 04093 ast_variables_destroy(var); 04094 var = NULL; 04095 } 04096 break; 04097 } 04098 } 04099 } 04100 } 04101 if (!var) 04102 return NULL; 04103 04104 tmp = var; 04105 while(tmp) { 04106 /* Make sure it's not a peer only... */ 04107 if (!strcasecmp(tmp->name, "type")) { 04108 if (strcasecmp(tmp->value, "friend") && 04109 strcasecmp(tmp->value, "user")) { 04110 return NULL; 04111 } 04112 } 04113 tmp = tmp->next; 04114 } 04115 04116 user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)); 04117 04118 ast_variables_destroy(var); 04119 04120 if (!user) 04121 return NULL; 04122 04123 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 04124 ast_set_flag(user, IAX_RTCACHEFRIENDS); 04125 ao2_link(users, user); 04126 } else { 04127 ast_set_flag(user, IAX_TEMPONLY); 04128 } 04129 04130 return user; 04131 }
| static void reg_source_db | ( | struct iax2_peer * | p | ) | [static] |
Definition at line 8042 of file chan_iax2.c.
References iax2_peer::addr, ast_db_get(), AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_inet_ntoa(), ast_sched_del(), ast_test_flag, ast_verb, iax2_peer::expire, expire_registry(), iax2_peer::expiry, iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), IAX_TEMPONLY, iax2_peer::name, peer_ref(), peer_unref(), and register_peer_exten().
Referenced by realtime_peer(), and set_config().
08043 { 08044 char data[80]; 08045 struct in_addr in; 08046 char *c, *d; 08047 if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) { 08048 c = strchr(data, ':'); 08049 if (c) { 08050 *c = '\0'; 08051 c++; 08052 if (inet_aton(data, &in)) { 08053 d = strchr(c, ':'); 08054 if (d) { 08055 *d = '\0'; 08056 d++; 08057 ast_verb(3, "Seeding '%s' at %s:%d for %d\n", p->name, 08058 ast_inet_ntoa(in), atoi(c), atoi(d)); 08059 iax2_poke_peer(p, 0); 08060 p->expiry = atoi(d); 08061 memset(&p->addr, 0, sizeof(p->addr)); 08062 p->addr.sin_family = AF_INET; 08063 p->addr.sin_addr = in; 08064 p->addr.sin_port = htons(atoi(c)); 08065 if (p->expire > -1) { 08066 if (!ast_sched_del(sched, p->expire)) { 08067 p->expire = -1; 08068 peer_unref(p); 08069 } 08070 } 08071 ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ 08072 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 08073 if (p->expire == -1) 08074 peer_unref(p); 08075 if (iax2_regfunk) 08076 iax2_regfunk(p->name, 1); 08077 register_peer_exten(p, 1); 08078 } 08079 08080 } 08081 } 08082 } 08083 }
| static void register_peer_exten | ( | struct iax2_peer * | peer, | |
| int | onoff | |||
| ) | [static] |
Definition at line 7961 of file chan_iax2.c.
References ast_add_extension(), ast_context_remove_extension(), ast_copy_string(), ast_exists_extension(), ast_free_ptr(), ast_strdup, ast_strlen_zero(), ext, iax2_peer::name, iax2_peer::regexten, S_OR, and strsep().
Referenced by __expire_registry(), peer_destructor(), reg_source_db(), and update_registry().
07962 { 07963 char multi[256]; 07964 char *stringp, *ext; 07965 if (!ast_strlen_zero(regcontext)) { 07966 ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); 07967 stringp = multi; 07968 while((ext = strsep(&stringp, "&"))) { 07969 if (onoff) { 07970 if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL)) 07971 ast_add_extension(regcontext, 1, ext, 1, NULL, NULL, 07972 "Noop", ast_strdup(peer->name), ast_free_ptr, "IAX2"); 07973 } else 07974 ast_context_remove_extension(regcontext, ext, 1, NULL); 07975 } 07976 } 07977 }
| static int register_verify | ( | int | callno, | |
| struct sockaddr_in * | sin, | |||
| struct iax_ies * | ies | |||
| ) | [static] |
Verify inbound registration.
Definition at line 7352 of file chan_iax2.c.
References ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_copy_string(), AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, chan_iax2_pvt::expiry, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, iax2_peer::inkeys, LOG_NOTICE, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax2_peer::name, iax_ies::password, peer_unref(), iax_ies::refresh, iax_ies::rsa_result, iax2_peer::secret, secret, strsep(), and iax_ies::username.
Referenced by socket_process().
07353 { 07354 char requeststr[256] = ""; 07355 char peer[256] = ""; 07356 char md5secret[256] = ""; 07357 char rsasecret[256] = ""; 07358 char secret[256] = ""; 07359 struct iax2_peer *p = NULL; 07360 struct ast_key *key; 07361 char *keyn; 07362 int x; 07363 int expire = 0; 07364 int res = -1; 07365 07366 ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 07367 /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */ 07368 if (ies->username) 07369 ast_copy_string(peer, ies->username, sizeof(peer)); 07370 if (ies->password) 07371 ast_copy_string(secret, ies->password, sizeof(secret)); 07372 if (ies->md5_result) 07373 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 07374 if (ies->rsa_result) 07375 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 07376 if (ies->refresh) 07377 expire = ies->refresh; 07378 07379 if (ast_strlen_zero(peer)) { 07380 ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr)); 07381 return -1; 07382 } 07383 07384 /* SLD: first call to lookup peer during registration */ 07385 ast_mutex_unlock(&iaxsl[callno]); 07386 p = find_peer(peer, 1); 07387 ast_mutex_lock(&iaxsl[callno]); 07388 if (!p || !iaxs[callno]) { 07389 if (iaxs[callno]) { 07390 int plaintext = ((last_authmethod & IAX_AUTH_PLAINTEXT) | (iaxs[callno]->authmethods & IAX_AUTH_PLAINTEXT)); 07391 /* Anything, as long as it's non-blank */ 07392 ast_string_field_set(iaxs[callno], secret, "badsecret"); 07393 /* An AUTHREQ must be sent in response to a REGREQ of an invalid peer unless 07394 * 1. A challenge already exists indicating a AUTHREQ was already sent out. 07395 * 2. A plaintext secret is present in ie as result of a previous AUTHREQ requesting it. 07396 * 3. A plaintext secret is present in the ie and the last_authmethod used by a peer happened 07397 * to be plaintext, indicating it is an authmethod used by other peers on the system. 07398 * 07399 * If none of these cases exist, res will be returned as 0 without authentication indicating 07400 * an AUTHREQ needs to be sent out. */ 07401 07402 if (ast_strlen_zero(iaxs[callno]->challenge) && 07403 !(!ast_strlen_zero(secret) && plaintext)) { 07404 /* by setting res to 0, an REGAUTH will be sent */ 07405 res = 0; 07406 } 07407 } 07408 if (authdebug && !p) 07409 ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 07410 goto return_unref; 07411 } 07412 07413 if (!ast_test_flag(p, IAX_DYNAMIC)) { 07414 if (authdebug) 07415 ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 07416 goto return_unref; 07417 } 07418 07419 if (!ast_apply_ha(p->ha, sin)) { 07420 if (authdebug) 07421 ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 07422 goto return_unref; 07423 } 07424 ast_string_field_set(iaxs[callno], secret, p->secret); 07425 ast_string_field_set(iaxs[callno], inkeys, p->inkeys); 07426 /* Check secret against what we have on file */ 07427 if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) { 07428 if (!ast_strlen_zero(p->inkeys)) { 07429 char tmpkeys[256]; 07430 char *stringp=NULL; 07431 ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys)); 07432 stringp=tmpkeys; 07433 keyn = strsep(&stringp, ":"); 07434 while(keyn) { 07435 key = ast_key_get(keyn, AST_KEY_PUBLIC); 07436 if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) { 07437 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 07438 break; 07439 } else if (!key) 07440 ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn); 07441 keyn = strsep(&stringp, ":"); 07442 } 07443 if (!keyn) { 07444 if (authdebug) 07445 ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys); 07446 goto return_unref; 07447 } 07448 } else { 07449 if (authdebug) 07450 ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer); 07451 goto return_unref; 07452 } 07453 } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) { 07454 struct MD5Context md5; 07455 unsigned char digest[16]; 07456 char *tmppw, *stringp; 07457 07458 tmppw = ast_strdupa(p->secret); 07459 stringp = tmppw; 07460 while((tmppw = strsep(&stringp, ";"))) { 07461 MD5Init(&md5); 07462 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 07463 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 07464 MD5Final(digest, &md5); 07465 for (x=0;x<16;x++) 07466 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 07467 if (!strcasecmp(requeststr, md5secret)) 07468 break; 07469 } 07470 if (tmppw) { 07471 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 07472 } else { 07473 if (authdebug) 07474 ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret); 07475 goto return_unref; 07476 } 07477 } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) { 07478 /* They've provided a plain text password and we support that */ 07479 if (strcmp(secret, p->secret)) { 07480 if (authdebug) 07481 ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 07482 goto return_unref; 07483 } else 07484 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 07485 } else if (!ast_strlen_zero(iaxs[callno]->challenge) && ast_strlen_zero(md5secret) && ast_strlen_zero(rsasecret)) { 07486 /* if challenge has been sent, but no challenge response if given, reject. */ 07487 goto return_unref; 07488 } 07489 ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ 07490 07491 /* either Authentication has taken place, or a REGAUTH must be sent before verifying registration */ 07492 res = 0; 07493 07494 return_unref: 07495 if (iaxs[callno]) { 07496 ast_string_field_set(iaxs[callno], peer, peer); 07497 07498 /* Choose lowest expiry number */ 07499 if (expire && (expire < iaxs[callno]->expiry)) { 07500 iaxs[callno]->expiry = expire; 07501 } 07502 } 07503 07504 if (p) { 07505 peer_unref(p); 07506 } 07507 return res; 07508 }
| static int registry_authrequest | ( | int | callno | ) | [static] |
Definition at line 8250 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_strdupa, ast_string_field_set, chan_iax2_pvt::authmethods, iax2_peer::authmethods, iax_ie_data::buf, find_peer(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_COMMAND_REGAUTH, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CHALLENGE, IAX_IE_USERNAME, peer_unref(), iax_ie_data::pos, and send_command().
Referenced by socket_process().
08251 { 08252 struct iax_ie_data ied; 08253 struct iax2_peer *p; 08254 char challenge[10]; 08255 const char *peer_name; 08256 int sentauthmethod; 08257 08258 peer_name = ast_strdupa(iaxs[callno]->peer); 08259 08260 /* SLD: third call to find_peer in registration */ 08261 ast_mutex_unlock(&iaxsl[callno]); 08262 if ((p = find_peer(peer_name, 1))) { 08263 last_authmethod = p->authmethods; 08264 } 08265 08266 ast_mutex_lock(&iaxsl[callno]); 08267 if (!iaxs[callno]) 08268 goto return_unref; 08269 08270 memset(&ied, 0, sizeof(ied)); 08271 /* The selection of which delayed reject is sent may leak information, 08272 * if it sets a static response. For example, if a host is known to only 08273 * use MD5 authentication, then an RSA response would indicate that the 08274 * peer does not exist, and vice-versa. 08275 * Therefore, we use whatever the last peer used (which may vary over the 08276 * course of a server, which should leak minimal information). */ 08277 sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT); 08278 if (!p) { 08279 iaxs[callno]->authmethods = sentauthmethod; 08280 } 08281 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod); 08282 if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) { 08283 /* Build the challenge */ 08284 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 08285 ast_string_field_set(iaxs[callno], challenge, challenge); 08286 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge); 08287 } 08288 iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name); 08289 08290 return_unref: 08291 if (p) { 08292 peer_unref(p); 08293 } 08294 08295 return iaxs[callno] ? send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1) : -1; 08296 }
| static int registry_rerequest | ( | struct iax_ies * | ies, | |
| int | callno, | |||
| struct sockaddr_in * | sin | |||
| ) | [static] |
Definition at line 8298 of file chan_iax2.c.
References add_empty_calltoken_ie(), iax2_registry::addr, ast_copy_string(), AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), authenticate(), iax_ies::authmethods, iax_ie_data::buf, iax_ies::challenge, IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax_ie_data::pos, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_AUTHSENT, REG_STATE_NOAUTH, iax2_registry::regstate, iax2_registry::secret, send_command(), iax2_registry::username, and iax_ies::username.
Referenced by socket_process().
08299 { 08300 struct iax2_registry *reg; 08301 /* Start pessimistic */ 08302 struct iax_ie_data ied; 08303 char peer[256] = ""; 08304 char challenge[256] = ""; 08305 int res; 08306 int authmethods = 0; 08307 if (ies->authmethods) 08308 authmethods = ies->authmethods; 08309 if (ies->username) 08310 ast_copy_string(peer, ies->username, sizeof(peer)); 08311 if (ies->challenge) 08312 ast_copy_string(challenge, ies->challenge, sizeof(challenge)); 08313 memset(&ied, 0, sizeof(ied)); 08314 reg = iaxs[callno]->reg; 08315 if (reg) { 08316 if (inaddrcmp(®->addr, sin)) { 08317 ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 08318 return -1; 08319 } 08320 if (ast_strlen_zero(reg->secret)) { 08321 ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username); 08322 reg->regstate = REG_STATE_NOAUTH; 08323 return -1; 08324 } 08325 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 08326 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 08327 if (reg->secret[0] == '[') { 08328 char tmpkey[256]; 08329 ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey)); 08330 tmpkey[strlen(tmpkey) - 1] = '\0'; 08331 res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL); 08332 } else 08333 res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL); 08334 if (!res) { 08335 reg->regstate = REG_STATE_AUTHSENT; 08336 add_empty_calltoken_ie(iaxs[callno], &ied); /* this _MUST_ be the last ie added */ 08337 return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 08338 } else 08339 return -1; 08340 ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer); 08341 } else 08342 ast_log(LOG_NOTICE, "Can't reregister without a reg\n"); 08343 return -1; 08344 }
| static char* regstate2str | ( | int | regstate | ) | [static] |
Definition at line 6527 of file chan_iax2.c.
References REG_STATE_AUTHSENT, REG_STATE_NOAUTH, REG_STATE_REGISTERED, REG_STATE_REGSENT, REG_STATE_REJECTED, REG_STATE_TIMEOUT, and REG_STATE_UNREGISTERED.
Referenced by handle_cli_iax2_show_registry().
06528 { 06529 switch(regstate) { 06530 case REG_STATE_UNREGISTERED: 06531 return "Unregistered"; 06532 case REG_STATE_REGSENT: 06533 return "Request Sent"; 06534 case REG_STATE_AUTHSENT: 06535 return "Auth. Sent"; 06536 case REG_STATE_REGISTERED: 06537 return "Registered"; 06538 case REG_STATE_REJECTED: 06539 return "Rejected"; 06540 case REG_STATE_TIMEOUT: 06541 return "Timeout"; 06542 case REG_STATE_NOAUTH: 06543 return "No Authentication"; 06544 default: 06545 return "Unknown"; 06546 } 06547 }
| static int reload | ( | void | ) | [static] |
Definition at line 12683 of file chan_iax2.c.
References reload_config().
12684 { 12685 return reload_config(); 12686 }
| static int reload_config | ( | void | ) | [static] |
Definition at line 12634 of file chan_iax2.c.
References ao2_callback, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_unload_realtime(), callno_limits, calltoken_ignores, config, debugaddr, iax2_do_register(), iax_provision_reload(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, peercnts, poke_all_peers(), prune_addr_range_cb(), prune_peers(), prune_users(), reload_firmware(), set_config(), and set_peercnt_limit_all_cb().
Referenced by handle_cli_iax2_reload(), and reload().
12635 { 12636 static const char config[] = "iax.conf"; 12637 struct iax2_registry *reg; 12638 12639 if (set_config(config, 1) > 0) { 12640 prune_peers(); 12641 prune_users(); 12642 ao2_callback(callno_limits, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, prune_addr_range_cb, NULL); 12643 ao2_callback(calltoken_ignores, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, prune_addr_range_cb, NULL); 12644 ao2_callback(peercnts, OBJ_NODATA, set_peercnt_limit_all_cb, NULL); 12645 trunk_timed = trunk_untimed = 0; 12646 trunk_nmaxmtu = trunk_maxmtu = 0; 12647 memset(&debugaddr, '\0', sizeof(debugaddr)); 12648 12649 AST_LIST_LOCK(®istrations); 12650 AST_LIST_TRAVERSE(®istrations, reg, entry) 12651 iax2_do_register(reg); 12652 AST_LIST_UNLOCK(®istrations); 12653 12654 /* Qualify hosts, too */ 12655 poke_all_peers(); 12656 } 12657 12658 reload_firmware(0); 12659 iax_provision_reload(1); 12660 ast_unload_realtime("iaxpeers"); 12661 12662 return 0; 12663 }
| static void reload_firmware | ( | int | unload | ) | [static] |
Definition at line 2888 of file chan_iax2.c.
References ast_config_AST_DATA_DIR, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verb, iax_firmware::dead, destroy_firmware(), dir, errno, LOG_WARNING, and try_firmware().
Referenced by __unload_module(), load_module(), and reload_config().
02889 { 02890 struct iax_firmware *cur = NULL; 02891 DIR *fwd; 02892 struct dirent *de; 02893 char dir[256], fn[256]; 02894 02895 AST_LIST_LOCK(&firmwares); 02896 02897 /* Mark all as dead */ 02898 AST_LIST_TRAVERSE(&firmwares, cur, list) 02899 cur->dead = 1; 02900 02901 /* Now that we have marked them dead... load new ones */ 02902 if (!unload) { 02903 snprintf(dir, sizeof(dir), "%s/firmware/iax", ast_config_AST_DATA_DIR); 02904 fwd = opendir(dir); 02905 if (fwd) { 02906 while((de = readdir(fwd))) { 02907 if (de->d_name[0] != '.') { 02908 snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name); 02909 if (!try_firmware(fn)) { 02910 ast_verb(2, "Loaded firmware '%s'\n", de->d_name); 02911 } 02912 } 02913 } 02914 closedir(fwd); 02915 } else 02916 ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno)); 02917 } 02918 02919 /* Clean up leftovers */ 02920 AST_LIST_TRAVERSE_SAFE_BEGIN(&firmwares, cur, list) { 02921 if (!cur->dead) 02922 continue; 02923 AST_LIST_REMOVE_CURRENT(list); 02924 destroy_firmware(cur); 02925 } 02926 AST_LIST_TRAVERSE_SAFE_END; 02927 02928 AST_LIST_UNLOCK(&firmwares); 02929 }
| static void remove_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1813 of file chan_iax2.c.
References ao2_unlink, ast_log(), LOG_ERROR, and chan_iax2_pvt::peercallno.
Referenced by complete_transfer(), iax2_destroy(), resend_with_token(), and socket_process().
01814 { 01815 if (!pvt->peercallno) { 01816 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01817 return; 01818 } 01819 01820 ao2_unlink(iax_peercallno_pvts, pvt); 01821 }
| static void remove_by_transfercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1794 of file chan_iax2.c.
References ao2_unlink, ast_log(), LOG_ERROR, and chan_iax2_pvt::transfercallno.
Referenced by complete_transfer(), and iax2_destroy().
01795 { 01796 if (!pvt->transfercallno) { 01797 ast_log(LOG_ERROR, "This should not be called without a transfer call number.\n"); 01798 return; 01799 } 01800 01801 ao2_unlink(iax_transfercallno_pvts, pvt); 01802 }
| static int replace_callno | ( | const void * | obj | ) | [static] |
Definition at line 2294 of file chan_iax2.c.
References ao2_link, ao2_lock(), ao2_ref, ao2_unlock(), ast_log(), callno_entry::callno, LOG_ERROR, total_nonval_callno_used, TRUNK_CALL_START, and callno_entry::validated.
Referenced by __find_callno(), make_trunk(), and sched_delay_remove().
02295 { 02296 struct callno_entry *callno_entry = (struct callno_entry *) obj; 02297 02298 /* the callno_pool container is locked here primarily to ensure thread 02299 * safety of the total_nonval_callno_used check and decrement */ 02300 ao2_lock(callno_pool); 02301 02302 if (!callno_entry->validated && (total_nonval_callno_used != 0)) { 02303 total_nonval_callno_used--; 02304 } else if (!callno_entry->validated && (total_nonval_callno_used == 0)) { 02305 ast_log(LOG_ERROR, "Attempted to decrement total non calltoken validated callnumbers below zero... Callno is:%d \n", callno_entry->callno); 02306 } 02307 02308 if (callno_entry->callno < TRUNK_CALL_START) { 02309 ao2_link(callno_pool, callno_entry); 02310 } else { 02311 ao2_link(callno_pool_trunk, callno_entry); 02312 } 02313 ao2_ref(callno_entry, -1); /* only container ref remains */ 02314 02315 ao2_unlock(callno_pool); 02316 return 0; 02317 }
| static void requirecalltoken_mark_auto | ( | const char * | name, | |
| int | subclass | |||
| ) | [static] |
Definition at line 4421 of file chan_iax2.c.
References ast_strlen_zero(), CALLTOKEN_AUTO, iax2_peer::calltoken_required, iax2_user::calltoken_required, CALLTOKEN_YES, find_peer(), find_user(), IAX_COMMAND_NEW, peer_unref(), and user_unref().
Referenced by handle_call_token().
04422 { 04423 struct iax2_user *user = NULL; 04424 struct iax2_peer *peer = NULL; 04425 04426 if (ast_strlen_zero(name)) { 04427 return; /* no username given */ 04428 } 04429 04430 if ((subclass == IAX_COMMAND_NEW) && (user = find_user(name)) && (user->calltoken_required == CALLTOKEN_AUTO)) { 04431 user->calltoken_required = CALLTOKEN_YES; 04432 } else if ((subclass != IAX_COMMAND_NEW) && (peer = find_peer(name, 1)) && (peer->calltoken_required == CALLTOKEN_AUTO)) { 04433 peer->calltoken_required = CALLTOKEN_YES; 04434 } 04435 04436 if (peer) { 04437 peer_unref(peer); 04438 } 04439 if (user) { 04440 user_unref(user); 04441 } 04442 }
| static void resend_with_token | ( | int | callno, | |
| struct iax_frame * | f, | |||
| const char * | newtoken | |||
| ) | [static] |
Definition at line 4337 of file chan_iax2.c.
References iax_frame::af, chan_iax2_pvt::aseqno, AST_FRAME_IAX, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, iax_ie_data::buf, chan_iax2_pvt::calltoken_ie_len, iax_frame::data, iax_frame::datalen, iax_frame::dcallno, iax_frame::encmethods, ast_frame::frametype, iax2_allow_new(), iax2_frame_free(), iax_ie_append_str(), IAX_IE_CALLTOKEN, chan_iax2_pvt::iseqno, chan_iax2_pvt::oseqno, chan_iax2_pvt::peercallno, remove_by_peercallno(), chan_iax2_pvt::rseqno, send_command(), and ast_frame::subclass.
Referenced by socket_process().
04338 { 04339 struct chan_iax2_pvt *pvt = iaxs[callno]; 04340 int frametype = f->af.frametype; 04341 int subclass = f->af.subclass; 04342 struct { 04343 struct ast_iax2_full_hdr fh; 04344 struct iax_ie_data ied; 04345 } data = { 04346 .ied.buf = { 0 }, 04347 .ied.pos = 0, 04348 }; 04349 /* total len - header len gives us the frame's IE len */ 04350 int ie_data_pos = f->datalen - sizeof(struct ast_iax2_full_hdr); 04351 04352 if (!pvt) { 04353 return; /* this should not be possible if called from socket_process() */ 04354 } 04355 04356 /* 04357 * Check to make sure last frame sent is valid for call token resend 04358 * 1. Frame should _NOT_ be encrypted since it starts the IAX dialog 04359 * 2. Frame should _NOT_ already have a destination callno 04360 * 3. Frame must be a valid iax_frame subclass capable of starting dialog 04361 * 4. Pvt must have a calltoken_ie_len which represents the number of 04362 * bytes at the end of the frame used for the previous calltoken ie. 04363 * 5. Pvt's calltoken_ie_len must be _LESS_ than the total IE length 04364 * 6. Total length of f->data must be _LESS_ than size of our data struct 04365 * because f->data must be able to fit within data. 04366 */ 04367 if (f->encmethods || f->dcallno || !iax2_allow_new(frametype, subclass, 0) 04368 || !pvt->calltoken_ie_len || (pvt->calltoken_ie_len > ie_data_pos) || 04369 (f->datalen > sizeof(data))) { 04370 04371 return; /* ignore resend, token was not valid for the dialog */ 04372 } 04373 04374 /* token is valid 04375 * 1. Copy frame data over 04376 * 2. Redo calltoken IE, it will always be the last ie in the frame. 04377 * NOTE: Having the ie always be last is not protocol specified, 04378 * it is only an implementation choice. Since we only expect the ie to 04379 * be last for frames we have sent, this can no way be affected by 04380 * another end point. 04381 * 3. Remove frame from queue 04382 * 4. Free old frame 04383 * 5. Clear previous seqnos 04384 * 6. Resend with CALLTOKEN ie. 04385 */ 04386 04387 /* ---1.--- */ 04388 memcpy(&data, f->data, f->datalen); 04389 data.ied.pos = ie_data_pos; 04390 04391 /* ---2.--- */ 04392 /* move to the beginning of the calltoken ie so we can write over it */ 04393 data.ied.pos -= pvt->calltoken_ie_len; 04394 iax_ie_append_str(&data.ied, IAX_IE_CALLTOKEN, newtoken); 04395 04396 /* make sure to update token length incase it ever has to be stripped off again */ 04397 pvt->calltoken_ie_len = data.ied.pos - ie_data_pos; /* new pos minus old pos tells how big token ie is */ 04398 04399 /* ---3.--- */ 04400 AST_LIST_LOCK(&frame_queue); 04401 AST_LIST_REMOVE(&frame_queue, f, list); 04402 AST_LIST_UNLOCK(&frame_queue); 04403 04404 /* ---4.--- */ 04405 iax2_frame_free(f); 04406 04407 /* ---5.--- */ 04408 pvt->oseqno = 0; 04409 pvt->rseqno = 0; 04410 pvt->iseqno = 0; 04411 pvt->aseqno = 0; 04412 if (pvt->peercallno) { 04413 remove_by_peercallno(pvt); 04414 pvt->peercallno = 0; 04415 } 04416 04417 /* ---6.--- */ 04418 send_command(pvt, AST_FRAME_IAX, subclass, 0, data.ied.buf, data.ied.pos, -1); 04419 }
Definition at line 8779 of file chan_iax2.c.
References ast_string_field_set, iax_frame::callno, IAX_MAX_OSPBLOCK_NUM, IAX_MAX_OSPBLOCK_SIZE, IAX_MAX_OSPBUFF_SIZE, iax_ies::ospblocklength, and iax_ies::osptokenblock.
Referenced by socket_process().
08780 { 08781 int i; 08782 unsigned int length, offset = 0; 08783 char full_osptoken[IAX_MAX_OSPBUFF_SIZE]; 08784 08785 for (i = 0; i < IAX_MAX_OSPBLOCK_NUM; i++) { 08786 length = ies->ospblocklength[i]; 08787 if (length != 0) { 08788 if (length > IAX_MAX_OSPBLOCK_SIZE) { 08789 /* OSP token block length wrong, clear buffer */ 08790 offset = 0; 08791 break; 08792 } else { 08793 memcpy(full_osptoken + offset, ies->osptokenblock[i], length); 08794 offset += length; 08795 } 08796 } else { 08797 break; 08798 } 08799 } 08800 *(full_osptoken + offset) = '\0'; 08801 if (strlen(full_osptoken) != offset) { 08802 /* OSP token length wrong, clear buffer */ 08803 *full_osptoken = '\0'; 08804 } 08805 08806 ast_string_field_set(iaxs[fr->callno], osptoken, full_osptoken); 08807 }
Definition at line 8768 of file chan_iax2.c.
References iax_frame::callno, iax_rr::delay, iax_rr::dropped, iax_rr::jitter, iax_rr::losscnt, iax_rr::losspct, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::remote_rr, iax_ies::rr_delay, iax_ies::rr_dropped, iax_ies::rr_jitter, iax_ies::rr_loss, iax_ies::rr_ooo, and iax_ies::rr_pkts.
Referenced by socket_process().
08769 { 08770 iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter; 08771 iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24; 08772 iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff; 08773 iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts; 08774 iaxs[fr->callno]->remote_rr.delay = ies->rr_delay; 08775 iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped; 08776 iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo; 08777 }
| static void sched_delay_remove | ( | struct sockaddr_in * | sin, | |
| struct callno_entry * | callno_entry | |||
| ) | [static] |
Definition at line 2366 of file chan_iax2.c.
References peercnt::addr, ao2_find, ao2_ref, ast_debug, ast_inet_ntoa(), iax2_sched_add(), MIN_REUSE_TIME, OBJ_POINTER, peercnt_remove_cb(), peercnts, and replace_callno().
Referenced by pvt_destructor().
02367 { 02368 int i; 02369 struct peercnt *peercnt; 02370 struct peercnt tmp = { 02371 .addr = sin->sin_addr.s_addr, 02372 }; 02373 02374 if ((peercnt = ao2_find(peercnts, &tmp, OBJ_POINTER))) { 02375 /* refcount is incremented with ao2_find. keep that ref for the scheduler */ 02376 ast_debug(1, "schedule decrement of callno used for %s in %d seconds\n", ast_inet_ntoa(sin->sin_addr), MIN_REUSE_TIME); 02377 i = iax2_sched_add(sched, MIN_REUSE_TIME * 1000, peercnt_remove_cb, peercnt); 02378 if (i == -1) { 02379 ao2_ref(peercnt, -1); 02380 } 02381 } 02382 02383 iax2_sched_add(sched, MIN_REUSE_TIME * 1000, replace_callno, callno_entry); 02384 }
| static void* sched_thread | ( | void * | ignore | ) | [static] |
Definition at line 11359 of file chan_iax2.c.
References ast_cond_timedwait(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), ast_tvnow(), and sched_lock.
Referenced by start_network_thread().
11360 { 11361 int count; 11362 int res; 11363 struct timeval wait; 11364 struct timespec ts; 11365 11366 for (;;) { 11367 pthread_testcancel(); 11368 ast_mutex_lock(&sched_lock); 11369 res = ast_sched_wait(sched); 11370 if ((res > 1000) || (res < 0)) 11371 res = 1000; 11372 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000)); 11373 ts.tv_sec = wait.tv_sec; 11374 ts.tv_nsec = wait.tv_usec * 1000; 11375 ast_cond_timedwait(&sched_cond, &sched_lock, &ts); 11376 ast_mutex_unlock(&sched_lock); 11377 pthread_testcancel(); 11378 11379 count = ast_sched_runq(sched); 11380 if (count >= 20) 11381 ast_debug(1, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count); 11382 } 11383 11384 return NULL; 11385 }
| static int schedule_delivery | ( | struct iax_frame * | fr, | |
| int | updatehistory, | |||
| int | fromtrunk, | |||
| unsigned int * | tsout | |||
| ) | [static] |
Definition at line 3797 of file chan_iax2.c.
References __do_deliver(), iax_frame::af, ast_bridged_channel(), AST_CHAN_TP_WANTSJITTER, ast_codec_get_samples(), ast_debug, ast_format_rate(), AST_FRAME_CNG, AST_FRAME_VOICE, ast_samp2tv(), AST_SCHED_DEL, ast_test_flag, ast_tv(), ast_tvadd(), ast_tvzero(), calc_rxstamp(), iax_frame::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), IAX_FORCEJITTERBUF, IAX_USEJITTERBUF, chan_iax2_pvt::jb, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, chan_iax2_pvt::jbid, chan_iax2_pvt::owner, ast_channel_tech::properties, chan_iax2_pvt::rxcore, ast_frame::subclass, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().
Referenced by socket_process(), and socket_process_meta().
03798 { 03799 int type, len; 03800 int ret; 03801 int needfree = 0; 03802 struct ast_channel *owner = NULL; 03803 struct ast_channel *bridge = NULL; 03804 03805 /* Attempt to recover wrapped timestamps */ 03806 unwrap_timestamp(fr); 03807 03808 /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */ 03809 if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore)) 03810 fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000)); 03811 else { 03812 #if 0 03813 ast_debug(1, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n"); 03814 #endif 03815 fr->af.delivery = ast_tv(0,0); 03816 } 03817 03818 type = JB_TYPE_CONTROL; 03819 len = 0; 03820 03821 if(fr->af.frametype == AST_FRAME_VOICE) { 03822 type = JB_TYPE_VOICE; 03823 len = ast_codec_get_samples(&fr->af) / (ast_format_rate(fr->af.subclass) / 1000); 03824 } else if(fr->af.frametype == AST_FRAME_CNG) { 03825 type = JB_TYPE_SILENCE; 03826 } 03827 03828 if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) { 03829 if (tsout) 03830 *tsout = fr->ts; 03831 __do_deliver(fr); 03832 return -1; 03833 } 03834 03835 if ((owner = iaxs[fr->callno]->owner)) 03836 bridge = ast_bridged_channel(owner); 03837 03838 /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to 03839 * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */ 03840 if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) { 03841 jb_frame frame; 03842 03843 /* deliver any frames in the jb */ 03844 while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) { 03845 __do_deliver(frame.data); 03846 /* __do_deliver() can make the call disappear */ 03847 if (!iaxs[fr->callno]) 03848 return -1; 03849 } 03850 03851 jb_reset(iaxs[fr->callno]->jb); 03852 03853 AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid); 03854 03855 /* deliver this frame now */ 03856 if (tsout) 03857 *tsout = fr->ts; 03858 __do_deliver(fr); 03859 return -1; 03860 } 03861 03862 /* insert into jitterbuffer */ 03863 /* TODO: Perhaps we could act immediately if it's not droppable and late */ 03864 ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts, 03865 calc_rxstamp(iaxs[fr->callno],fr->ts)); 03866 if (ret == JB_DROP) { 03867 needfree++; 03868 } else if (ret == JB_SCHED) { 03869 update_jbsched(iaxs[fr->callno]); 03870 } 03871 if (tsout) 03872 *tsout = fr->ts; 03873 if (needfree) { 03874 /* Free our iax frame */ 03875 iax2_frame_free(fr); 03876 return -1; 03877 } 03878 return 0; 03879 }
| static int scheduled_destroy | ( | const void * | vid | ) | [static] |
Definition at line 1550 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_destroy(), LOG_DEBUG, option_debug, and PTR_TO_CALLNO.
Referenced by iax2_hangup().
01551 { 01552 short callno = PTR_TO_CALLNO(vid); 01553 ast_mutex_lock(&iaxsl[callno]); 01554 if (iaxs[callno]) { 01555 if (option_debug) { 01556 ast_log(LOG_DEBUG, "Really destroying %d now...\n", callno); 01557 } 01558 iax2_destroy(callno); 01559 } 01560 ast_mutex_unlock(&iaxsl[callno]); 01561 return 0; 01562 }
| static int send_apathetic_reply | ( | unsigned short | callno, | |
| unsigned short | dcallno, | |||
| struct sockaddr_in * | sin, | |||
| int | command, | |||
| int | ts, | |||
| unsigned char | seqno, | |||
| int | sockfd, | |||
| struct iax_ie_data * | ied | |||
| ) | [static] |
Definition at line 4301 of file chan_iax2.c.
References AST_FRAME_IAX, iax_ie_data::buf, compress_subclass(), and iax_ie_data::pos.
Referenced by handle_call_token(), and socket_process().
04304 { 04305 struct { 04306 struct ast_iax2_full_hdr f; 04307 struct iax_ie_data ied; 04308 } data; 04309 size_t size = sizeof(struct ast_iax2_full_hdr); 04310 04311 if (ied) { 04312 size += ied->pos; 04313 memcpy(&data.ied, ied->buf, ied->pos); 04314 } 04315 04316 data.f.scallno = htons(0x8000 | callno); 04317 data.f.dcallno = htons(dcallno); 04318 data.f.ts = htonl(ts); 04319 data.f.iseqno = seqno; 04320 data.f.oseqno = 0; 04321 data.f.type = AST_FRAME_IAX; 04322 data.f.csub = compress_subclass(command); 04323 04324 return sendto(sockfd, &data, size, 0, (struct sockaddr *)sin, sizeof(*sin)); 04325 }
| static int send_command | ( | struct chan_iax2_pvt * | i, | |
| char | type, | |||
| int | command, | |||
| unsigned int | ts, | |||
| const unsigned char * | data, | |||
| int | datalen, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 6907 of file chan_iax2.c.
References __send_command().
Referenced by __attempt_transmit(), __send_lagrq(), __send_ping(), authenticate_reply(), authenticate_request(), cache_get_callno_locked(), dp_lookup(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_indicate(), iax2_key_rotate(), iax2_poke_peer(), iax2_provision(), iax2_start_transfer(), registry_authrequest(), registry_rerequest(), resend_with_token(), send_command_locked(), and socket_process().
06908 { 06909 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0); 06910 }
| static int send_command_final | ( | struct chan_iax2_pvt * | i, | |
| char | type, | |||
| int | command, | |||
| unsigned int | ts, | |||
| const unsigned char * | data, | |||
| int | datalen, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 6926 of file chan_iax2.c.
References __send_command(), chan_iax2_pvt::callno, and iax2_predestroy().
Referenced by __auth_reject(), __auto_hangup(), authenticate_request(), iax2_hangup(), socket_process(), and update_registry().
06927 { 06928 int call_num = i->callno; 06929 /* It is assumed that the callno has already been locked */ 06930 iax2_predestroy(i->callno); 06931 if (!iaxs[call_num]) 06932 return -1; 06933 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1); 06934 }
| static int send_command_immediate | ( | struct chan_iax2_pvt * | i, | |
| char | type, | |||
| int | command, | |||
| unsigned int | ts, | |||
| const unsigned char * | data, | |||
| int | datalen, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 6936 of file chan_iax2.c.
References __send_command().
Referenced by iax2_vnak(), and socket_process().
06937 { 06938 return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0); 06939 }
| static int send_command_locked | ( | unsigned short | callno, | |
| char | type, | |||
| int | command, | |||
| unsigned int | ts, | |||
| const unsigned char * | data, | |||
| int | datalen, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 6912 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), and send_command().
Referenced by iax2_answer(), iax2_digit_begin(), iax2_digit_end(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), and iax2_transfer().
06913 { 06914 int res; 06915 ast_mutex_lock(&iaxsl[callno]); 06916 res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno); 06917 ast_mutex_unlock(&iaxsl[callno]); 06918 return res; 06919 }
| static int send_command_transfer | ( | struct chan_iax2_pvt * | i, | |
| char | type, | |||
| int | command, | |||
| unsigned int | ts, | |||
| const unsigned char * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 6941 of file chan_iax2.c.
References __send_command().
Referenced by socket_process(), and try_transfer().
06942 { 06943 return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0); 06944 }
| static int send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1349 of file chan_iax2.c.
References __send_lagrq(), and schedule_action.
Referenced by __find_callno(), __send_lagrq(), and make_trunk().
01350 { 01351 #ifdef SCHED_MULTITHREADED 01352 if (schedule_action(__send_lagrq, data)) 01353 #endif 01354 __send_lagrq(data); 01355 01356 return 0; 01357 }
| static int send_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 3001 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax2_trunk_peer::addr, ast_debug, ast_inet_ntoa(), iax_frame::callno, iax_frame::data, iax_frame::datalen, errno, handle_error(), iax_showframe(), chan_iax2_pvt::peercallno, iax2_trunk_peer::sockfd, chan_iax2_pvt::transfer, transfer, iax_frame::transfer, and iax_frame::ts.
Referenced by __attempt_transmit(), iax2_send(), network_thread(), and vnak_retransmit().
03002 { 03003 int res; 03004 int callno = f->callno; 03005 03006 /* Don't send if there was an error, but return error instead */ 03007 if (!callno || !iaxs[callno] || iaxs[callno]->error) 03008 return -1; 03009 03010 /* Called with iaxsl held */ 03011 if (iaxdebug) 03012 ast_debug(3, "Sending %d on %d/%d to %s:%d\n", f->ts, callno, iaxs[callno]->peercallno, ast_inet_ntoa(iaxs[callno]->addr.sin_addr), ntohs(iaxs[callno]->addr.sin_port)); 03013 03014 if (f->transfer) { 03015 if (iaxdebug) 03016 iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr)); 03017 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer, sizeof(iaxs[callno]->transfer)); 03018 } else { 03019 if (iaxdebug) 03020 iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr)); 03021 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr, sizeof(iaxs[callno]->addr)); 03022 } 03023 if (res < 0) { 03024 if (iaxdebug) 03025 ast_debug(1, "Received error: %s\n", strerror(errno)); 03026 handle_error(); 03027 } else 03028 res = 0; 03029 03030 return res; 03031 }
| static int send_ping | ( | const void * | data | ) | [static] |
Definition at line 1304 of file chan_iax2.c.
References __send_ping(), and schedule_action.
Referenced by __find_callno(), __send_ping(), and make_trunk().
01305 { 01306 #ifdef SCHED_MULTITHREADED 01307 if (schedule_action(__send_ping, data)) 01308 #endif 01309 __send_ping(data); 01310 01311 return 0; 01312 }
| static int send_trunk | ( | struct iax2_trunk_peer * | tpeer, | |
| struct timeval * | now | |||
| ) | [static] |
Definition at line 8481 of file chan_iax2.c.
References iax2_trunk_peer::addr, iax_frame::afdata, ast_debug, ast_inet_ntoa(), ast_test_flag, calc_txpeerstamp(), iax2_trunk_peer::calls, ast_iax2_meta_hdr::cmddata, iax_frame::data, ast_iax2_meta_hdr::data, iax_frame::datalen, iax_frame::direction, DIRECTION_OUTGRESS, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_hdr::metacmd, iax_frame::retrans, iax2_trunk_peer::sockfd, iax_frame::transfer, transmit_trunk(), iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdatalen, ast_iax2_meta_trunk_hdr::ts, and ast_iax2_meta_hdr::zeros.
Referenced by iax2_trunk_queue(), and timing_read().
08482 { 08483 int res = 0; 08484 struct iax_frame *fr; 08485 struct ast_iax2_meta_hdr *meta; 08486 struct ast_iax2_meta_trunk_hdr *mth; 08487 int calls = 0; 08488 08489 /* Point to frame */ 08490 fr = (struct iax_frame *)tpeer->trunkdata; 08491 /* Point to meta data */ 08492 meta = (struct ast_iax2_meta_hdr *)fr->afdata; 08493 mth = (struct ast_iax2_meta_trunk_hdr *)meta->data; 08494 if (tpeer->trunkdatalen) { 08495 /* We're actually sending a frame, so fill the meta trunk header and meta header */ 08496 meta->zeros = 0; 08497 meta->metacmd = IAX_META_TRUNK; 08498 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) 08499 meta->cmddata = IAX_META_TRUNK_MINI; 08500 else 08501 meta->cmddata = IAX_META_TRUNK_SUPERMINI; 08502 mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now)); 08503 /* And the rest of the ast_iax2 header */ 08504 fr->direction = DIRECTION_OUTGRESS; 08505 fr->retrans = -1; 08506 fr->transfer = 0; 08507 /* Any appropriate call will do */ 08508 fr->data = fr->afdata; 08509 fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr); 08510 res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd); 08511 calls = tpeer->calls; 08512 #if 0 08513 ast_debug(1, "Trunking %d call chunks in %d bytes to %s:%d, ts=%d\n", calls, fr->datalen, ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), ntohl(mth->ts)); 08514 #endif 08515 /* Reset transmit trunk side data */ 08516 tpeer->trunkdatalen = 0; 08517 tpeer->calls = 0; 08518 } 08519 if (res < 0) 08520 return res; 08521 return calls; 08522 }
| static int set_config | ( | const char * | config_file, | |
| int | reload | |||
| ) | [static] |
Load configuration.
Definition at line 12211 of file chan_iax2.c.
References add_calltoken_ignore(), ao2_link, ast_category_browse(), ast_cdr_amaflags2int(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_context_find_or_create(), ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_netsock_bind(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_netsock_sockfd(), ast_netsock_unref(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_str2cos(), ast_str2tos(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, build_callno_limits(), build_peer(), build_user(), capability, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MAXCALLNO_LIMIT, DEFAULT_MAXCALLNO_LIMIT_NONVAL, DEFAULT_MAXMS, errno, format, gen, get_encrypt_methods(), global_maxcallno, global_maxcallno_nonval, iax2_register(), IAX_ALLOWFWDOWNLOAD, IAX_CAPABILITY_FULLBANDWIDTH, IAX_CAPABILITY_LOWBANDWIDTH, IAX_CAPABILITY_MEDBANDWIDTH, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_ENCRYPT_KEYROTATE, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_RTUPDATE, IAX_TRANSFERMEDIA, IAX_TRUNKTIMESTAMPS, IAX_USEJITTERBUF, iaxmaxthreadcount, iaxthreadcount, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MAX_TRUNK_MTU, MAX_TRUNKDATA, ast_variable::name, ast_variable::next, peer_unref(), prefs, qos, reg_source_db(), secret, set_config_destroy(), socket_read(), user_unref(), and ast_variable::value.
Referenced by load_module(), and reload_config().
12212 { 12213 struct ast_config *cfg, *ucfg; 12214 int capability=iax2_capability; 12215 struct ast_variable *v; 12216 char *cat; 12217 const char *utype; 12218 const char *tosval; 12219 int format; 12220 int portno = IAX_DEFAULT_PORTNO; 12221 int x; 12222 int mtuv; 12223 struct iax2_user *user; 12224 struct iax2_peer *peer; 12225 struct ast_netsock *ns; 12226 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 12227 #if 0 12228 static unsigned short int last_port=0; 12229 #endif 12230 12231 cfg = ast_config_load(config_file, config_flags); 12232 12233 if (!cfg) { 12234 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); 12235 return -1; 12236 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 12237 ucfg = ast_config_load("users.conf", config_flags); 12238 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 12239 return 0; 12240 /* Otherwise we need to reread both files */ 12241 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 12242 cfg = ast_config_load(config_file, config_flags); 12243 } else { /* iax.conf changed, gotta reread users.conf, too */ 12244 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 12245 ucfg = ast_config_load("users.conf", config_flags); 12246 } 12247 12248 if (reload) { 12249 set_config_destroy(); 12250 } 12251 12252 /* Reset global codec prefs */ 12253 memset(&prefs, 0 , sizeof(struct ast_codec_pref)); 12254 12255 /* Reset Global Flags */ 12256 memset(&globalflags, 0, sizeof(globalflags)); 12257 ast_set_flag(&globalflags, IAX_RTUPDATE); 12258 12259 /* Turns on support for key rotation during encryption. */ 12260 iax2_encryption |= IAX_ENCRYPT_KEYROTATE; 12261 #ifdef SO_NO_CHECK 12262 nochecksums = 0; 12263 #endif 12264 /* Reset default parking lot */ 12265 default_parkinglot[0] = '\0'; 12266 12267 min_reg_expire = IAX_DEFAULT_REG_EXPIRE; 12268 max_reg_expire = IAX_DEFAULT_REG_EXPIRE; 12269 global_max_trunk_mtu = MAX_TRUNK_MTU; 12270 global_maxcallno = DEFAULT_MAXCALLNO_LIMIT; 12271 global_maxcallno_nonval = DEFAULT_MAXCALLNO_LIMIT_NONVAL; 12272 12273 maxauthreq = 3; 12274 12275 srvlookup = 0; 12276 12277 v = ast_variable_browse(cfg, "general"); 12278 12279 /* Seed initial tos value */ 12280 tosval = ast_variable_retrieve(cfg, "general", "tos"); 12281 if (tosval) { 12282 if (ast_str2tos(tosval, &qos.tos)) 12283 ast_log(LOG_WARNING, "Invalid tos value, refer to QoS documentation\n"); 12284 } 12285 /* Seed initial cos value */ 12286 tosval = ast_variable_retrieve(cfg, "general", "cos"); 12287 if (tosval) { 12288 if (ast_str2cos(tosval, &qos.cos)) 12289 ast_log(LOG_WARNING, "Invalid cos value, refer to QoS documentation\n"); 12290 } 12291 while(v) { 12292 if (!strcasecmp(v->name, "bindport")){ 12293 if (reload) 12294 ast_log(LOG_NOTICE, "Ignoring bindport on reload\n"); 12295 else 12296 portno = atoi(v->value); 12297 } else if (!strcasecmp(v->name, "pingtime")) 12298 ping_time = atoi(v->value); 12299 else if (!strcasecmp(v->name, "iaxthreadcount")) { 12300 if (reload) { 12301 if (atoi(v->value) != iaxthreadcount) 12302 ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n"); 12303 } else { 12304 iaxthreadcount = atoi(v->value); 12305 if (iaxthreadcount < 1) { 12306 ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n"); 12307 iaxthreadcount = 1; 12308 } else if (iaxthreadcount > 256) { 12309 ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n"); 12310 iaxthreadcount = 256; 12311 } 12312 } 12313 } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) { 12314 if (reload) { 12315 AST_LIST_LOCK(&dynamic_list); 12316 iaxmaxthreadcount = atoi(v->value); 12317 AST_LIST_UNLOCK(&dynamic_list); 12318 } else { 12319 iaxmaxthreadcount = atoi(v->value); 12320 if (iaxmaxthreadcount < 0) { 12321 ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n"); 12322 iaxmaxthreadcount = 0; 12323 } else if (iaxmaxthreadcount > 256) { 12324 ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n"); 12325 iaxmaxthreadcount = 256; 12326 } 12327 } 12328 } else if (!strcasecmp(v->name, "nochecksums")) { 12329 #ifdef SO_NO_CHECK 12330 if (ast_true(v->value)) 12331 nochecksums = 1; 12332 else 12333 nochecksums = 0; 12334 #else 12335 if (ast_true(v->value)) 12336 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 12337 #endif 12338 } 12339 else if (!strcasecmp(v->name, "maxjitterbuffer")) 12340 maxjitterbuffer = atoi(v->value); 12341 else if (!strcasecmp(v->name, "resyncthreshold")) 12342 resyncthreshold = atoi(v->value); 12343 else if (!strcasecmp(v->name, "maxjitterinterps")) 12344 maxjitterinterps = atoi(v->value); 12345 else if (!strcasecmp(v->name, "jittertargetextra")) 12346 jittertargetextra = atoi(v->value); 12347 else if (!strcasecmp(v->name, "lagrqtime")) 12348 lagrq_time = atoi(v->value); 12349 else if (!strcasecmp(v->name, "maxregexpire")) 12350 max_reg_expire = atoi(v->value); 12351 else if (!strcasecmp(v->name, "minregexpire")) 12352 min_reg_expire = atoi(v->value); 12353 else if (!strcasecmp(v->name, "bindaddr")) { 12354 if (reload) { 12355 ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n"); 12356 } else { 12357 if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, qos.tos, qos.cos, socket_read, NULL))) { 12358 ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno); 12359 } else { 12360 if (strchr(v->value, ':')) 12361 ast_verb(2, "Binding IAX2 to '%s'\n", v->value); 12362 else 12363 ast_verb(2, "Binding IAX2 to '%s:%d'\n", v->value, portno); 12364 if (defaultsockfd < 0) 12365 defaultsockfd = ast_netsock_sockfd(ns); 12366 ast_netsock_unref(ns); 12367 } 12368 } 12369 } else if (!strcasecmp(v->name, "authdebug")) 12370 authdebug = ast_true(v->value); 12371 else if (!strcasecmp(v->name, "encryption")) 12372 iax2_encryption |= get_encrypt_methods(v->value); 12373 else if (!strcasecmp(v->name, "transfer")) { 12374 if (!strcasecmp(v->value, "mediaonly")) { 12375 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 12376 } else if (ast_true(v->value)) { 12377 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 12378 } else 12379 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 12380 } else if (!strcasecmp(v->name, "codecpriority")) { 12381 if(!strcasecmp(v->value, "caller")) 12382 ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST); 12383 else if(!strcasecmp(v->value, "disabled")) 12384 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 12385 else if(!strcasecmp(v->value, "reqonly")) { 12386 ast_set_flag((&globalflags), IAX_CODEC_NOCAP); 12387 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 12388 } 12389 } else if (!strcasecmp(v->name, "jitterbuffer")) 12390 ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 12391 else if (!strcasecmp(v->name, "forcejitterbuffer")) 12392 ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF); 12393 else if (!strcasecmp(v->name, "delayreject")) 12394 delayreject = ast_true(v->value); 12395 else if (!strcasecmp(v->name, "allowfwdownload")) 12396 ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD); 12397 else if (!strcasecmp(v->name, "rtcachefriends")) 12398 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS); 12399 else if (!strcasecmp(v->name, "rtignoreregexpire")) 12400 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE); 12401 else if (!strcasecmp(v->name, "rtupdate")) 12402 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE); 12403 else if (!strcasecmp(v->name, "trunktimestamps")) 12404 ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS); 12405 else if (!strcasecmp(v->name, "rtautoclear")) { 12406 int i = atoi(v->value); 12407 if(i > 0) 12408 global_rtautoclear = i; 12409 else 12410 i = 0; 12411 ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR); 12412 } else if (!strcasecmp(v->name, "trunkfreq")) { 12413 trunkfreq = atoi(v->value); 12414 if (trunkfreq < 10) 12415 trunkfreq = 10; 12416 } else if (!strcasecmp(v->name, "trunkmtu")) { 12417 mtuv = atoi(v->value); 12418 if (mtuv == 0 ) 12419 global_max_trunk_mtu = 0; 12420 else if (mtuv >= 172 && mtuv < 4000) 12421 global_max_trunk_mtu = mtuv; 12422 else 12423 ast_log(LOG_NOTICE, "trunkmtu value out of bounds (%d) at line %d\n", 12424 mtuv, v->lineno); 12425 } else if (!strcasecmp(v->name, "trunkmaxsize")) { 12426 trunkmaxsize = atoi(v->value); 12427 if (trunkmaxsize == 0) 12428 trunkmaxsize = MAX_TRUNKDATA; 12429 } else if (!strcasecmp(v->name, "autokill")) { 12430 if (sscanf(v->value, "%30d", &x) == 1) { 12431 if (x >= 0) 12432 autokill = x; 12433 else 12434 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); 12435 } else if (ast_true(v->value)) { 12436 autokill = DEFAULT_MAXMS; 12437 } else { 12438 autokill = 0; 12439 } 12440 } else if (!strcasecmp(v->name, "bandwidth")) { 12441 if (!strcasecmp(v->value, "low")) { 12442 capability = IAX_CAPABILITY_LOWBANDWIDTH; 12443 } else if (!strcasecmp(v->value, "medium")) { 12444 capability = IAX_CAPABILITY_MEDBANDWIDTH; 12445 } else if (!strcasecmp(v->value, "high")) { 12446 capability = IAX_CAPABILITY_FULLBANDWIDTH; 12447 } else 12448 ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n"); 12449 } else if (!strcasecmp(v->name, "allow")) { 12450 ast_parse_allow_disallow(&prefs, &capability, v->value, 1); 12451 } else if (!strcasecmp(v->name, "disallow")) { 12452 ast_parse_allow_disallow(&prefs, &capability, v->value, 0); 12453 } else if (!strcasecmp(v->name, "register")) { 12454 iax2_register(v->value, v->lineno); 12455 } else if (!strcasecmp(v->name, "iaxcompat")) { 12456 iaxcompat = ast_true(v->value); 12457 } else if (!strcasecmp(v->name, "regcontext")) { 12458 ast_copy_string(regcontext, v->value, sizeof(regcontext)); 12459 /* Create context if it doesn't exist already */ 12460 ast_context_find_or_create(NULL, NULL, regcontext, "IAX2"); 12461 } else if (!strcasecmp(v->name, "tos")) { 12462 if (ast_str2tos(v->value, &qos.tos)) 12463 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); 12464 } else if (!strcasecmp(v->name, "cos")) { 12465 if (ast_str2cos(v->value, &qos.cos)) 12466 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno); 12467 } else if (!strcasecmp(v->name, "parkinglot")) { 12468 ast_copy_string(default_parkinglot, v->value, sizeof(default_parkinglot)); 12469 } else if (!strcasecmp(v->name, "accountcode")) { 12470 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 12471 } else if (!strcasecmp(v->name, "mohinterpret")) { 12472 ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret)); 12473 } else if (!strcasecmp(v->name, "mohsuggest")) { 12474 ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest)); 12475 } else if (!strcasecmp(v->name, "amaflags")) { 12476 format = ast_cdr_amaflags2int(v->value); 12477 if (format < 0) { 12478 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 12479 } else { 12480 amaflags = format; 12481 } 12482 } else if (!strcasecmp(v->name, "language")) { 12483 ast_copy_string(language, v->value, sizeof(language)); 12484 } else if (!strcasecmp(v->name, "maxauthreq")) { 12485 maxauthreq = atoi(v->value); 12486 if (maxauthreq < 0) 12487 maxauthreq = 0; 12488 } else if (!strcasecmp(v->name, "adsi")) { 12489 adsi = ast_true(v->value); 12490 } else if (!strcasecmp(v->name, "srvlookup")) { 12491 srvlookup = ast_true(v->value); 12492 } else if (!strcasecmp(v->name, "maxcallnumbers")) { 12493 if (sscanf(v->value, "%10hu", &global_maxcallno) != 1) { 12494 ast_log(LOG_WARNING, "maxcallnumbers must be set to a valid number. %s is not valid at line %d\n", v->value, v->lineno); 12495 } 12496 } else if (!strcasecmp(v->name, "maxcallnumbers_nonvalidated")) { 12497 if (sscanf(v->value, "%10hu", &global_maxcallno_nonval) != 1) { 12498 ast_log(LOG_WARNING, "maxcallnumbers_nonvalidated must be set to a valid number. %s is not valid at line %d.\n", v->value, v->lineno); 12499 } 12500 } else if(!strcasecmp(v->name, "calltokenoptional")) { 12501 if (add_calltoken_ignore(v->value)) { 12502 ast_log(LOG_WARNING, "Invalid calltokenoptional address range - '%s' line %d\n", v->value, v->lineno); 12503 } 12504 }/*else if (strcasecmp(v->name,"type")) */ 12505 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 12506 v = v->next; 12507 } 12508 12509 if (defaultsockfd < 0) { 12510 if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, qos.tos, qos.cos, socket_read, NULL))) { 12511 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 12512 } else { 12513 ast_verb(2, "Binding IAX2 to default address 0.0.0.0:%d\n", portno); 12514 defaultsockfd = ast_netsock_sockfd(ns); 12515 ast_netsock_unref(ns); 12516 } 12517 } 12518 if (reload) { 12519 ast_netsock_release(outsock); 12520 outsock = ast_netsock_list_alloc(); 12521 if (!outsock) { 12522 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 12523 return -1; 12524 } 12525 ast_netsock_init(outsock); 12526 } 12527 12528 if (min_reg_expire > max_reg_expire) { 12529 ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n", 12530 min_reg_expire, max_reg_expire, max_reg_expire); 12531 min_reg_expire = max_reg_expire; 12532 } 12533 iax2_capability = capability; 12534 12535 if (ucfg) { 12536 struct ast_variable *gen; 12537 int genhasiax; 12538 int genregisteriax; 12539 const char *hasiax, *registeriax; 12540 12541 genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax")); 12542 genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax")); 12543 gen = ast_variable_browse(ucfg, "general"); 12544 cat = ast_category_browse(ucfg, NULL); 12545 while (cat) { 12546 if (strcasecmp(cat, "general")) { 12547 hasiax = ast_variable_retrieve(ucfg, cat, "hasiax"); 12548 registeriax = ast_variable_retrieve(ucfg, cat, "registeriax"); 12549 if (ast_true(hasiax) || (!hasiax && genhasiax)) { 12550 /* Start with general parameters, then specific parameters, user and peer */ 12551 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0); 12552 if (user) { 12553 ao2_link(users, user); 12554 user = user_unref(user); 12555 } 12556 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); 12557 if (peer) { 12558 if (ast_test_flag(peer, IAX_DYNAMIC)) 12559 reg_source_db(peer); 12560 ao2_link(peers, peer); 12561 peer = peer_unref(peer); 12562 } 12563 } 12564 if (ast_true(registeriax) || (!registeriax && genregisteriax)) { 12565 char tmp[256]; 12566 const char *host = ast_variable_retrieve(ucfg, cat, "host"); 12567 const char *username = ast_variable_retrieve(ucfg, cat, "username"); 12568 const char *secret = ast_variable_retrieve(ucfg, cat, "secret"); 12569 if (!host) 12570 host = ast_variable_retrieve(ucfg, "general", "host"); 12571 if (!username) 12572 username = ast_variable_retrieve(ucfg, "general", "username"); 12573 if (!secret) 12574 secret = ast_variable_retrieve(ucfg, "general", "secret"); 12575 if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { 12576 if (!ast_strlen_zero(secret)) 12577 snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host); 12578 else 12579 snprintf(tmp, sizeof(tmp), "%s@%s", username, host); 12580 iax2_register(tmp, 0); 12581 } 12582 } 12583 } 12584 cat = ast_category_browse(ucfg, cat); 12585 } 12586 ast_config_destroy(ucfg); 12587 } 12588 12589 cat = ast_category_browse(cfg, NULL); 12590 while(cat) { 12591 if (strcasecmp(cat, "general")) { 12592 utype = ast_variable_retrieve(cfg, cat, "type"); 12593 if (!strcasecmp(cat, "callnumberlimits")) { 12594 build_callno_limits(ast_variable_browse(cfg, cat)); 12595 } else if (utype) { 12596 if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) { 12597 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0); 12598 if (user) { 12599 ao2_link(users, user); 12600 user = user_unref(user); 12601 } 12602 } 12603 if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) { 12604 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); 12605 if (peer) { 12606 if (ast_test_flag(peer, IAX_DYNAMIC)) 12607 reg_source_db(peer); 12608 ao2_link(peers, peer); 12609 peer = peer_unref(peer); 12610 } 12611 } else if (strcasecmp(utype, "user")) { 12612 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file); 12613 } 12614 } else 12615 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 12616 } 12617 cat = ast_category_browse(cfg, cat); 12618 } 12619 ast_config_destroy(cfg); 12620 return 1; 12621 }
| static void set_config_destroy | ( | void | ) | [static] |
Definition at line 12192 of file chan_iax2.c.
References addr_range_delme_cb(), ao2_callback, ast_clear_flag, callno_limits, calltoken_ignores, delete_users(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, MAX_TRUNKDATA, and OBJ_NODATA.
Referenced by set_config().
12193 { 12194 strcpy(accountcode, ""); 12195 strcpy(language, ""); 12196 strcpy(mohinterpret, "default"); 12197 strcpy(mohsuggest, ""); 12198 trunkmaxsize = MAX_TRUNKDATA; 12199 amaflags = 0; 12200 delayreject = 0; 12201 ast_clear_flag((&globalflags), IAX_NOTRANSFER); 12202 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 12203 ast_clear_flag((&globalflags), IAX_USEJITTERBUF); 12204 ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF); 12205 delete_users(); 12206 ao2_callback(callno_limits, OBJ_NODATA, addr_range_delme_cb, NULL); 12207 ao2_callback(calltoken_ignores, OBJ_NODATA, addr_range_delme_cb, NULL); 12208 }
| static void set_peercnt_limit | ( | struct peercnt * | peercnt | ) | [static] |
Definition at line 1927 of file chan_iax2.c.
References peercnt::addr, addr_range_match_address_cb(), ao2_callback, ao2_ref, ast_debug, ast_inet_ntoa(), callno_limits, global_maxcallno, addr_range::limit, peercnt::limit, and peercnt::reg.
Referenced by peercnt_add(), peercnt_modify(), and set_peercnt_limit_all_cb().
01928 { 01929 uint16_t limit = global_maxcallno; 01930 struct addr_range *addr_range; 01931 struct sockaddr_in sin = { 01932 .sin_addr.s_addr = peercnt->addr, 01933 }; 01934 01935 01936 if (peercnt->reg && peercnt->limit) { 01937 return; /* this peercnt has a custom limit set by a registration */ 01938 } 01939 01940 if ((addr_range = ao2_callback(callno_limits, 0, addr_range_match_address_cb, &sin))) { 01941 limit = addr_range->limit; 01942 ast_debug(1, "custom addr_range %d found for %s\n", limit, ast_inet_ntoa(sin.sin_addr)); 01943 ao2_ref(addr_range, -1); 01944 } 01945 01946 peercnt->limit = limit; 01947 }
| static int set_peercnt_limit_all_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1953 of file chan_iax2.c.
References ast_debug, and set_peercnt_limit().
Referenced by reload_config().
01954 { 01955 struct peercnt *peercnt = obj; 01956 01957 set_peercnt_limit(peercnt); 01958 ast_debug(1, "Reset limits for peercnts table\n"); 01959 01960 return 0; 01961 }
| static void signal_condition | ( | ast_mutex_t * | lock, | |
| ast_cond_t * | cond | |||
| ) | [static] |
Definition at line 899 of file chan_iax2.c.
References ast_cond_signal(), ast_mutex_lock(), and ast_mutex_unlock().
Referenced by __schedule_action(), iax2_process_thread(), iax2_sched_add(), iax2_sched_replace(), iax2_transmit(), and socket_read().
00900 { 00901 ast_mutex_lock(lock); 00902 ast_cond_signal(cond); 00903 ast_mutex_unlock(lock); 00904 }
| static int socket_process | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 9205 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, ast_aes_decrypt_key, ast_async_goto(), ast_best_codec(), ast_bridged_channel(), ast_calloc, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_channel_datastore_add(), ast_channel_trylock, ast_channel_unlock, ast_clear_flag, ast_codec_choose(), ast_codec_get_samples(), ast_codec_pref_convert(), ast_codec_pref_index(), ast_codec_pref_string(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_datastore_alloc, ast_datastore_free(), ast_debug, AST_DEVICE_NOT_INUSE, AST_DEVICE_UNAVAILABLE, ast_devstate_changed(), ast_exists_extension(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_IAX, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_free, ast_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), ast_sched_del(), AST_SCHED_DEL, ast_set_flag, ast_set_read_format(), ast_set_write_format(), AST_STATE_RING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_var_assign(), ast_variables_destroy(), ast_verb, auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), chan_iax2_pvt::authmethods, iax_ie_data::buf, iax2_thread::buf, iax2_thread::buf_len, CACHE_FLAG_TRANSMITTED, iax_frame::cacheable, calc_timestamp(), iax_ies::called_number, iax2_peer::callno, chan_iax2_pvt::callno, iax_frame::callno, iax_ies::calltoken, iax_ies::calltokendata, chan_iax2_pvt::capability, iax_ies::cause, iax_ies::causecode, iax_ies::challenge, check_access(), check_provisioning(), chan_iax2_pvt::chosenformat, chan_iax2_pvt::cid_num, cid_num, iax_ies::codec_prefs, complete_dpreply(), complete_transfer(), construct_rr(), context, chan_iax2_pvt::context, ast_iax2_full_hdr::csub, ast_datastore::data, ast_frame::data, ast_frame::datalen, DATASTORE_INHERIT_FOREVER, ast_iax2_full_hdr::dcallno, DEADLOCK_AVOIDANCE, decrypt_frame(), iax_ies::devicetype, dp_lookup(), chan_iax2_pvt::encmethods, iax_ies::encmethods, chan_iax2_pvt::error, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, chan_iax2_pvt::exten, iax_frame::final, find_callno(), chan_iax2_pvt::first_iax_message, iax2_dpcache::flags, iax_ies::format, format, chan_iax2_pvt::frames_received, ast_frame::frametype, iax_ies::fwdesc, handle_call_token(), ast_channel::hangupcause, iax2_peer::historicms, iax2_ack_registry(), iax2_allow_new(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_queue_control_data(), iax2_queue_frame(), iax2_sched_add(), iax2_send(), iax2_vnak(), IAX_ALLOWFWDOWNLOAD, IAX_ALREADYGONE, IAX_AUTH_MD5, IAX_CALLENCRYPTED, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, IAX_COMMAND_CALLTOKEN, IAX_COMMAND_DIAL, IAX_COMMAND_DPREP, IAX_COMMAND_DPREQ, IAX_COMMAND_FWDATA, IAX_COMMAND_FWDOWNL, IAX_COMMAND_HANGUP, IAX_COMMAND_INVAL, IAX_COMMAND_LAGRP, IAX_COMMAND_LAGRQ, IAX_COMMAND_NEW, IAX_COMMAND_PING, IAX_COMMAND_POKE, IAX_COMMAND_PONG, IAX_COMMAND_QUELCH, IAX_COMMAND_REGACK, IAX_COMMAND_REGAUTH, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, IAX_COMMAND_RTKEY, IAX_COMMAND_TRANSFER, IAX_COMMAND_TXACC, IAX_COMMAND_TXCNT, IAX_COMMAND_TXMEDIA, IAX_COMMAND_TXREADY, IAX_COMMAND_TXREJ, IAX_COMMAND_TXREL, IAX_COMMAND_TXREQ, IAX_COMMAND_UNQUELCH, IAX_COMMAND_UNSUPPORT, IAX_COMMAND_VNAK, IAX_DEBUGDIGEST, IAX_DELAYPBXSTART, IAX_ENCRYPTED, iax_firmware_append(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_wrap(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLNO, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_FORMAT, IAX_IE_IAX_UNKNOWN, iax_outputframe(), iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_TRUNK, iax_ies::iax_unknown, iaxfrdup2(), chan_iax2_pvt::iaxvars, inaddrcmp(), ast_datastore::inheritance, chan_iax2_pvt::initid, chan_iax2_pvt::inkeys, iax2_thread::iofd, iax2_thread::iosin, chan_iax2_pvt::iseqno, iax_frame::iseqno, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::last, chan_iax2_pvt::last_iax_message, iax2_peer::lastms, ast_frame::len, LOG_ERROR, log_jitterstats(), LOG_NOTICE, LOG_WARNING, make_trunk(), ast_frame::mallocd, manager_event, iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, chan_iax2_pvt::mohsuggest, iax_ies::musiconhold, iax2_peer::name, ast_variable::name, ast_channel::nativeformats, NEW_ALLOW, NEW_ALLOW_CALLTOKEN_VALIDATED, NEW_PREVENT, ast_variable::next, ast_frame::offset, chan_iax2_pvt::oseqno, iax_frame::oseqno, ast_iax2_full_hdr::oseqno, iax_frame::outoforder, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), peer_ref(), peer_unref(), chan_iax2_pvt::peercallno, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, chan_iax2_pvt::prefs, iax_ies::provver, iax_ies::provverpres, ast_frame::ptr, raw_hangup(), ast_channel::readformat, iax_ies::refresh, REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), remove_by_peercallno(), resend_with_token(), iax_frame::retries, chan_iax2_pvt::rprefs, chan_iax2_pvt::rseqno, S_OR, ast_frame::samples, save_osptoken(), save_rr(), ast_iax2_full_hdr::scallno, schedule_delivery(), chan_iax2_pvt::secret, send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax_ies::serviceident, iax2_peer::smoothing, socket_process_meta(), spawn_dp_lookup(), ast_frame::src, chan_iax2_pvt::state, stop_stuff(), store_by_peercallno(), ast_frame::subclass, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MEDIAPASS, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, try_transfer(), iax_frame::ts, ast_iax2_full_hdr::ts, ast_iax2_full_hdr::type, uncompress_subclass(), update_registry(), iax_ies::username, ast_variable::value, var, iax_ies::vars, VERBOSE_PREFIX_4, chan_iax2_pvt::videoformat, vnak_retransmit(), chan_iax2_pvt::voiceformat, and ast_iax2_meta_hdr::zeros.
Referenced by handle_deferred_full_frames(), and iax2_process_thread().
09206 { 09207 struct sockaddr_in sin; 09208 int res; 09209 int updatehistory=1; 09210 int new = NEW_PREVENT; 09211 int dcallno = 0; 09212 struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf; 09213 struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf; 09214 struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf; 09215 struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf; 09216 struct iax_frame *fr; 09217 struct iax_frame *cur; 09218 struct ast_frame f = { 0, }; 09219 struct ast_channel *c = NULL; 09220 struct iax2_dpcache *dp; 09221 struct iax2_peer *peer; 09222 struct iax_ies ies; 09223 struct iax_ie_data ied0, ied1; 09224 int format; 09225 int fd; 09226 int exists; 09227 int minivid = 0; 09228 char empty[32]=""; /* Safety measure */ 09229 struct iax_frame *duped_fr; 09230 char host_pref_buf[128]; 09231 char caller_pref_buf[128]; 09232 struct ast_codec_pref pref; 09233 char *using_prefs = "mine"; 09234 09235 /* allocate an iax_frame with 4096 bytes of data buffer */ 09236 fr = alloca(sizeof(*fr) + 4096); 09237 memset(fr, 0, sizeof(*fr)); 09238 fr->afdatalen = 4096; /* From alloca() above */ 09239 09240 /* Copy frequently used parameters to the stack */ 09241 res = thread->buf_len; 09242 fd = thread->iofd; 09243 memcpy(&sin, &thread->iosin, sizeof(sin)); 09244 09245 if (res < sizeof(*mh)) { 09246 ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int) sizeof(*mh)); 09247 return 1; 09248 } 09249 if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) { 09250 if (res < sizeof(*vh)) { 09251 ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a video frame but is too short\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 09252 return 1; 09253 } 09254 09255 /* This is a video frame, get call number */ 09256 fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd, 0); 09257 minivid = 1; 09258 } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) 09259 return socket_process_meta(res, meta, &sin, fd, fr); 09260 09261 #ifdef DEBUG_SUPPORT 09262 if (res >= sizeof(*fh)) 09263 iax_outputframe(NULL, fh, 1, &sin, res - sizeof(*fh)); 09264 #endif 09265 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 09266 if (res < sizeof(*fh)) { 09267 ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a full frame but is too short\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 09268 return 1; 09269 } 09270 09271 /* Get the destination call number */ 09272 dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS; 09273 /* Retrieve the type and subclass */ 09274 f.frametype = fh->type; 09275 if (f.frametype == AST_FRAME_VIDEO) { 09276 f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 09277 } else { 09278 f.subclass = uncompress_subclass(fh->csub); 09279 } 09280 09281 /* Deal with POKE/PONG without allocating a callno */ 09282 if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_POKE) { 09283 /* Reply back with a PONG, but don't care about the result. */ 09284 send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_PONG, ntohl(fh->ts), fh->iseqno + 1, fd, NULL); 09285 return 1; 09286 } else if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK && dcallno == 1) { 09287 /* Ignore */ 09288 return 1; 09289 } 09290 09291 f.datalen = res - sizeof(*fh); 09292 if (f.datalen) { 09293 if (f.frametype == AST_FRAME_IAX) { 09294 if (iax_parse_ies(&ies, thread->buf + sizeof(struct ast_iax2_full_hdr), f.datalen)) { 09295 ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr)); 09296 return 1; 09297 } 09298 f.data.ptr = NULL; 09299 f.datalen = 0; 09300 } else { 09301 f.data.ptr = thread->buf + sizeof(struct ast_iax2_full_hdr); 09302 memset(&ies, 0, sizeof(ies)); 09303 } 09304 } else { 09305 if (f.frametype == AST_FRAME_IAX) 09306 f.data.ptr = NULL; 09307 else 09308 f.data.ptr = empty; 09309 memset(&ies, 0, sizeof(ies)); 09310 } 09311 09312 if (!dcallno && iax2_allow_new(f.frametype, f.subclass, 1)) { 09313 /* only set NEW_ALLOW if calltoken checks out */ 09314 if (handle_call_token(fh, &ies, &sin, fd)) { 09315 return 1; 09316 } 09317 09318 if (ies.calltoken && ies.calltokendata) { 09319 /* if we've gotten this far, and the calltoken ie data exists, 09320 * then calltoken validation _MUST_ have taken place. If calltoken 09321 * data is provided, it is always validated reguardless of any 09322 * calltokenoptional or requirecalltoken options */ 09323 new = NEW_ALLOW_CALLTOKEN_VALIDATED; 09324 } else { 09325 new = NEW_ALLOW; 09326 } 09327 } 09328 } else { 09329 /* Don't know anything about it yet */ 09330 f.frametype = AST_FRAME_NULL; 09331 f.subclass = 0; 09332 } 09333 09334 if (!fr->callno) { 09335 int check_dcallno = 0; 09336 09337 /* 09338 * We enforce accurate destination call numbers for all full frames except 09339 * LAGRQ and PING commands. This is because older versions of Asterisk 09340 * schedule these commands to get sent very quickly, and they will sometimes 09341 * be sent before they receive the first frame from the other side. When 09342 * that happens, it doesn't contain the destination call number. However, 09343 * not checking it for these frames is safe. 09344 * 09345 * Discussed in the following thread: 09346 * http://lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html 09347 */ 09348 09349 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 09350 check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1; 09351 } 09352 09353 if (!(fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno))) { 09354 if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_NEW) { 09355 send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_REJECT, ntohl(fh->ts), fh->iseqno + 1, fd, NULL); 09356 } else if (f.frametype == AST_FRAME_IAX && (f.subclass == IAX_COMMAND_REGREQ || f.subclass == IAX_COMMAND_REGREL)) { 09357 send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_REGREJ, ntohl(fh->ts), fh->iseqno + 1, fd, NULL); 09358 } 09359 return 1; 09360 } 09361 } 09362 09363 if (fr->callno > 0) 09364 ast_mutex_lock(&iaxsl[fr->callno]); 09365 09366 if (!fr->callno || !iaxs[fr->callno]) { 09367 /* A call arrived for a nonexistent destination. Unless it's an "inval" 09368 frame, reply with an inval */ 09369 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 09370 /* We can only raw hangup control frames */ 09371 if (((f.subclass != IAX_COMMAND_INVAL) && 09372 (f.subclass != IAX_COMMAND_TXCNT) && 09373 (f.subclass != IAX_COMMAND_TXACC) && 09374 (f.subclass != IAX_COMMAND_FWDOWNL))|| 09375 (f.frametype != AST_FRAME_IAX)) 09376 raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL, 09377 fd); 09378 } 09379 if (fr->callno > 0) 09380 ast_mutex_unlock(&iaxsl[fr->callno]); 09381 return 1; 09382 } 09383 if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) { 09384 if (decrypt_frame(fr->callno, fh, &f, &res)) { 09385 ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n"); 09386 ast_mutex_unlock(&iaxsl[fr->callno]); 09387 return 1; 09388 } 09389 #ifdef DEBUG_SUPPORT 09390 else 09391 iax_outputframe(NULL, fh, 3, &sin, res - sizeof(*fh)); 09392 #endif 09393 } 09394 09395 /* count this frame */ 09396 iaxs[fr->callno]->frames_received++; 09397 09398 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid && 09399 f.subclass != IAX_COMMAND_TXCNT && /* for attended transfer */ 09400 f.subclass != IAX_COMMAND_TXACC) { /* for attended transfer */ 09401 unsigned short new_peercallno; 09402 09403 new_peercallno = (unsigned short) (ntohs(mh->callno) & ~IAX_FLAG_FULL); 09404 if (new_peercallno && new_peercallno != iaxs[fr->callno]->peercallno) { 09405 if (iaxs[fr->callno]->peercallno) { 09406 remove_by_peercallno(iaxs[fr->callno]); 09407 } 09408 iaxs[fr->callno]->peercallno = new_peercallno; 09409 store_by_peercallno(iaxs[fr->callno]); 09410 } 09411 } 09412 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 09413 if (iaxdebug) 09414 ast_debug(1, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass); 09415 /* Check if it's out of order (and not an ACK or INVAL) */ 09416 fr->oseqno = fh->oseqno; 09417 fr->iseqno = fh->iseqno; 09418 fr->ts = ntohl(fh->ts); 09419 #ifdef IAXTESTS 09420 if (test_resync) { 09421 ast_debug(1, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync); 09422 fr->ts += test_resync; 09423 } 09424 #endif /* IAXTESTS */ 09425 #if 0 09426 if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || 09427 ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX && 09428 (f.subclass == IAX_COMMAND_NEW || 09429 f.subclass == IAX_COMMAND_AUTHREQ || 09430 f.subclass == IAX_COMMAND_ACCEPT || 09431 f.subclass == IAX_COMMAND_REJECT)) ) ) 09432 #endif 09433 if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE)) 09434 updatehistory = 0; 09435 if ((iaxs[fr->callno]->iseqno != fr->oseqno) && 09436 (iaxs[fr->callno]->iseqno || 09437 ((f.subclass != IAX_COMMAND_TXCNT) && 09438 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 09439 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 09440 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 09441 (f.subclass != IAX_COMMAND_TXACC)) || 09442 (f.frametype != AST_FRAME_IAX))) { 09443 if ( 09444 ((f.subclass != IAX_COMMAND_ACK) && 09445 (f.subclass != IAX_COMMAND_INVAL) && 09446 (f.subclass != IAX_COMMAND_TXCNT) && 09447 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 09448 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 09449 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 09450 (f.subclass != IAX_COMMAND_TXACC) && 09451 (f.subclass != IAX_COMMAND_VNAK)) || 09452 (f.frametype != AST_FRAME_IAX)) { 09453 /* If it's not an ACK packet, it's out of order. */ 09454 ast_debug(1, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 09455 iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass); 09456 /* Check to see if we need to request retransmission, 09457 * and take sequence number wraparound into account */ 09458 if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) { 09459 /* If we've already seen it, ack it XXX There's a border condition here XXX */ 09460 if ((f.frametype != AST_FRAME_IAX) || 09461 ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) { 09462 ast_debug(1, "Acking anyway\n"); 09463 /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if 09464 we have anything to send, we'll retransmit and get an ACK back anyway XXX */ 09465 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09466 } 09467 } else { 09468 /* Send a VNAK requesting retransmission */ 09469 iax2_vnak(fr->callno); 09470 } 09471 ast_mutex_unlock(&iaxsl[fr->callno]); 09472 return 1; 09473 } 09474 } else { 09475 /* Increment unless it's an ACK or VNAK */ 09476 if (((f.subclass != IAX_COMMAND_ACK) && 09477 (f.subclass != IAX_COMMAND_INVAL) && 09478 (f.subclass != IAX_COMMAND_TXCNT) && 09479 (f.subclass != IAX_COMMAND_TXACC) && 09480 (f.subclass != IAX_COMMAND_VNAK)) || 09481 (f.frametype != AST_FRAME_IAX)) 09482 iaxs[fr->callno]->iseqno++; 09483 } 09484 /* Ensure text frames are NULL-terminated */ 09485 if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') { 09486 if (res < thread->buf_size) 09487 thread->buf[res++] = '\0'; 09488 else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */ 09489 thread->buf[res - 1] = '\0'; 09490 } 09491 09492 /* Handle implicit ACKing unless this is an INVAL, and only if this is 09493 from the real peer, not the transfer peer */ 09494 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 09495 ((f.subclass != IAX_COMMAND_INVAL) || 09496 (f.frametype != AST_FRAME_IAX))) { 09497 unsigned char x; 09498 int call_to_destroy; 09499 /* First we have to qualify that the ACKed value is within our window */ 09500 if (iaxs[fr->callno]->rseqno >= iaxs[fr->callno]->oseqno || (fr->iseqno >= iaxs[fr->callno]->rseqno && fr->iseqno < iaxs[fr->callno]->oseqno)) 09501 x = fr->iseqno; 09502 else 09503 x = iaxs[fr->callno]->oseqno; 09504 if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) { 09505 /* The acknowledgement is within our window. Time to acknowledge everything 09506 that it says to */ 09507 for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) { 09508 /* Ack the packet with the given timestamp */ 09509 if (iaxdebug) 09510 ast_debug(1, "Cancelling transmission of packet %d\n", x); 09511 call_to_destroy = 0; 09512 AST_LIST_LOCK(&frame_queue); 09513 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 09514 /* If it's our call, and our timestamp, mark -1 retries */ 09515 if ((fr->callno == cur->callno) && (x == cur->oseqno)) { 09516 cur->retries = -1; 09517 /* Destroy call if this is the end */ 09518 if (cur->final) 09519 call_to_destroy = fr->callno; 09520 } 09521 } 09522 AST_LIST_UNLOCK(&frame_queue); 09523 if (call_to_destroy) { 09524 if (iaxdebug) 09525 ast_debug(1, "Really destroying %d, having been acked on final message\n", call_to_destroy); 09526 ast_mutex_lock(&iaxsl[call_to_destroy]); 09527 iax2_destroy(call_to_destroy); 09528 ast_mutex_unlock(&iaxsl[call_to_destroy]); 09529 } 09530 } 09531 /* Note how much we've received acknowledgement for */ 09532 if (iaxs[fr->callno]) 09533 iaxs[fr->callno]->rseqno = fr->iseqno; 09534 else { 09535 /* Stop processing now */ 09536 ast_mutex_unlock(&iaxsl[fr->callno]); 09537 return 1; 09538 } 09539 } else { 09540 ast_debug(1, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno); 09541 } 09542 } 09543 if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 09544 ((f.frametype != AST_FRAME_IAX) || 09545 ((f.subclass != IAX_COMMAND_TXACC) && 09546 (f.subclass != IAX_COMMAND_TXCNT)))) { 09547 /* Only messages we accept from a transfer host are TXACC and TXCNT */ 09548 ast_mutex_unlock(&iaxsl[fr->callno]); 09549 return 1; 09550 } 09551 09552 /* when we receive the first full frame for a new incoming channel, 09553 it is safe to start the PBX on the channel because we have now 09554 completed a 3-way handshake with the peer */ 09555 if ((f.frametype == AST_FRAME_VOICE) || 09556 (f.frametype == AST_FRAME_VIDEO) || 09557 (f.frametype == AST_FRAME_IAX)) { 09558 if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) { 09559 ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 09560 if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) { 09561 ast_mutex_unlock(&iaxsl[fr->callno]); 09562 return 1; 09563 } 09564 } 09565 09566 if (ies.vars) { 09567 struct ast_datastore *variablestore = NULL; 09568 struct ast_variable *var, *prev = NULL; 09569 AST_LIST_HEAD(, ast_var_t) *varlist; 09570 if ((c = iaxs[fr->callno]->owner)) { 09571 varlist = ast_calloc(1, sizeof(*varlist)); 09572 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 09573 09574 if (variablestore && varlist) { 09575 variablestore->data = varlist; 09576 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 09577 AST_LIST_HEAD_INIT(varlist); 09578 ast_debug(1, "I can haz IAX vars?\n"); 09579 for (var = ies.vars; var; var = var->next) { 09580 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 09581 if (prev) { 09582 ast_free(prev); 09583 } 09584 prev = var; 09585 if (!newvar) { 09586 /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */ 09587 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 09588 } else { 09589 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 09590 } 09591 } 09592 if (prev) { 09593 ast_free(prev); 09594 } 09595 ies.vars = NULL; 09596 ast_channel_datastore_add(c, variablestore); 09597 } else { 09598 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 09599 if (variablestore) { 09600 ast_datastore_free(variablestore); 09601 } 09602 if (varlist) { 09603 ast_free(varlist); 09604 } 09605 } 09606 } else { 09607 /* No channel yet, so transfer the variables directly over to the pvt, 09608 * for later inheritance. */ 09609 ast_debug(1, "No channel, so populating IAXVARs to the pvt, as an intermediate step.\n"); 09610 for (var = ies.vars; var && var->next; var = var->next); 09611 if (var) { 09612 var->next = iaxs[fr->callno]->iaxvars; 09613 iaxs[fr->callno]->iaxvars = ies.vars; 09614 ies.vars = NULL; 09615 } 09616 } 09617 } 09618 09619 if (ies.vars) { 09620 ast_debug(1, "I have IAX variables, but they were not processed\n"); 09621 } 09622 } 09623 09624 if (f.frametype == AST_FRAME_VOICE) { 09625 if (f.subclass != iaxs[fr->callno]->voiceformat) { 09626 iaxs[fr->callno]->voiceformat = f.subclass; 09627 ast_debug(1, "Ooh, voice format changed to %d\n", f.subclass); 09628 if (iaxs[fr->callno]->owner) { 09629 int orignative; 09630 retryowner: 09631 if (ast_channel_trylock(iaxs[fr->callno]->owner)) { 09632 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 09633 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner; 09634 } 09635 if (iaxs[fr->callno]) { 09636 if (iaxs[fr->callno]->owner) { 09637 orignative = iaxs[fr->callno]->owner->nativeformats; 09638 iaxs[fr->callno]->owner->nativeformats = f.subclass; 09639 if (iaxs[fr->callno]->owner->readformat) 09640 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 09641 iaxs[fr->callno]->owner->nativeformats = orignative; 09642 ast_channel_unlock(iaxs[fr->callno]->owner); 09643 } 09644 } else { 09645 ast_debug(1, "Neat, somebody took away the channel at a magical time but i found it!\n"); 09646 /* Free remote variables (if any) */ 09647 if (ies.vars) { 09648 ast_variables_destroy(ies.vars); 09649 ast_debug(1, "I can haz iaxvars, but they is no good. :-(\n"); 09650 ies.vars = NULL; 09651 } 09652 ast_mutex_unlock(&iaxsl[fr->callno]); 09653 return 1; 09654 } 09655 } 09656 } 09657 } 09658 if (f.frametype == AST_FRAME_VIDEO) { 09659 if (f.subclass != iaxs[fr->callno]->videoformat) { 09660 ast_debug(1, "Ooh, video format changed to %d\n", f.subclass & ~0x1); 09661 iaxs[fr->callno]->videoformat = f.subclass & ~0x1; 09662 } 09663 } 09664 if (f.frametype == AST_FRAME_CONTROL && iaxs[fr->callno]->owner) { 09665 if (f.subclass == AST_CONTROL_BUSY) { 09666 iaxs[fr->callno]->owner->hangupcause = AST_CAUSE_BUSY; 09667 } else if (f.subclass == AST_CONTROL_CONGESTION) { 09668 iaxs[fr->callno]->owner->hangupcause = AST_CAUSE_CONGESTION; 09669 } 09670 } 09671 if (f.frametype == AST_FRAME_IAX) { 09672 AST_SCHED_DEL(sched, iaxs[fr->callno]->initid); 09673 /* Handle the IAX pseudo frame itself */ 09674 if (iaxdebug) 09675 ast_debug(1, "IAX subclass %d received\n", f.subclass); 09676 09677 /* Update last ts unless the frame's timestamp originated with us. */ 09678 if (iaxs[fr->callno]->last < fr->ts && 09679 f.subclass != IAX_COMMAND_ACK && 09680 f.subclass != IAX_COMMAND_PONG && 09681 f.subclass != IAX_COMMAND_LAGRP) { 09682 iaxs[fr->callno]->last = fr->ts; 09683 if (iaxdebug) 09684 ast_debug(1, "For call=%d, set last=%d\n", fr->callno, fr->ts); 09685 } 09686 iaxs[fr->callno]->last_iax_message = f.subclass; 09687 if (!iaxs[fr->callno]->first_iax_message) { 09688 iaxs[fr->callno]->first_iax_message = f.subclass; 09689 } 09690 switch(f.subclass) { 09691 case IAX_COMMAND_ACK: 09692 /* Do nothing */ 09693 break; 09694 case IAX_COMMAND_QUELCH: 09695 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 09696 /* Generate Manager Hold event, if necessary*/ 09697 if (iaxs[fr->callno]->owner) { 09698 manager_event(EVENT_FLAG_CALL, "Hold", 09699 "Status: On\r\n" 09700 "Channel: %s\r\n" 09701 "Uniqueid: %s\r\n", 09702 iaxs[fr->callno]->owner->name, 09703 iaxs[fr->callno]->owner->uniqueid); 09704 } 09705 09706 ast_set_flag(iaxs[fr->callno], IAX_QUELCH); 09707 if (ies.musiconhold) { 09708 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 09709 const char *moh_suggest = iaxs[fr->callno]->mohsuggest; 09710 iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, 09711 S_OR(moh_suggest, NULL), 09712 !ast_strlen_zero(moh_suggest) ? strlen(moh_suggest) + 1 : 0); 09713 if (!iaxs[fr->callno]) { 09714 ast_mutex_unlock(&iaxsl[fr->callno]); 09715 return 1; 09716 } 09717 } 09718 } 09719 } 09720 break; 09721 case IAX_COMMAND_UNQUELCH: 09722 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 09723 /* Generate Manager Unhold event, if necessary*/ 09724 if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) { 09725 manager_event(EVENT_FLAG_CALL, "Hold", 09726 "Status: Off\r\n" 09727 "Channel: %s\r\n" 09728 "Uniqueid: %s\r\n", 09729 iaxs[fr->callno]->owner->name, 09730 iaxs[fr->callno]->owner->uniqueid); 09731 } 09732 09733 ast_clear_flag(iaxs[fr->callno], IAX_QUELCH); 09734 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 09735 iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0); 09736 if (!iaxs[fr->callno]) { 09737 ast_mutex_unlock(&iaxsl[fr->callno]); 09738 return 1; 09739 } 09740 } 09741 } 09742 break; 09743 case IAX_COMMAND_TXACC: 09744 if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) { 09745 /* Ack the packet with the given timestamp */ 09746 AST_LIST_LOCK(&frame_queue); 09747 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 09748 /* Cancel any outstanding txcnt's */ 09749 if ((fr->callno == cur->callno) && (cur->transfer)) 09750 cur->retries = -1; 09751 } 09752 AST_LIST_UNLOCK(&frame_queue); 09753 memset(&ied1, 0, sizeof(ied1)); 09754 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno); 09755 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1); 09756 iaxs[fr->callno]->transferring = TRANSFER_READY; 09757 } 09758 break; 09759 case IAX_COMMAND_NEW: 09760 /* Ignore if it's already up */ 09761 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) 09762 break; 09763 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 09764 ast_mutex_unlock(&iaxsl[fr->callno]); 09765 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 09766 ast_mutex_lock(&iaxsl[fr->callno]); 09767 if (!iaxs[fr->callno]) { 09768 ast_mutex_unlock(&iaxsl[fr->callno]); 09769 return 1; 09770 } 09771 } 09772 /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */ 09773 if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) { 09774 int new_callno; 09775 if ((new_callno = make_trunk(fr->callno, 1)) != -1) 09776 fr->callno = new_callno; 09777 } 09778 /* For security, always ack immediately */ 09779 if (delayreject) 09780 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09781 if (check_access(fr->callno, &sin, &ies)) { 09782 /* They're not allowed on */ 09783 auth_fail(fr->callno, IAX_COMMAND_REJECT); 09784 if (authdebug) 09785 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, who was trying to reach '%s@%s'\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->exten, iaxs[fr->callno]->context); 09786 break; 09787 } 09788 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 09789 const char *context, *exten, *cid_num; 09790 09791 context = ast_strdupa(iaxs[fr->callno]->context); 09792 exten = ast_strdupa(iaxs[fr->callno]->exten); 09793 cid_num = ast_strdupa(iaxs[fr->callno]->cid_num); 09794 09795 /* This might re-enter the IAX code and need the lock */ 09796 ast_mutex_unlock(&iaxsl[fr->callno]); 09797 exists = ast_exists_extension(NULL, context, exten, 1, cid_num); 09798 ast_mutex_lock(&iaxsl[fr->callno]); 09799 09800 if (!iaxs[fr->callno]) { 09801 ast_mutex_unlock(&iaxsl[fr->callno]); 09802 return 1; 09803 } 09804 } else 09805 exists = 0; 09806 /* Get OSP token if it does exist */ 09807 save_osptoken(fr, &ies); 09808 if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) { 09809 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 09810 memset(&ied0, 0, sizeof(ied0)); 09811 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 09812 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 09813 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09814 if (!iaxs[fr->callno]) { 09815 ast_mutex_unlock(&iaxsl[fr->callno]); 09816 return 1; 09817 } 09818 if (authdebug) 09819 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->exten, iaxs[fr->callno]->context); 09820 } else { 09821 /* Select an appropriate format */ 09822 09823 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 09824 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 09825 using_prefs = "reqonly"; 09826 } else { 09827 using_prefs = "disabled"; 09828 } 09829 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 09830 memset(&pref, 0, sizeof(pref)); 09831 strcpy(caller_pref_buf, "disabled"); 09832 strcpy(host_pref_buf, "disabled"); 09833 } else { 09834 using_prefs = "mine"; 09835 /* If the information elements are in here... use them */ 09836 if (ies.codec_prefs) 09837 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 09838 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 09839 /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/ 09840 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 09841 pref = iaxs[fr->callno]->rprefs; 09842 using_prefs = "caller"; 09843 } else { 09844 pref = iaxs[fr->callno]->prefs; 09845 } 09846 } else 09847 pref = iaxs[fr->callno]->prefs; 09848 09849 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 09850 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 09851 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 09852 } 09853 if (!format) { 09854 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 09855 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 09856 if (!format) { 09857 memset(&ied0, 0, sizeof(ied0)); 09858 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 09859 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 09860 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09861 if (!iaxs[fr->callno]) { 09862 ast_mutex_unlock(&iaxsl[fr->callno]); 09863 return 1; 09864 } 09865 if (authdebug) { 09866 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 09867 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->capability); 09868 else 09869 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability); 09870 } 09871 } else { 09872 /* Pick one... */ 09873 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 09874 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 09875 format = 0; 09876 } else { 09877 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 09878 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 09879 memset(&pref, 0, sizeof(pref)); 09880 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 09881 strcpy(caller_pref_buf,"disabled"); 09882 strcpy(host_pref_buf,"disabled"); 09883 } else { 09884 using_prefs = "mine"; 09885 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 09886 /* Do the opposite of what we tried above. */ 09887 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 09888 pref = iaxs[fr->callno]->prefs; 09889 } else { 09890 pref = iaxs[fr->callno]->rprefs; 09891 using_prefs = "caller"; 09892 } 09893 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 09894 09895 } else /* if no codec_prefs IE do it the old way */ 09896 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 09897 } 09898 } 09899 09900 if (!format) { 09901 memset(&ied0, 0, sizeof(ied0)); 09902 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 09903 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 09904 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 09905 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09906 if (!iaxs[fr->callno]) { 09907 ast_mutex_unlock(&iaxsl[fr->callno]); 09908 return 1; 09909 } 09910 if (authdebug) 09911 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability); 09912 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 09913 break; 09914 } 09915 } 09916 } 09917 if (format) { 09918 /* No authentication required, let them in */ 09919 memset(&ied1, 0, sizeof(ied1)); 09920 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 09921 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 09922 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 09923 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09924 ast_verb(3, "Accepting UNAUTHENTICATED call from %s:\n" 09925 "%srequested format = %s,\n" 09926 "%srequested prefs = %s,\n" 09927 "%sactual format = %s,\n" 09928 "%shost prefs = %s,\n" 09929 "%spriority = %s\n", 09930 ast_inet_ntoa(sin.sin_addr), 09931 VERBOSE_PREFIX_4, 09932 ast_getformatname(iaxs[fr->callno]->peerformat), 09933 VERBOSE_PREFIX_4, 09934 caller_pref_buf, 09935 VERBOSE_PREFIX_4, 09936 ast_getformatname(format), 09937 VERBOSE_PREFIX_4, 09938 host_pref_buf, 09939 VERBOSE_PREFIX_4, 09940 using_prefs); 09941 09942 iaxs[fr->callno]->chosenformat = format; 09943 ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 09944 } else { 09945 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 09946 /* If this is a TBD call, we're ready but now what... */ 09947 ast_verb(3, "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 09948 } 09949 } 09950 } 09951 break; 09952 } 09953 if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5) 09954 merge_encryption(iaxs[fr->callno],ies.encmethods); 09955 else 09956 iaxs[fr->callno]->encmethods = 0; 09957 if (!authenticate_request(fr->callno) && iaxs[fr->callno]) 09958 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED); 09959 if (!iaxs[fr->callno]) { 09960 ast_mutex_unlock(&iaxsl[fr->callno]); 09961 return 1; 09962 } 09963 break; 09964 case IAX_COMMAND_DPREQ: 09965 /* Request status in the dialplan */ 09966 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) && 09967 !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) { 09968 if (iaxcompat) { 09969 /* Spawn a thread for the lookup */ 09970 spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num); 09971 } else { 09972 /* Just look it up */ 09973 dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1); 09974 } 09975 } 09976 break; 09977 case IAX_COMMAND_HANGUP: 09978 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 09979 ast_debug(1, "Immediately destroying %d, having received hangup\n", fr->callno); 09980 /* Set hangup cause according to remote */ 09981 if (ies.causecode && iaxs[fr->callno]->owner) 09982 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 09983 /* Send ack immediately, before we destroy */ 09984 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09985 iax2_destroy(fr->callno); 09986 break; 09987 case IAX_COMMAND_REJECT: 09988 /* Set hangup cause according to remote */ 09989 if (ies.causecode && iaxs[fr->callno]->owner) 09990 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 09991 09992 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 09993 if (iaxs[fr->callno]->owner && authdebug) 09994 ast_log(LOG_WARNING, "Call rejected by %s: %s\n", 09995 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), 09996 ies.cause ? ies.cause : "<Unknown>"); 09997 ast_debug(1, "Immediately destroying %d, having received reject\n", 09998 fr->callno); 09999 } 10000 /* Send ack immediately, before we destroy */ 10001 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, 10002 fr->ts, NULL, 0, fr->iseqno); 10003 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) 10004 iaxs[fr->callno]->error = EPERM; 10005 iax2_destroy(fr->callno); 10006 break; 10007 case IAX_COMMAND_TRANSFER: 10008 { 10009 struct ast_channel *bridged_chan; 10010 10011 if (iaxs[fr->callno]->owner && (bridged_chan = ast_bridged_channel(iaxs[fr->callno]->owner)) && ies.called_number) { 10012 /* Set BLINDTRANSFER channel variables */ 10013 10014 ast_mutex_unlock(&iaxsl[fr->callno]); 10015 pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", bridged_chan->name); 10016 ast_mutex_lock(&iaxsl[fr->callno]); 10017 if (!iaxs[fr->callno]) { 10018 ast_mutex_unlock(&iaxsl[fr->callno]); 10019 return 1; 10020 } 10021 10022 pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", iaxs[fr->callno]->owner->name); 10023 if (!strcmp(ies.called_number, ast_parking_ext())) { 10024 struct ast_channel *saved_channel = iaxs[fr->callno]->owner; 10025 ast_mutex_unlock(&iaxsl[fr->callno]); 10026 if (iax_park(bridged_chan, saved_channel)) { 10027 ast_log(LOG_WARNING, "Failed to park call on '%s'\n", bridged_chan->name); 10028 } else { 10029 ast_debug(1, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name); 10030 } 10031 ast_mutex_lock(&iaxsl[fr->callno]); 10032 } else { 10033 if (ast_async_goto(bridged_chan, iaxs[fr->callno]->context, ies.called_number, 1)) 10034 ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", bridged_chan->name, 10035 ies.called_number, iaxs[fr->callno]->context); 10036 else { 10037 ast_debug(1, "Async goto of '%s' to '%s@%s' started\n", bridged_chan->name, 10038 ies.called_number, iaxs[fr->callno]->context); 10039 } 10040 } 10041 } else { 10042 ast_debug(1, "Async goto not applicable on call %d\n", fr->callno); 10043 } 10044 10045 break; 10046 } 10047 case IAX_COMMAND_ACCEPT: 10048 /* Ignore if call is already up or needs authentication or is a TBD */ 10049 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED)) 10050 break; 10051 if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 10052 /* Send ack immediately, before we destroy */ 10053 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 10054 iax2_destroy(fr->callno); 10055 break; 10056 } 10057 if (ies.format) { 10058 iaxs[fr->callno]->peerformat = ies.format; 10059 } else { 10060 if (iaxs[fr->callno]->owner) 10061 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats; 10062 else 10063 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability; 10064 } 10065 ast_verb(3, "Call accepted by %s (format %s)\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), ast_getformatname(iaxs[fr->callno]->peerformat)); 10066 if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) { 10067 memset(&ied0, 0, sizeof(ied0)); 10068 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 10069 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 10070 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 10071 if (!iaxs[fr->callno]) { 10072 ast_mutex_unlock(&iaxsl[fr->callno]); 10073 return 1; 10074 } 10075 if (authdebug) 10076 ast_log(LOG_NOTICE, "Rejected call to %s, format 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->capability); 10077 } else { 10078 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 10079 if (iaxs[fr->callno]->owner) { 10080 /* Switch us to use a compatible format */ 10081 iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat; 10082 ast_verb(3, "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats)); 10083 retryowner2: 10084 if (ast_channel_trylock(iaxs[fr->callno]->owner)) { 10085 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 10086 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2; 10087 } 10088 10089 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) { 10090 /* Setup read/write formats properly. */ 10091 if (iaxs[fr->callno]->owner->writeformat) 10092 ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat); 10093 if (iaxs[fr->callno]->owner->readformat) 10094 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 10095 ast_channel_unlock(iaxs[fr->callno]->owner); 10096 } 10097 } 10098 } 10099 if (iaxs[fr->callno]) { 10100 AST_LIST_LOCK(&dpcache); 10101 AST_LIST_TRAVERSE(&iaxs[fr->callno]->dpentries, dp, peer_list) 10102 if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) 10103 iax2_dprequest(dp, fr->callno); 10104 AST_LIST_UNLOCK(&dpcache); 10105 } 10106 break; 10107 case IAX_COMMAND_POKE: 10108 /* Send back a pong packet with the original timestamp */ 10109 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1); 10110 if (!iaxs[fr->callno]) { 10111 ast_mutex_unlock(&iaxsl[fr->callno]); 10112 return 1; 10113 } 10114 break; 10115 case IAX_COMMAND_PING: 10116 { 10117 struct iax_ie_data pingied; 10118 construct_rr(iaxs[fr->callno], &pingied); 10119 /* Send back a pong packet with the original timestamp */ 10120 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1); 10121 } 10122 break; 10123 case IAX_COMMAND_PONG: 10124 /* Calculate ping time */ 10125 iaxs[fr->callno]->pingtime = calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts; 10126 /* save RR info */ 10127 save_rr(fr, &ies); 10128 10129 /* Good time to write jb stats for this call */ 10130 log_jitterstats(fr->callno); 10131 10132 if (iaxs[fr->callno]->peerpoke) { 10133 peer = iaxs[fr->callno]->peerpoke; 10134 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) { 10135 if (iaxs[fr->callno]->pingtime <= peer->maxms) { 10136 ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime); 10137 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 10138 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "IAX2/%s", peer->name); /* Activate notification */ 10139 } 10140 } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) { 10141 if (iaxs[fr->callno]->pingtime > peer->maxms) { 10142 ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime); 10143 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 10144 ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", peer->name); /* Activate notification */ 10145 } 10146 } 10147 peer->lastms = iaxs[fr->callno]->pingtime; 10148 if (peer->smoothing && (peer->lastms > -1)) 10149 peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2; 10150 else if (peer->smoothing && peer->lastms < 0) 10151 peer->historicms = (0 + peer->historicms) / 2; 10152 else 10153 peer->historicms = iaxs[fr->callno]->pingtime; 10154 10155 /* Remove scheduled iax2_poke_noanswer */ 10156 if (peer->pokeexpire > -1) { 10157 if (!ast_sched_del(sched, peer->pokeexpire)) { 10158 peer_unref(peer); 10159 peer->pokeexpire = -1; 10160 } 10161 } 10162 /* Schedule the next cycle */ 10163 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) 10164 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 10165 else 10166 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer_ref(peer)); 10167 if (peer->pokeexpire == -1) 10168 peer_unref(peer); 10169 /* and finally send the ack */ 10170 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 10171 /* And wrap up the qualify call */ 10172 iax2_destroy(fr->callno); 10173 peer->callno = 0; 10174 ast_debug(1, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms); 10175 } 10176 break; 10177 case IAX_COMMAND_LAGRQ: 10178 case IAX_COMMAND_LAGRP: 10179 f.src = "LAGRQ"; 10180 f.mallocd = 0; 10181 f.offset = 0; 10182 f.samples = 0; 10183 iax_frame_wrap(fr, &f); 10184 if(f.subclass == IAX_COMMAND_LAGRQ) { 10185 /* Received a LAGRQ - echo back a LAGRP */ 10186 fr->af.subclass = IAX_COMMAND_LAGRP; 10187 iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0); 10188 } else { 10189 /* Received LAGRP in response to our LAGRQ */ 10190 unsigned int ts; 10191 /* This is a reply we've been given, actually measure the difference */ 10192 ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af); 10193 iaxs[fr->callno]->lag = ts - fr->ts; 10194 if (iaxdebug) 10195 ast_debug(1, "Peer %s lag measured as %dms\n", 10196 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag); 10197 } 10198 break; 10199 case IAX_COMMAND_AUTHREQ: 10200 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 10201 ast_log(LOG_WARNING, "Call on %s is already up, can't start on it\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 10202 break; 10203 } 10204 if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) { 10205 struct ast_frame hangup_fr = { .frametype = AST_FRAME_CONTROL, 10206 .subclass = AST_CONTROL_HANGUP, 10207 }; 10208 ast_log(LOG_WARNING, 10209 "I don't know how to authenticate %s to %s\n", 10210 ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr)); 10211 iax2_queue_frame(fr->callno, &hangup_fr); 10212 } 10213 if (!iaxs[fr->callno]) { 10214 ast_mutex_unlock(&iaxsl[fr->callno]); 10215 return 1; 10216 } 10217 break; 10218 case IAX_COMMAND_AUTHREP: 10219 /* For security, always ack immediately */ 10220 if (delayreject) 10221 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 10222 /* Ignore once we've started */ 10223 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 10224 ast_log(LOG_WARNING, "Call on %s is already up, can't start on it\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 10225 break; 10226 } 10227 if (authenticate_verify(iaxs[fr->callno], &ies)) { 10228 if (authdebug) 10229 ast_log(LOG_NOTICE, "Host %s failed to authenticate as %s\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->username); 10230 memset(&ied0, 0, sizeof(ied0)); 10231 auth_fail(fr->callno, IAX_COMMAND_REJECT); 10232 break; 10233 } 10234 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 10235 /* This might re-enter the IAX code and need the lock */ 10236 exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num); 10237 } else 10238 exists = 0; 10239 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 10240 if (authdebug) 10241 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->exten, iaxs[fr->callno]->context); 10242 memset(&ied0, 0, sizeof(ied0)); 10243 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 10244 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 10245 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 10246 if (!iaxs[fr->callno]) { 10247 ast_mutex_unlock(&iaxsl[fr->callno]); 10248 return 1; 10249 } 10250 } else { 10251 /* Select an appropriate format */ 10252 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 10253 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 10254 using_prefs = "reqonly"; 10255 } else { 10256 using_prefs = "disabled"; 10257 } 10258 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 10259 memset(&pref, 0, sizeof(pref)); 10260 strcpy(caller_pref_buf, "disabled"); 10261 strcpy(host_pref_buf, "disabled"); 10262 } else { 10263 using_prefs = "mine"; 10264 if (ies.codec_prefs) 10265 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 10266 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 10267 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 10268 pref = iaxs[fr->callno]->rprefs; 10269 using_prefs = "caller"; 10270 } else { 10271 pref = iaxs[fr->callno]->prefs; 10272 } 10273 } else /* if no codec_prefs IE do it the old way */ 10274 pref = iaxs[fr->callno]->prefs; 10275 10276 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 10277 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 10278 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 10279 } 10280 if (!format) { 10281 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 10282 ast_debug(1, "We don't do requested format %s, falling back to peer capability %d\n", ast_getformatname(iaxs[fr->callno]->peerformat), iaxs[fr->callno]->peercapability); 10283 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 10284 } 10285 if (!format) { 10286 if (authdebug) { 10287 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 10288 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->capability); 10289 else 10290 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability); 10291 } 10292 memset(&ied0, 0, sizeof(ied0)); 10293 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 10294 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 10295 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 10296 if (!iaxs[fr->callno]) { 10297 ast_mutex_unlock(&iaxsl[fr->callno]); 10298 return 1; 10299 } 10300 } else { 10301 /* Pick one... */ 10302 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 10303 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 10304 format = 0; 10305 } else { 10306 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 10307 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 10308 memset(&pref, 0, sizeof(pref)); 10309 format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? 10310 iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 10311 strcpy(caller_pref_buf,"disabled"); 10312 strcpy(host_pref_buf,"disabled"); 10313 } else { 10314 using_prefs = "mine"; 10315 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 10316 /* Do the opposite of what we tried above. */ 10317 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 10318 pref = iaxs[fr->callno]->prefs; 10319 } else { 10320 pref = iaxs[fr->callno]->rprefs; 10321 using_prefs = "caller"; 10322 } 10323 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 10324 } else /* if no codec_prefs IE do it the old way */ 10325 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 10326 } 10327 } 10328 if (!format) { 10329 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 10330 if (authdebug) { 10331 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 10332 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->capability); 10333 else 10334 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability); 10335 } 10336 memset(&ied0, 0, sizeof(ied0)); 10337 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 10338 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 10339 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 10340 if (!iaxs[fr->callno]) { 10341 ast_mutex_unlock(&iaxsl[fr->callno]); 10342 return 1; 10343 } 10344 } 10345 } 10346 } 10347 if (format) { 10348 /* Authentication received */ 10349 memset(&ied1, 0, sizeof(ied1)); 10350 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 10351 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 10352 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 10353 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 10354 ast_verb(3, "Accepting AUTHENTICATED call from %s:\n" 10355 "%srequested format = %s,\n" 10356 "%srequested prefs = %s,\n" 10357 "%sactual format = %s,\n" 10358 "%shost prefs = %s,\n" 10359 "%spriority = %s\n", 10360 ast_inet_ntoa(sin.sin_addr), 10361 VERBOSE_PREFIX_4, 10362 ast_getformatname(iaxs[fr->callno]->peerformat), 10363 VERBOSE_PREFIX_4, 10364 caller_pref_buf, 10365 VERBOSE_PREFIX_4, 10366 ast_getformatname(format), 10367 VERBOSE_PREFIX_4, 10368 host_pref_buf, 10369 VERBOSE_PREFIX_4, 10370 using_prefs); 10371 10372 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 10373 if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format))) 10374 iax2_destroy(fr->callno); 10375 else if (ies.vars) { 10376 struct ast_datastore *variablestore; 10377 struct ast_variable *var, *prev = NULL; 10378 AST_LIST_HEAD(, ast_var_t) *varlist; 10379 varlist = ast_calloc(1, sizeof(*varlist)); 10380 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 10381 if (variablestore && varlist) { 10382 variablestore->data = varlist; 10383 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 10384 AST_LIST_HEAD_INIT(varlist); 10385 ast_debug(1, "I can haz IAX vars? w00t\n"); 10386 for (var = ies.vars; var; var = var->next) { 10387 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 10388 if (prev) 10389 ast_free(prev); 10390 prev = var; 10391 if (!newvar) { 10392 /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */ 10393 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 10394 } else { 10395 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 10396 } 10397 } 10398 if (prev) 10399 ast_free(prev); 10400 ies.vars = NULL; 10401 ast_channel_datastore_add(c, variablestore); 10402 } else { 10403 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 10404 if (variablestore) 10405 ast_datastore_free(variablestore); 10406 if (varlist) 10407 ast_free(varlist); 10408 } 10409 } 10410 } else { 10411 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 10412 /* If this is a TBD call, we're ready but now what... */ 10413 ast_verb(3, "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 10414 } 10415 } 10416 } 10417 break; 10418 case IAX_COMMAND_DIAL: 10419 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) { 10420 ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 10421 ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s"); 10422 if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) { 10423 if (authdebug) 10424 ast_log(LOG_NOTICE, "Rejected dial attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->exten, iaxs[fr->callno]->context); 10425 memset(&ied0, 0, sizeof(ied0)); 10426 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 10427 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 10428 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 10429 if (!iaxs[fr->callno]) { 10430 ast_mutex_unlock(&iaxsl[fr->callno]); 10431 return 1; 10432 } 10433 } else { 10434 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 10435 ast_verb(3, "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat); 10436 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 10437 send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1); 10438 if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat))) 10439 iax2_destroy(fr->callno); 10440 else if (ies.vars) { 10441 struct ast_datastore *variablestore; 10442 struct ast_variable *var, *prev = NULL; 10443 AST_LIST_HEAD(, ast_var_t) *varlist; 10444 varlist = ast_calloc(1, sizeof(*varlist)); 10445 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 10446 ast_debug(1, "I can haz IAX vars? w00t\n"); 10447 if (variablestore && varlist) { 10448 variablestore->data = varlist; 10449 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 10450 AST_LIST_HEAD_INIT(varlist); 10451 for (var = ies.vars; var; var = var->next) { 10452 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 10453 if (prev) 10454 ast_free(prev); 10455 prev = var; 10456 if (!newvar) { 10457 /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */ 10458 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 10459 } else { 10460 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 10461 } 10462 } 10463 if (prev) 10464 ast_free(prev); 10465 ies.vars = NULL; 10466 ast_channel_datastore_add(c, variablestore); 10467 } else { 10468 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 10469 if (variablestore) 10470 ast_datastore_free(variablestore); 10471 if (varlist) 10472 ast_free(varlist); 10473 } 10474 } 10475 } 10476 } 10477 break; 10478 case IAX_COMMAND_INVAL: 10479 iaxs[fr->callno]->error = ENOTCONN; 10480 ast_debug(1, "Immediately destroying %d, having received INVAL\n", fr->callno); 10481 iax2_destroy(fr->callno); 10482 ast_debug(1, "Destroying call %d\n", fr->callno); 10483 break; 10484 case IAX_COMMAND_VNAK: 10485 ast_debug(1, "Received VNAK: resending outstanding frames\n"); 10486 /* Force retransmission */ 10487 vnak_retransmit(fr->callno, fr->iseqno); 10488 break; 10489 case IAX_COMMAND_REGREQ: 10490 case IAX_COMMAND_REGREL: 10491 /* For security, always ack immediately */ 10492 if (delayreject) 10493 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 10494 if (register_verify(fr->callno, &sin, &ies)) { 10495 if (!iaxs[fr->callno]) { 10496 ast_mutex_unlock(&iaxsl[fr->callno]); 10497 return 1; 10498 } 10499 /* Send delayed failure */ 10500 auth_fail(fr->callno, IAX_COMMAND_REGREJ); 10501 break; 10502 } 10503 if (!iaxs[fr->callno]) { 10504 ast_mutex_unlock(&iaxsl[fr->callno]); 10505 return 1; 10506 } 10507 if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 10508 ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED)) { 10509 10510 if (f.subclass == IAX_COMMAND_REGREL) 10511 memset(&sin, 0, sizeof(sin)); 10512 if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh)) 10513 ast_log(LOG_WARNING, "Registry error\n"); 10514 if (!iaxs[fr->callno]) { 10515 ast_mutex_unlock(&iaxsl[fr->callno]); 10516 return 1; 10517 } 10518 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 10519 ast_mutex_unlock(&iaxsl[fr->callno]); 10520 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 10521 ast_mutex_lock(&iaxsl[fr->callno]); 10522 if (!iaxs[fr->callno]) { 10523 ast_mutex_unlock(&iaxsl[fr->callno]); 10524 return 1; 10525 } 10526 } 10527 break; 10528 } 10529 registry_authrequest(fr->callno); 10530 if (!iaxs[fr->callno]) { 10531 ast_mutex_unlock(&iaxsl[fr->callno]); 10532 return 1; 10533 } 10534 break; 10535 case IAX_COMMAND_REGACK: 10536 if (iax2_ack_registry(&ies, &sin, fr->callno)) 10537 ast_log(LOG_WARNING, "Registration failure\n"); 10538 /* Send ack immediately, before we destroy */ 10539 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 10540 iax2_destroy(fr->callno); 10541 break; 10542 case IAX_COMMAND_REGREJ: 10543 if (iaxs[fr->callno]->reg) { 10544 if (authdebug) { 10545 ast_log(LOG_NOTICE, "Registration of '%s' rejected: '%s' from: '%s'\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : "<unknown>", ast_inet_ntoa(sin.sin_addr)); 10546 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: IAX2\r\nUsername: %s\r\nStatus: Rejected\r\nCause: %s\r\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : "<unknown>"); 10547 } 10548 iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED; 10549 } 10550 /* Send ack immediately, before we destroy */ 10551 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 10552 iax2_destroy(fr->callno); 10553 break; 10554 case IAX_COMMAND_REGAUTH: 10555 /* Authentication request */ 10556 if (registry_rerequest(&ies, fr->callno, &sin)) { 10557 memset(&ied0, 0, sizeof(ied0)); 10558 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found"); 10559 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 10560 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 10561 if (!iaxs[fr->callno]) { 10562 ast_mutex_unlock(&iaxsl[fr->callno]); 10563 return 1; 10564 } 10565 } 10566 break; 10567 case IAX_COMMAND_TXREJ: 10568 iaxs[fr->callno]->transferring = 0; 10569 ast_verb(3, "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 10570 memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer)); 10571 if (iaxs[fr->callno]->bridgecallno) { 10572 if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) { 10573 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0; 10574 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 10575 } 10576 } 10577 break; 10578 case IAX_COMMAND_TXREADY: 10579 if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) || 10580 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) { 10581 if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN) 10582 iaxs[fr->callno]->transferring = TRANSFER_MREADY; 10583 else 10584 iaxs[fr->callno]->transferring = TRANSFER_READY; 10585 ast_verb(3, "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 10586 if (iaxs[fr->callno]->bridgecallno) { 10587 if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) || 10588 (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) { 10589 /* They're both ready, now release them. */ 10590 if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) { 10591 ast_verb(3, "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 10592 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 10593 10594 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA; 10595 iaxs[fr->callno]->transferring = TRANSFER_MEDIA; 10596 10597 memset(&ied0, 0, sizeof(ied0)); 10598 memset(&ied1, 0, sizeof(ied1)); 10599 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 10600 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 10601 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1); 10602 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1); 10603 } else { 10604 ast_verb(3, "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 10605 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 10606 10607 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED; 10608 iaxs[fr->callno]->transferring = TRANSFER_RELEASED; 10609 ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE); 10610 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 10611 10612 /* Stop doing lag & ping requests */ 10613 stop_stuff(fr->callno); 10614 stop_stuff(iaxs[fr->callno]->bridgecallno); 10615 10616 memset(&ied0, 0, sizeof(ied0)); 10617 memset(&ied1, 0, sizeof(ied1)); 10618 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 10619 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 10620 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1); 10621 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1); 10622 } 10623 10624 } 10625 } 10626 } 10627 break; 10628 case IAX_COMMAND_TXREQ: 10629 try_transfer(iaxs[fr->callno], &ies); 10630 break; 10631 case IAX_COMMAND_TXCNT: 10632 if (iaxs[fr->callno]->transferring) 10633 send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0); 10634 break; 10635 case IAX_COMMAND_TXREL: 10636 /* Send ack immediately, rather than waiting until we've changed addresses */ 10637 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 10638 complete_transfer(fr->callno, &ies); 10639 stop_stuff(fr->callno); /* for attended transfer to work with libiax */ 10640 break; 10641 case IAX_COMMAND_TXMEDIA: 10642 if (iaxs[fr->callno]->transferring == TRANSFER_READY) { 10643 AST_LIST_LOCK(&frame_queue); 10644 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 10645 /* Cancel any outstanding frames and start anew */ 10646 if ((fr->callno == cur->callno) && (cur->transfer)) 10647 cur->retries = -1; 10648 } 10649 AST_LIST_UNLOCK(&frame_queue); 10650 /* Start sending our media to the transfer address, but otherwise leave the call as-is */ 10651 iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS; 10652 } 10653 break; 10654 case IAX_COMMAND_RTKEY: 10655 if (!IAX_CALLENCRYPTED(iaxs[fr->callno])) { 10656 ast_log(LOG_WARNING, 10657 "we've been told to rotate our encryption key, " 10658 "but this isn't an encrypted call. bad things will happen.\n" 10659 ); 10660 break; 10661 } 10662 10663 IAX_DEBUGDIGEST("Receiving", ies.challenge); 10664 10665 ast_aes_decrypt_key((unsigned char *) ies.challenge, &iaxs[fr->callno]->dcx); 10666 break; 10667 case IAX_COMMAND_DPREP: 10668 complete_dpreply(iaxs[fr->callno], &ies); 10669 break; 10670 case IAX_COMMAND_UNSUPPORT: 10671 ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown); 10672 break; 10673 case IAX_COMMAND_FWDOWNL: 10674 /* Firmware download */ 10675 if (!ast_test_flag(&globalflags, IAX_ALLOWFWDOWNLOAD)) { 10676 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, NULL, 0, -1); 10677 break; 10678 } 10679 memset(&ied0, 0, sizeof(ied0)); 10680 res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc); 10681 if (res < 0) 10682 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 10683 else if (res > 0) 10684 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 10685 else 10686 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 10687 if (!iaxs[fr->callno]) { 10688 ast_mutex_unlock(&iaxsl[fr->callno]); 10689 return 1; 10690 } 10691 break; 10692 case IAX_COMMAND_CALLTOKEN: 10693 { 10694 struct iax_frame *cur; 10695 int found = 0; 10696 AST_LIST_LOCK(&frame_queue); 10697 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 10698 /* find the last sent frame in our frame queue for this callno. 10699 * There are many things to take into account before resending this frame. 10700 * All of these are taken care of in resend_with_token() */ 10701 if (cur->callno == fr->callno) { 10702 found = 1; 10703 break; 10704 } 10705 } 10706 AST_LIST_UNLOCK(&frame_queue); 10707 10708 /* find last sent frame */ 10709 if (cur && found && ies.calltoken && ies.calltokendata) { 10710 resend_with_token(fr->callno, cur, (char *) ies.calltokendata); 10711 } 10712 break; 10713 } 10714 default: 10715 ast_debug(1, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno); 10716 memset(&ied0, 0, sizeof(ied0)); 10717 iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass); 10718 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1); 10719 } 10720 /* Free remote variables (if any) */ 10721 if (ies.vars) { 10722 ast_variables_destroy(ies.vars); 10723 ast_debug(1, "I can haz IAX vars, but they is no good :-(\n"); 10724 ies.vars = NULL; 10725 } 10726 10727 /* Don't actually pass these frames along */ 10728 if ((f.subclass != IAX_COMMAND_ACK) && 10729 (f.subclass != IAX_COMMAND_TXCNT) && 10730 (f.subclass != IAX_COMMAND_TXACC) && 10731 (f.subclass != IAX_COMMAND_INVAL) && 10732 (f.subclass != IAX_COMMAND_VNAK)) { 10733 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 10734 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 10735 } 10736 ast_mutex_unlock(&iaxsl[fr->callno]); 10737 return 1; 10738 } 10739 /* Unless this is an ACK or INVAL frame, ack it */ 10740 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 10741 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 10742 } else if (minivid) { 10743 f.frametype = AST_FRAME_VIDEO; 10744 if (iaxs[fr->callno]->videoformat > 0) 10745 f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0); 10746 else { 10747 ast_log(LOG_WARNING, "Received mini frame before first full video frame\n"); 10748 iax2_vnak(fr->callno); 10749 ast_mutex_unlock(&iaxsl[fr->callno]); 10750 return 1; 10751 } 10752 f.datalen = res - sizeof(*vh); 10753 if (f.datalen) 10754 f.data.ptr = thread->buf + sizeof(*vh); 10755 else 10756 f.data.ptr = NULL; 10757 #ifdef IAXTESTS 10758 if (test_resync) { 10759 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff); 10760 } else 10761 #endif /* IAXTESTS */ 10762 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff); 10763 } else { 10764 /* A mini frame */ 10765 f.frametype = AST_FRAME_VOICE; 10766 if (iaxs[fr->callno]->voiceformat > 0) 10767 f.subclass = iaxs[fr->callno]->voiceformat; 10768 else { 10769 ast_debug(1, "Received mini frame before first full voice frame\n"); 10770 iax2_vnak(fr->callno); 10771 ast_mutex_unlock(&iaxsl[fr->callno]); 10772 return 1; 10773 } 10774 f.datalen = res - sizeof(struct ast_iax2_mini_hdr); 10775 if (f.datalen < 0) { 10776 ast_log(LOG_WARNING, "Datalen < 0?\n"); 10777 ast_mutex_unlock(&iaxsl[fr->callno]); 10778 return 1; 10779 } 10780 if (f.datalen) 10781 f.data.ptr = thread->buf + sizeof(*mh); 10782 else 10783 f.data.ptr = NULL; 10784 #ifdef IAXTESTS 10785 if (test_resync) { 10786 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff); 10787 } else 10788 #endif /* IAXTESTS */ 10789 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts); 10790 /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */ 10791 } 10792 /* Don't pass any packets until we're started */ 10793 if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 10794 ast_mutex_unlock(&iaxsl[fr->callno]); 10795 return 1; 10796 } 10797 /* Common things */ 10798 f.src = "IAX2"; 10799 f.mallocd = 0; 10800 f.offset = 0; 10801 f.len = 0; 10802 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) { 10803 f.samples = ast_codec_get_samples(&f); 10804 /* We need to byteswap incoming slinear samples from network byte order */ 10805 if (f.subclass == AST_FORMAT_SLINEAR) 10806 ast_frame_byteswap_be(&f); 10807 } else 10808 f.samples = 0; 10809 iax_frame_wrap(fr, &f); 10810 10811 /* If this is our most recent packet, use it as our basis for timestamping */ 10812 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 10813 /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/ 10814 fr->outoforder = 0; 10815 } else { 10816 if (iaxdebug && iaxs[fr->callno]) 10817 ast_debug(1, "Received out of order packet... (type=%d, subclass %d, ts = %d, last = %d)\n", f.frametype, f.subclass, fr->ts, iaxs[fr->callno]->last); 10818 fr->outoforder = -1; 10819 } 10820 fr->cacheable = ((f.frametype == AST_FRAME_VOICE) || (f.frametype == AST_FRAME_VIDEO)); 10821 duped_fr = iaxfrdup2(fr); 10822 if (duped_fr) { 10823 schedule_delivery(duped_fr, updatehistory, 0, &fr->ts); 10824 } 10825 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 10826 iaxs[fr->callno]->last = fr->ts; 10827 #if 1 10828 if (iaxdebug) 10829 ast_debug(1, "For call=%d, set last=%d\n", fr->callno, fr->ts); 10830 #endif 10831 } 10832 10833 /* Always run again */ 10834 ast_mutex_unlock(&iaxsl[fr->callno]); 10835 return 1; 10836 }
| static int socket_process_meta | ( | int | packet_len, | |
| struct ast_iax2_meta_hdr * | meta, | |||
| struct sockaddr_in * | sin, | |||
| int | sockfd, | |||
| struct iax_frame * | fr | |||
| ) | [static] |
Definition at line 9005 of file chan_iax2.c.
References ast_codec_get_samples(), AST_FRAME_VOICE, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_test_flag, ast_tvnow(), ast_tvzero(), iax_frame::callno, ast_iax2_meta_trunk_entry::callno, ast_iax2_mini_hdr::callno, ast_iax2_meta_hdr::cmddata, ast_frame::data, ast_iax2_meta_trunk_hdr::data, ast_iax2_meta_hdr::data, ast_frame::datalen, find_callno_locked(), find_tpeer(), fix_peerts(), ast_frame::frametype, iax2_vnak(), IAX_FLAG_FULL, iax_frame_wrap(), IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_STATE_STARTED, iaxfrdup2(), chan_iax2_pvt::last, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_WARNING, ast_frame::mallocd, ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, NEW_PREVENT, ast_frame::offset, iax_frame::outoforder, ast_frame::ptr, iax2_trunk_peer::rxtrunktime, ast_frame::samples, schedule_delivery(), ast_frame::src, chan_iax2_pvt::state, ast_frame::subclass, iax2_trunk_peer::trunkact, iax_frame::ts, ast_iax2_mini_hdr::ts, ast_iax2_meta_trunk_hdr::ts, and chan_iax2_pvt::voiceformat.
Referenced by socket_process().
09007 { 09008 unsigned char metatype; 09009 struct ast_iax2_meta_trunk_mini *mtm; 09010 struct ast_iax2_meta_trunk_hdr *mth; 09011 struct ast_iax2_meta_trunk_entry *mte; 09012 struct iax2_trunk_peer *tpeer; 09013 unsigned int ts; 09014 void *ptr; 09015 struct timeval rxtrunktime; 09016 struct ast_frame f = { 0, }; 09017 09018 if (packet_len < sizeof(*meta)) { 09019 ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a meta frame but is too short\n", 09020 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 09021 return 1; 09022 } 09023 09024 if (meta->metacmd != IAX_META_TRUNK) 09025 return 1; 09026 09027 if (packet_len < (sizeof(*meta) + sizeof(*mth))) { 09028 ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %d min)\n", packet_len, 09029 (int) (sizeof(*meta) + sizeof(*mth))); 09030 return 1; 09031 } 09032 mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data); 09033 ts = ntohl(mth->ts); 09034 metatype = meta->cmddata; 09035 packet_len -= (sizeof(*meta) + sizeof(*mth)); 09036 ptr = mth->data; 09037 tpeer = find_tpeer(sin, sockfd); 09038 if (!tpeer) { 09039 ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", 09040 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 09041 return 1; 09042 } 09043 tpeer->trunkact = ast_tvnow(); 09044 if (!ts || ast_tvzero(tpeer->rxtrunktime)) 09045 tpeer->rxtrunktime = tpeer->trunkact; 09046 rxtrunktime = tpeer->rxtrunktime; 09047 ast_mutex_unlock(&tpeer->lock); 09048 while (packet_len >= sizeof(*mte)) { 09049 /* Process channels */ 09050 unsigned short callno, trunked_ts, len; 09051 09052 if (metatype == IAX_META_TRUNK_MINI) { 09053 mtm = (struct ast_iax2_meta_trunk_mini *) ptr; 09054 ptr += sizeof(*mtm); 09055 packet_len -= sizeof(*mtm); 09056 len = ntohs(mtm->len); 09057 callno = ntohs(mtm->mini.callno); 09058 trunked_ts = ntohs(mtm->mini.ts); 09059 } else if (metatype == IAX_META_TRUNK_SUPERMINI) { 09060 mte = (struct ast_iax2_meta_trunk_entry *)ptr; 09061 ptr += sizeof(*mte); 09062 packet_len -= sizeof(*mte); 09063 len = ntohs(mte->len); 09064 callno = ntohs(mte->callno); 09065 trunked_ts = 0; 09066 } else { 09067 ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 09068 break; 09069 } 09070 /* Stop if we don't have enough data */ 09071 if (len > packet_len) 09072 break; 09073 fr->callno = find_callno_locked(callno & ~IAX_FLAG_FULL, 0, sin, NEW_PREVENT, sockfd, 0); 09074 if (!fr->callno) 09075 continue; 09076 09077 /* If it's a valid call, deliver the contents. If not, we 09078 drop it, since we don't have a scallno to use for an INVAL */ 09079 /* Process as a mini frame */ 09080 memset(&f, 0, sizeof(f)); 09081 f.frametype = AST_FRAME_VOICE; 09082 if (!iaxs[fr->callno]) { 09083 /* drop it */ 09084 } else if (iaxs[fr->callno]->voiceformat == 0) { 09085 ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n"); 09086 iax2_vnak(fr->callno); 09087 } else { 09088 f.subclass = iaxs[fr->callno]->voiceformat; 09089 f.datalen = len; 09090 if (f.datalen >= 0) { 09091 if (f.datalen) 09092 f.data.ptr = ptr; 09093 else 09094 f.data.ptr = NULL; 09095 if (trunked_ts) 09096 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff); 09097 else 09098 fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts); 09099 /* Don't pass any packets until we're started */ 09100 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 09101 struct iax_frame *duped_fr; 09102 09103 /* Common things */ 09104 f.src = "IAX2"; 09105 f.mallocd = 0; 09106 f.offset = 0; 09107 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 09108 f.samples = ast_codec_get_samples(&f); 09109 else 09110 f.samples = 0; 09111 fr->outoforder = 0; 09112 iax_frame_wrap(fr, &f); 09113 duped_fr = iaxfrdup2(fr); 09114 if (duped_fr) 09115 schedule_delivery(duped_fr, 1, 1, &fr->ts); 09116 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) 09117 iaxs[fr->callno]->last = fr->ts; 09118 } 09119 } else { 09120 ast_log(LOG_WARNING, "Datalen < 0?\n"); 09121 } 09122 } 09123 ast_mutex_unlock(&iaxsl[fr->callno]); 09124 ptr += len; 09125 packet_len -= len; 09126 } 09127 09128 return 1; 09129 }
| static int socket_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | cbdata | |||
| ) | [static] |
Definition at line 8927 of file chan_iax2.c.
References ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), iax2_thread::buf, iax2_thread::buf_len, iax2_thread::buf_size, iax2_thread::callno, iax2_thread::cond, ast_iax2_full_hdr::csub, iax2_thread::csub, iax2_thread::curfunc, defer_full_frame(), errno, iax2_thread::ffinfo, find_idle_thread(), handle_error(), IAX_FLAG_FULL, IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, inaddrcmp(), iax2_thread::iofd, iax2_thread::iosin, iax2_thread::iostate, iax2_thread::lock, LOG_WARNING, iax2_thread::readbuf, ast_iax2_full_hdr::scallno, signal_condition(), iax2_thread::sin, thread, ast_iax2_full_hdr::type, and iax2_thread::type.
Referenced by peer_set_srcaddr(), and set_config().
08928 { 08929 struct iax2_thread *thread; 08930 socklen_t len; 08931 time_t t; 08932 static time_t last_errtime = 0; 08933 struct ast_iax2_full_hdr *fh; 08934 08935 if (!(thread = find_idle_thread())) { 08936 time(&t); 08937 if (t != last_errtime) 08938 ast_debug(1, "Out of idle IAX2 threads for I/O, pausing!\n"); 08939 last_errtime = t; 08940 usleep(1); 08941 return 1; 08942 } 08943 08944 len = sizeof(thread->iosin); 08945 thread->iofd = fd; 08946 thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len); 08947 thread->buf_size = sizeof(thread->readbuf); 08948 thread->buf = thread->readbuf; 08949 if (thread->buf_len < 0) { 08950 if (errno != ECONNREFUSED && errno != EAGAIN) 08951 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); 08952 handle_error(); 08953 thread->iostate = IAX_IOSTATE_IDLE; 08954 signal_condition(&thread->lock, &thread->cond); 08955 return 1; 08956 } 08957 if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */ 08958 thread->iostate = IAX_IOSTATE_IDLE; 08959 signal_condition(&thread->lock, &thread->cond); 08960 return 1; 08961 } 08962 08963 /* Determine if this frame is a full frame; if so, and any thread is currently 08964 processing a full frame for the same callno from this peer, then drop this 08965 frame (and the peer will retransmit it) */ 08966 fh = (struct ast_iax2_full_hdr *) thread->buf; 08967 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 08968 struct iax2_thread *cur = NULL; 08969 uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL; 08970 08971 AST_LIST_LOCK(&active_list); 08972 AST_LIST_TRAVERSE(&active_list, cur, list) { 08973 if ((cur->ffinfo.callno == callno) && 08974 !inaddrcmp(&cur->ffinfo.sin, &thread->iosin)) 08975 break; 08976 } 08977 if (cur) { 08978 /* we found another thread processing a full frame for this call, 08979 so queue it up for processing later. */ 08980 defer_full_frame(thread, cur); 08981 AST_LIST_UNLOCK(&active_list); 08982 thread->iostate = IAX_IOSTATE_IDLE; 08983 signal_condition(&thread->lock, &thread->cond); 08984 return 1; 08985 } else { 08986 /* this thread is going to process this frame, so mark it */ 08987 thread->ffinfo.callno = callno; 08988 memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin)); 08989 thread->ffinfo.type = fh->type; 08990 thread->ffinfo.csub = fh->csub; 08991 } 08992 AST_LIST_UNLOCK(&active_list); 08993 } 08994 08995 /* Mark as ready and send on its way */ 08996 thread->iostate = IAX_IOSTATE_READY; 08997 #ifdef DEBUG_SCHED_MULTITHREAD 08998 ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc)); 08999 #endif 09000 signal_condition(&thread->lock, &thread->cond); 09001 09002 return 1; 09003 }
| static void spawn_dp_lookup | ( | int | callno, | |
| const char * | context, | |||
| const char * | callednum, | |||
| const char * | callerid | |||
| ) | [static] |
Definition at line 8643 of file chan_iax2.c.
References ast_calloc, ast_copy_string(), ast_log(), ast_pthread_create_detached, ast_strdup, dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, dp_lookup_thread(), and LOG_WARNING.
Referenced by socket_process().
08644 { 08645 pthread_t newthread; 08646 struct dpreq_data *dpr; 08647 08648 if (!(dpr = ast_calloc(1, sizeof(*dpr)))) 08649 return; 08650 08651 dpr->callno = callno; 08652 ast_copy_string(dpr->context, context, sizeof(dpr->context)); 08653 ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum)); 08654 if (callerid) 08655 dpr->callerid = ast_strdup(callerid); 08656 if (ast_pthread_create_detached(&newthread, NULL, dp_lookup_thread, dpr)) { 08657 ast_log(LOG_WARNING, "Unable to start lookup thread!\n"); 08658 } 08659 }
| static int start_network_thread | ( | void | ) | [static] |
Definition at line 11452 of file chan_iax2.c.
References ast_calloc, ast_cond_init(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_pthread_create_background, ast_pthread_create_detached, ast_verb, iax2_thread::cond, iax2_process_thread(), IAX_THREAD_TYPE_POOL, iaxthreadcount, iax2_thread::lock, LOG_WARNING, network_thread(), sched_thread(), thread, iax2_thread::threadid, iax2_thread::threadnum, and iax2_thread::type.
Referenced by load_module().
11453 { 11454 struct iax2_thread *thread; 11455 int threadcount = 0; 11456 int x; 11457 for (x = 0; x < iaxthreadcount; x++) { 11458 thread = ast_calloc(1, sizeof(*thread)); 11459 if (thread) { 11460 thread->type = IAX_THREAD_TYPE_POOL; 11461 thread->threadnum = ++threadcount; 11462 ast_mutex_init(&thread->lock); 11463 ast_cond_init(&thread->cond, NULL); 11464 if (ast_pthread_create_detached(&thread->threadid, NULL, iax2_process_thread, thread)) { 11465 ast_log(LOG_WARNING, "Failed to create new thread!\n"); 11466 ast_free(thread); 11467 thread = NULL; 11468 } 11469 AST_LIST_LOCK(&idle_list); 11470 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 11471 AST_LIST_UNLOCK(&idle_list); 11472 } 11473 } 11474 ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL); 11475 ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); 11476 ast_verb(2, "%d helper threads started\n", threadcount); 11477 return 0; 11478 }
| static void stop_stuff | ( | int | callno | ) | [static] |
Definition at line 8346 of file chan_iax2.c.
References iax2_destroy_helper().
Referenced by socket_process().
08347 { 08348 iax2_destroy_helper(iaxs[callno]); 08349 }
| static void store_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1803 of file chan_iax2.c.
References ao2_link, ast_log(), LOG_ERROR, and chan_iax2_pvt::peercallno.
Referenced by __find_callno(), complete_transfer(), and socket_process().
01804 { 01805 if (!pvt->peercallno) { 01806 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01807 return; 01808 } 01809 01810 ao2_link(iax_peercallno_pvts, pvt); 01811 }
| static void store_by_transfercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1784 of file chan_iax2.c.
References ao2_link, ast_log(), LOG_ERROR, and chan_iax2_pvt::transfercallno.
Referenced by try_transfer().
01785 { 01786 if (!pvt->transfercallno) { 01787 ast_log(LOG_ERROR, "This should not be called without a transfer call number.\n"); 01788 return; 01789 } 01790 01791 ao2_link(iax_transfercallno_pvts, pvt); 01792 }
| static int timing_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | cbdata | |||
| ) | [static] |
Definition at line 8532 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_debug, ast_free, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_timer_ack(), ast_tvnow(), ast_verbose, iax2_trunk_expired(), iax2_trunk_peer::lock, send_trunk(), totalcalls, iax2_trunk_peer::trunkdataalloc, and iax2_trunk_peer::trunkdatalen.
Referenced by network_thread().
08533 { 08534 int res, processed = 0, totalcalls = 0; 08535 struct iax2_trunk_peer *tpeer = NULL, *drop = NULL; 08536 struct timeval now = ast_tvnow(); 08537 08538 if (iaxtrunkdebug) 08539 ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", trunkmaxsize); 08540 08541 if (timer) { 08542 ast_timer_ack(timer, 1); 08543 } 08544 08545 /* For each peer that supports trunking... */ 08546 AST_LIST_LOCK(&tpeers); 08547 AST_LIST_TRAVERSE_SAFE_BEGIN(&tpeers, tpeer, list) { 08548 processed++; 08549 res = 0; 08550 ast_mutex_lock(&tpeer->lock); 08551 /* We can drop a single tpeer per pass. That makes all this logic 08552 substantially easier */ 08553 if (!drop && iax2_trunk_expired(tpeer, &now)) { 08554 /* Take it out of the list, but don't free it yet, because it 08555 could be in use */ 08556 AST_LIST_REMOVE_CURRENT(list); 08557 drop = tpeer; 08558 } else { 08559 res = send_trunk(tpeer, &now); 08560 trunk_timed++; 08561 if (iaxtrunkdebug) 08562 ast_verbose(" - Trunk peer (%s:%d) has %d call chunk%s in transit, %d bytes backloged and has hit a high water mark of %d bytes\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), res, (res != 1) ? "s" : "", tpeer->trunkdatalen, tpeer->trunkdataalloc); 08563 } 08564 totalcalls += res; 08565 res = 0; 08566 ast_mutex_unlock(&tpeer->lock); 08567 } 08568 AST_LIST_TRAVERSE_SAFE_END; 08569 AST_LIST_UNLOCK(&tpeers); 08570 08571 if (drop) { 08572 ast_mutex_lock(&drop->lock); 08573 /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 08574 because by the time they could get tpeerlock, we've already grabbed it */ 08575 ast_debug(1, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port)); 08576 if (drop->trunkdata) { 08577 ast_free(drop->trunkdata); 08578 drop->trunkdata = NULL; 08579 } 08580 ast_mutex_unlock(&drop->lock); 08581 ast_mutex_destroy(&drop->lock); 08582 ast_free(drop); 08583 08584 } 08585 08586 if (iaxtrunkdebug) 08587 ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls); 08588 iaxtrunkdebug = 0; 08589 08590 return 1; 08591 }
| static int transfercallno_pvt_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 13474 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, chan_iax2_pvt::frames_received, and match().
Referenced by load_objects().
13475 { 13476 struct chan_iax2_pvt *pvt = obj, *pvt2 = arg; 13477 13478 /* The frames_received field is used to hold whether we're matching 13479 * against a full frame or not ... */ 13480 13481 return match(&pvt2->transfer, pvt2->transfercallno, pvt2->callno, pvt, 13482 pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0; 13483 }
| static int transfercallno_pvt_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 13467 of file chan_iax2.c.
References chan_iax2_pvt::transfercallno.
Referenced by load_objects().
13468 { 13469 const struct chan_iax2_pvt *pvt = obj; 13470 13471 return pvt->transfercallno; 13472 }
| static int transmit_trunk | ( | struct iax_frame * | f, | |
| struct sockaddr_in * | sin, | |||
| int | sockfd | |||
| ) | [static] |
Definition at line 2988 of file chan_iax2.c.
References ast_debug, iax_frame::data, iax_frame::datalen, errno, and handle_error().
Referenced by send_trunk().
02989 { 02990 int res; 02991 res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin, 02992 sizeof(*sin)); 02993 if (res < 0) { 02994 ast_debug(1, "Received error: %s\n", strerror(errno)); 02995 handle_error(); 02996 } else 02997 res = 0; 02998 return res; 02999 }
| static int try_firmware | ( | char * | s | ) | [static] |
Definition at line 2690 of file chan_iax2.c.
References ast_calloc, AST_FILE_MODE, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_random(), ast_strlen_zero(), ast_iax2_firmware_header::chksum, ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, iax_firmware::dead, ast_iax2_firmware_header::devname, errno, iax_firmware::fd, iax_firmware::fwh, IAX_FIRMWARE_MAGIC, last, LOG_WARNING, ast_iax2_firmware_header::magic, MD5Final(), MD5Init(), MD5Update(), iax_firmware::mmaplen, and ast_iax2_firmware_header::version.
Referenced by reload_firmware().
02691 { 02692 struct stat stbuf; 02693 struct iax_firmware *cur = NULL; 02694 int ifd, fd, res, len, chunk; 02695 struct ast_iax2_firmware_header *fwh, fwh2; 02696 struct MD5Context md5; 02697 unsigned char sum[16], buf[1024]; 02698 char *s2, *last; 02699 02700 if (!(s2 = alloca(strlen(s) + 100))) { 02701 ast_log(LOG_WARNING, "Alloca failed!\n"); 02702 return -1; 02703 } 02704 02705 last = strrchr(s, '/'); 02706 if (last) 02707 last++; 02708 else 02709 last = s; 02710 02711 snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random()); 02712 02713 if ((res = stat(s, &stbuf) < 0)) { 02714 ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno)); 02715 return -1; 02716 } 02717 02718 /* Make sure it's not a directory */ 02719 if (S_ISDIR(stbuf.st_mode)) 02720 return -1; 02721 ifd = open(s, O_RDONLY); 02722 if (ifd < 0) { 02723 ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno)); 02724 return -1; 02725 } 02726 fd = open(s2, O_RDWR | O_CREAT | O_EXCL, AST_FILE_MODE); 02727 if (fd < 0) { 02728 ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno)); 02729 close(ifd); 02730 return -1; 02731 } 02732 /* Unlink our newly created file */ 02733 unlink(s2); 02734 02735 /* Now copy the firmware into it */ 02736 len = stbuf.st_size; 02737 while(len) { 02738 chunk = len; 02739 if (chunk > sizeof(buf)) 02740 chunk = sizeof(buf); 02741 res = read(ifd, buf, chunk); 02742 if (res != chunk) { 02743 ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 02744 close(ifd); 02745 close(fd); 02746 return -1; 02747 } 02748 res = write(fd, buf, chunk); 02749 if (res != chunk) { 02750 ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 02751 close(ifd); 02752 close(fd); 02753 return -1; 02754 } 02755 len -= chunk; 02756 } 02757 close(ifd); 02758 /* Return to the beginning */ 02759 lseek(fd, 0, SEEK_SET); 02760 if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) { 02761 ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s); 02762 close(fd); 02763 return -1; 02764 } 02765 if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) { 02766 ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s); 02767 close(fd); 02768 return -1; 02769 } 02770 if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) { 02771 ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s); 02772 close(fd); 02773 return -1; 02774 } 02775 if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) { 02776 ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s); 02777 close(fd); 02778 return -1; 02779 } 02780 fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 02781 if (fwh == MAP_FAILED) { 02782 ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno)); 02783 close(fd); 02784 return -1; 02785 } 02786 MD5Init(&md5); 02787 MD5Update(&md5, fwh->data, ntohl(fwh->datalen)); 02788 MD5Final(sum, &md5); 02789 if (memcmp(sum, fwh->chksum, sizeof(sum))) { 02790 ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s); 02791 munmap((void*)fwh, stbuf.st_size); 02792 close(fd); 02793 return -1; 02794 } 02795 02796 AST_LIST_TRAVERSE(&firmwares, cur, list) { 02797 if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) { 02798 /* Found a candidate */ 02799 if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version))) 02800 /* The version we have on loaded is older, load this one instead */ 02801 break; 02802 /* This version is no newer than what we have. Don't worry about it. 02803 We'll consider it a proper load anyhow though */ 02804 munmap((void*)fwh, stbuf.st_size); 02805 close(fd); 02806 return 0; 02807 } 02808 } 02809 02810 if (!cur && ((cur = ast_calloc(1, sizeof(*cur))))) { 02811 cur->fd = -1; 02812 AST_LIST_INSERT_TAIL(&firmwares, cur, list); 02813 } 02814 02815 if (cur) { 02816 if (cur->fwh) 02817 munmap((void*)cur->fwh, cur->mmaplen); 02818 if (cur->fd > -1) 02819 close(cur->fd); 02820 cur->fwh = fwh; 02821 cur->fd = fd; 02822 cur->mmaplen = stbuf.st_size; 02823 cur->dead = 0; 02824 } 02825 02826 return 0; 02827 }
| static int try_transfer | ( | struct chan_iax2_pvt * | pvt, | |
| struct iax_ies * | ies | |||
| ) | [static] |
Definition at line 7694 of file chan_iax2.c.
References iax_ies::apparent_addr, AST_FRAME_IAX, ast_log(), iax_ie_data::buf, iax_ies::callno, IAX_COMMAND_TXCNT, iax_ie_append_int(), IAX_IE_TRANSFERID, LOG_WARNING, iax_ie_data::pos, send_command_transfer(), store_by_transfercallno(), chan_iax2_pvt::transfer, TRANSFER_BEGIN, chan_iax2_pvt::transfercallno, iax_ies::transferid, chan_iax2_pvt::transferid, and chan_iax2_pvt::transferring.
Referenced by socket_process().
07695 { 07696 int newcall = 0; 07697 char newip[256]; 07698 struct iax_ie_data ied; 07699 struct sockaddr_in new; 07700 07701 07702 memset(&ied, 0, sizeof(ied)); 07703 if (ies->apparent_addr) 07704 memmove(&new, ies->apparent_addr, sizeof(new)); 07705 if (ies->callno) 07706 newcall = ies->callno; 07707 if (!newcall || !new.sin_addr.s_addr || !new.sin_port) { 07708 ast_log(LOG_WARNING, "Invalid transfer request\n"); 07709 return -1; 07710 } 07711 pvt->transfercallno = newcall; 07712 memcpy(&pvt->transfer, &new, sizeof(pvt->transfer)); 07713 inet_aton(newip, &pvt->transfer.sin_addr); 07714 pvt->transfer.sin_family = AF_INET; 07715 pvt->transferring = TRANSFER_BEGIN; 07716 pvt->transferid = ies->transferid; 07717 store_by_transfercallno(pvt); 07718 if (ies->transferid) 07719 iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid); 07720 send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos); 07721 return 0; 07722 }
| static int uncompress_subclass | ( | unsigned char | csub | ) | [static] |
Definition at line 1379 of file chan_iax2.c.
References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.
Referenced by decode_frame(), handle_call_token(), and socket_process().
01380 { 01381 /* If the SC_LOG flag is set, return 2^csub otherwise csub */ 01382 if (csub & IAX_FLAG_SC_LOG) { 01383 /* special case for 'compressed' -1 */ 01384 if (csub == 0xff) 01385 return -1; 01386 else 01387 return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT); 01388 } 01389 else 01390 return csub; 01391 }
| static void unlink_peer | ( | struct iax2_peer * | peer | ) | [static] |
Definition at line 7980 of file chan_iax2.c.
References ao2_unlink, ast_sched_del(), iax2_peer::expire, peer_unref(), and iax2_peer::pokeexpire.
Referenced by __expire_registry(), build_peer(), and prune_peers().
07981 { 07982 if (peer->expire > -1) { 07983 if (!ast_sched_del(sched, peer->expire)) { 07984 peer->expire = -1; 07985 peer_unref(peer); 07986 } 07987 } 07988 07989 if (peer->pokeexpire > -1) { 07990 if (!ast_sched_del(sched, peer->pokeexpire)) { 07991 peer->pokeexpire = -1; 07992 peer_unref(peer); 07993 } 07994 } 07995 07996 ao2_unlink(peers, peer); 07997 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 13432 of file chan_iax2.c.
References __unload_module(), and ast_custom_function_unregister().
13433 { 13434 ast_custom_function_unregister(&iaxpeer_function); 13435 ast_custom_function_unregister(&iaxvar_function); 13436 return __unload_module(); 13437 }
| static void unlock_both | ( | unsigned short | callno0, | |
| unsigned short | callno1 | |||
| ) | [static] |
Definition at line 4987 of file chan_iax2.c.
References ast_mutex_unlock().
Referenced by iax2_bridge().
04988 { 04989 ast_mutex_unlock(&iaxsl[callno1]); 04990 ast_mutex_unlock(&iaxsl[callno0]); 04991 }
| static void unwrap_timestamp | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 3654 of file chan_iax2.c.
References iax_frame::af, ast_debug, AST_FRAME_VIDEO, iax_frame::callno, ast_frame::frametype, chan_iax2_pvt::last, and iax_frame::ts.
Referenced by schedule_delivery().
03655 { 03656 /* Video mini frames only encode the lower 15 bits of the session 03657 * timestamp, but other frame types (e.g. audio) encode 16 bits. */ 03658 const int ts_shift = (fr->af.frametype == AST_FRAME_VIDEO) ? 15 : 16; 03659 const int lower_mask = (1 << ts_shift) - 1; 03660 const int upper_mask = ~lower_mask; 03661 const int last_upper = iaxs[fr->callno]->last & upper_mask; 03662 03663 if ( (fr->ts & upper_mask) == last_upper ) { 03664 const int x = fr->ts - iaxs[fr->callno]->last; 03665 const int threshold = (ts_shift == 15) ? 25000 : 50000; 03666 03667 if (x < -threshold) { 03668 /* Sudden big jump backwards in timestamp: 03669 What likely happened here is that miniframe timestamp has circled but we haven't 03670 gotten the update from the main packet. We'll just pretend that we did, and 03671 update the timestamp appropriately. */ 03672 fr->ts = (last_upper + (1 << ts_shift)) | (fr->ts & lower_mask); 03673 if (iaxdebug) 03674 ast_debug(1, "schedule_delivery: pushed forward timestamp\n"); 03675 } else if (x > threshold) { 03676 /* Sudden apparent big jump forwards in timestamp: 03677 What's likely happened is this is an old miniframe belonging to the previous 03678 top 15 or 16-bit timestamp that has turned up out of order. 03679 Adjust the timestamp appropriately. */ 03680 fr->ts = (last_upper - (1 << ts_shift)) | (fr->ts & lower_mask); 03681 if (iaxdebug) 03682 ast_debug(1, "schedule_delivery: pushed back timestamp\n"); 03683 } 03684 } 03685 }
| static void update_jbsched | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 3689 of file chan_iax2.c.
References ast_tvdiff_ms(), ast_tvnow(), chan_iax2_pvt::callno, CALLNO_TO_PTR, get_from_jb(), iax2_sched_replace(), chan_iax2_pvt::jb, jb_next(), chan_iax2_pvt::jbid, and chan_iax2_pvt::rxcore.
Referenced by __get_from_jb(), and schedule_delivery().
03690 { 03691 int when; 03692 03693 when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore); 03694 03695 when = jb_next(pvt->jb) - when; 03696 03697 if (when <= 0) { 03698 /* XXX should really just empty until when > 0.. */ 03699 when = 1; 03700 } 03701 03702 pvt->jbid = iax2_sched_replace(pvt->jbid, sched, when, get_from_jb, 03703 CALLNO_TO_PTR(pvt->callno)); 03704 }
| static void update_max_nontrunk | ( | void | ) | [static] |
Definition at line 1712 of file chan_iax2.c.
References ast_debug, and TRUNK_CALL_START.
Referenced by __find_callno(), and make_trunk().
01713 { 01714 int max = 1; 01715 int x; 01716 /* XXX Prolly don't need locks here XXX */ 01717 for (x=1;x<TRUNK_CALL_START - 1; x++) { 01718 if (iaxs[x]) 01719 max = x + 1; 01720 } 01721 maxnontrunkcall = max; 01722 if (iaxdebug) 01723 ast_debug(1, "New max nontrunk callno is %d\n", max); 01724 }
| static void update_max_trunk | ( | void | ) | [static] |
Definition at line 1695 of file chan_iax2.c.
References ARRAY_LEN, ast_debug, and TRUNK_CALL_START.
Referenced by iax2_destroy(), and make_trunk().
01696 { 01697 int max = TRUNK_CALL_START; 01698 int x; 01699 01700 /* XXX Prolly don't need locks here XXX */ 01701 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01702 if (iaxs[x]) { 01703 max = x + 1; 01704 } 01705 } 01706 01707 maxtrunkcall = max; 01708 if (iaxdebug) 01709 ast_debug(1, "New max trunk callno is %d\n", max); 01710 }
| static int update_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 3117 of file chan_iax2.c.
References build_rand_pad(), iax_frame::callno, iax_frame::data, iax_frame::datalen, iax_frame::dcallno, ast_iax2_full_hdr::dcallno, decode_frame(), iax_frame::ecx, iax_frame::encmethods, encrypt_frame(), IAX_FLAG_RETRANS, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, iax_frame::mydcx, and iax_frame::semirand.
Referenced by __attempt_transmit().
03118 { 03119 /* Called with iaxsl lock held, and iaxs[callno] non-NULL */ 03120 struct ast_iax2_full_hdr *fh = f->data; 03121 struct ast_frame af; 03122 03123 /* if frame is encrypted. decrypt before updating it. */ 03124 if (f->encmethods) { 03125 decode_frame(&f->mydcx, fh, &af, &f->datalen); 03126 } 03127 /* Mark this as a retransmission */ 03128 fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno); 03129 /* Update iseqno */ 03130 f->iseqno = iaxs[f->callno]->iseqno; 03131 fh->iseqno = f->iseqno; 03132 03133 /* Now re-encrypt the frame */ 03134 if (f->encmethods) { 03135 /* since this is a retransmit frame, create a new random padding 03136 * before re-encrypting. */ 03137 build_rand_pad(f->semirand, sizeof(f->semirand)); 03138 encrypt_frame(&f->ecx, fh, f->semirand, &f->datalen); 03139 } 03140 return 0; 03141 }
| static int update_registry | ( | struct sockaddr_in * | sin, | |
| int | callno, | |||
| char * | devtype, | |||
| int | fd, | |||
| unsigned short | refresh | |||
| ) | [static] |
Definition at line 8091 of file chan_iax2.c.
References iax2_peer::addr, ast_app_inboxcount(), ast_db_del(), ast_db_put(), AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verb, iax_ie_data::buf, iax2_peer::cid_name, iax2_peer::cid_num, context, EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), iax2_datetime(), iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), iax_check_version(), IAX_COMMAND_REGACK, IAX_HASCALLERID, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_DATETIME, IAX_IE_FIRMWAREVER, IAX_IE_MSGCOUNT, IAX_IE_REFRESH, IAX_IE_USERNAME, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_STATE_AUTHENTICATED, IAX_TEMPONLY, inaddrcmp(), LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mailbox, manager_event, iax2_peer::maxcallno, iax2_peer::name, peer_ref(), peer_unref(), peercnt_modify(), iax_ie_data::pos, realtime_update_peer(), register_peer_exten(), send_command_final(), iax2_peer::sockfd, strsep(), version, and iax2_peer::zonetag.
Referenced by socket_process().
08092 { 08093 /* Called from IAX thread only, with proper iaxsl lock */ 08094 struct iax_ie_data ied; 08095 struct iax2_peer *p; 08096 int msgcount; 08097 char data[80]; 08098 int version; 08099 const char *peer_name; 08100 int res = -1; 08101 08102 memset(&ied, 0, sizeof(ied)); 08103 08104 peer_name = ast_strdupa(iaxs[callno]->peer); 08105 08106 /* SLD: Another find_peer call during registration - this time when we are really updating our registration */ 08107 ast_mutex_unlock(&iaxsl[callno]); 08108 if (!(p = find_peer(peer_name, 1))) { 08109 ast_mutex_lock(&iaxsl[callno]); 08110 ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name); 08111 return -1; 08112 } 08113 ast_mutex_lock(&iaxsl[callno]); 08114 if (!iaxs[callno]) 08115 goto return_unref; 08116 08117 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) { 08118 if (sin->sin_addr.s_addr) { 08119 time_t nowtime; 08120 time(&nowtime); 08121 realtime_update_peer(peer_name, sin, nowtime); 08122 } else { 08123 realtime_update_peer(peer_name, sin, 0); 08124 } 08125 } 08126 if (inaddrcmp(&p->addr, sin)) { 08127 if (iax2_regfunk) 08128 iax2_regfunk(p->name, 1); 08129 08130 /* modify entry in peercnts table as _not_ registered */ 08131 peercnt_modify(0, 0, &p->addr); 08132 08133 /* Stash the IP address from which they registered */ 08134 memcpy(&p->addr, sin, sizeof(p->addr)); 08135 08136 snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry); 08137 if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) { 08138 ast_db_put("IAX/Registry", p->name, data); 08139 ast_verb(3, "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 08140 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 08141 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name); 08142 register_peer_exten(p, 1); 08143 ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ 08144 } else if (!ast_test_flag(p, IAX_TEMPONLY)) { 08145 ast_verb(3, "Unregistered IAX2 '%s' (%s)\n", p->name, 08146 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED"); 08147 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name); 08148 register_peer_exten(p, 0); 08149 ast_db_del("IAX/Registry", p->name); 08150 ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", p->name); /* Activate notification */ 08151 } 08152 /* Update the host */ 08153 /* Verify that the host is really there */ 08154 iax2_poke_peer(p, callno); 08155 } 08156 08157 /* modify entry in peercnts table as registered */ 08158 if (p->maxcallno) { 08159 peercnt_modify(1, p->maxcallno, &p->addr); 08160 } 08161 08162 /* Make sure our call still exists, an INVAL at the right point may make it go away */ 08163 if (!iaxs[callno]) { 08164 res = -1; 08165 goto return_unref; 08166 } 08167 08168 /* Store socket fd */ 08169 p->sockfd = fd; 08170 /* Setup the expiry */ 08171 if (p->expire > -1) { 08172 if (!ast_sched_del(sched, p->expire)) { 08173 p->expire = -1; 08174 peer_unref(p); 08175 } 08176 } 08177 /* treat an unspecified refresh interval as the minimum */ 08178 if (!refresh) 08179 refresh = min_reg_expire; 08180 if (refresh > max_reg_expire) { 08181 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 08182 p->name, max_reg_expire, refresh); 08183 p->expiry = max_reg_expire; 08184 } else if (refresh < min_reg_expire) { 08185 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 08186 p->name, min_reg_expire, refresh); 08187 p->expiry = min_reg_expire; 08188 } else { 08189 p->expiry = refresh; 08190 } 08191 if (p->expiry && sin->sin_addr.s_addr) { 08192 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 08193 if (p->expire == -1) 08194 peer_unref(p); 08195 } 08196 iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name); 08197 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag)); 08198 if (sin->sin_addr.s_addr) { 08199 iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry); 08200 iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr); 08201 if (!ast_strlen_zero(p->mailbox)) { 08202 struct ast_event *event; 08203 int new, old; 08204 char *mailbox, *context; 08205 08206 context = mailbox = ast_strdupa(p->mailbox); 08207 strsep(&context, "@"); 08208 if (ast_strlen_zero(context)) 08209 context = "default"; 08210 08211 event = ast_event_get_cached(AST_EVENT_MWI, 08212 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 08213 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 08214 AST_EVENT_IE_END); 08215 if (event) { 08216 new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 08217 old = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 08218 ast_event_destroy(event); 08219 } else { /* Fall back on checking the mailbox directly */ 08220 ast_app_inboxcount(p->mailbox, &new, &old); 08221 } 08222 08223 if (new > 255) { 08224 new = 255; 08225 } 08226 if (old > 255) { 08227 old = 255; 08228 } 08229 msgcount = (old << 8) | new; 08230 08231 iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount); 08232 } 08233 if (ast_test_flag(p, IAX_HASCALLERID)) { 08234 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num); 08235 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name); 08236 } 08237 } 08238 version = iax_check_version(devtype); 08239 if (version) 08240 iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version); 08241 08242 res = 0; 08243 08244 return_unref: 08245 peer_unref(p); 08246 08247 return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1); 08248 }
| static int user_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1426 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, and iax2_user::name.
Referenced by load_objects().
| static int user_delme_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 12127 of file chan_iax2.c.
References ast_set_flag, and IAX_DELME.
Referenced by delete_users().
12128 { 12129 struct iax2_user *user = obj; 12130 12131 ast_set_flag(user, IAX_DELME); 12132 12133 return 0; 12134 }
| static void user_destructor | ( | void * | obj | ) | [static] |
Definition at line 11878 of file chan_iax2.c.
References ast_free_ha(), ast_string_field_free_memory, ast_variables_destroy(), iax2_user::contexts, free_context(), iax2_user::ha, and iax2_user::vars.
Referenced by build_user().
11879 { 11880 struct iax2_user *user = obj; 11881 11882 ast_free_ha(user->ha); 11883 free_context(user->contexts); 11884 if(user->vars) { 11885 ast_variables_destroy(user->vars); 11886 user->vars = NULL; 11887 } 11888 ast_string_field_free_memory(user); 11889 }
| static int user_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1416 of file chan_iax2.c.
References ast_str_hash(), and iax2_user::name.
Referenced by load_objects().
01417 { 01418 const struct iax2_user *user = obj; 01419 01420 return ast_str_hash(user->name); 01421 }
Definition at line 1473 of file chan_iax2.c.
References ao2_ref.
01474 { 01475 ao2_ref(user, +1); 01476 return user; 01477 }
Definition at line 1479 of file chan_iax2.c.
References ao2_ref.
Referenced by authenticate_request(), authenticate_verify(), build_user(), calltoken_required(), check_access(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_users(), iax2_destroy_helper(), prune_users(), requirecalltoken_mark_auto(), and set_config().
01480 { 01481 ao2_ref(user, -1); 01482 return NULL; 01483 }
| static void vnak_retransmit | ( | int | callno, | |
| int | last | |||
| ) | [static] |
Definition at line 8447 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax_frame::callno, f, iax_frame::oseqno, iax_frame::retries, and send_packet().
Referenced by socket_process().
08448 { 08449 struct iax_frame *f; 08450 08451 AST_LIST_LOCK(&frame_queue); 08452 AST_LIST_TRAVERSE(&frame_queue, f, list) { 08453 /* Send a copy immediately */ 08454 if ((f->callno == callno) && iaxs[f->callno] && 08455 ((unsigned char ) (f->oseqno - last) < 128) && 08456 (f->retries >= 0)) { 08457 send_packet(f); 08458 } 08459 } 08460 AST_LIST_UNLOCK(&frame_queue); 08461 }
| static int wait_for_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 4844 of file chan_iax2.c.
References chan_iax2_pvt::callno, DEADLOCK_AVOIDANCE, and chan_iax2_pvt::peercallno.
Referenced by iax2_indicate(), and iax2_setoption().
04845 { 04846 unsigned short callno = pvt->callno; 04847 04848 if (!pvt->peercallno) { 04849 /* We don't know the remote side's call number, yet. :( */ 04850 int count = 10; 04851 while (count-- && pvt && !pvt->peercallno) { 04852 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 04853 pvt = iaxs[callno]; 04854 } 04855 if (!pvt->peercallno) { 04856 return -1; 04857 } 04858 } 04859 04860 return 0; 04861 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Inter Asterisk eXchange (Ver 2)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 13655 of file chan_iax2.c.
char accountcode[AST_MAX_ACCOUNT_CODE] [static] |
Definition at line 243 of file chan_iax2.c.
Referenced by __ast_channel_alloc_ap(), __oh323_new(), ast_call_forward(), ast_cdr_setaccount(), begin_dial_channel(), check_peer_ok(), dahdi_new(), dial_exec_full(), disa_exec(), do_forward(), gtalk_new(), jingle_new(), local_call(), sip_new(), tds_log(), and wait_for_answer().
int adsi = 0 [static] |
Definition at line 247 of file chan_iax2.c.
int amaflags = 0 [static] |
Definition at line 246 of file chan_iax2.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 13655 of file chan_iax2.c.
int authdebug = 1 [static] |
Definition at line 159 of file chan_iax2.c.
int autokill = 0 [static] |
Definition at line 160 of file chan_iax2.c.
struct ao2_container* callno_limits [static] |
Table containing custom callno limit rules for a range of ip addresses.
Definition at line 743 of file chan_iax2.c.
Referenced by __unload_module(), build_callno_limits(), load_objects(), reload_config(), set_config_destroy(), and set_peercnt_limit().
struct ao2_container* callno_pool [static] |
table of available call numbers
Definition at line 702 of file chan_iax2.c.
const unsigned int CALLNO_POOL_BUCKETS = 2699 [static] |
Definition at line 707 of file chan_iax2.c.
struct ao2_container* callno_pool_trunk [static] |
table of available trunk call numbers
Definition at line 705 of file chan_iax2.c.
struct ao2_container* calltoken_ignores [static] |
Table containing ip addresses not requiring calltoken validation
Definition at line 746 of file chan_iax2.c.
Referenced by __unload_module(), add_calltoken_ignore(), calltoken_required(), load_objects(), reload_config(), and set_config_destroy().
struct ast_cli_entry cli_iax2[] [static] |
Definition at line 13314 of file chan_iax2.c.
| unsigned int cos |
Definition at line 170 of file chan_iax2.c.
struct sockaddr_in debugaddr [static] |
Definition at line 948 of file chan_iax2.c.
Referenced by handle_cli_iax2_set_debug(), iax_outputframe(), and reload_config().
uint16_t DEFAULT_MAXCALLNO_LIMIT = 2048 [static] |
Definition at line 748 of file chan_iax2.c.
Referenced by set_config().
uint16_t DEFAULT_MAXCALLNO_LIMIT_NONVAL = 8192 [static] |
Definition at line 750 of file chan_iax2.c.
Referenced by set_config().
char default_parkinglot[AST_MAX_CONTEXT] [static] |
Definition at line 140 of file chan_iax2.c.
int defaultsockfd = -1 [static] |
Definition at line 182 of file chan_iax2.c.
int delayreject = 0 [static] |
Definition at line 248 of file chan_iax2.c.
int global_max_trunk_mtu [static] |
Maximum MTU, 0 if not used
Definition at line 135 of file chan_iax2.c.
uint16_t global_maxcallno [static] |
Definition at line 752 of file chan_iax2.c.
Referenced by set_config(), and set_peercnt_limit().
uint16_t global_maxcallno_nonval [static] |
Total num of call numbers allowed to be allocated without calltoken validation
Definition at line 755 of file chan_iax2.c.
Referenced by get_unused_callno(), handle_cli_iax2_show_callno_limits(), and set_config().
int global_rtautoclear = 120 [static] |
Definition at line 301 of file chan_iax2.c.
struct ast_flags globalflags = { 0 } [static] |
Definition at line 251 of file chan_iax2.c.
int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static] |
Definition at line 229 of file chan_iax2.c.
int iax2_encryption = 0 [static] |
Definition at line 249 of file chan_iax2.c.
| int(* iax2_regfunk)(const char *username, int onoff) = NULL |
Referenced by __expire_registry(), reg_source_db(), and update_registry().
struct ast_switch iax2_switch [static] |
Definition at line 13200 of file chan_iax2.c.
struct ast_channel_tech iax2_tech [static] |
Definition at line 1063 of file chan_iax2.c.
struct ast_datastore_info iax2_variable_datastore_info [static] |
{
.type = "IAX2_VARIABLE",
.duplicate = iax2_dup_variable_datastore,
.destroy = iax2_free_variable_datastore,
}
Definition at line 1108 of file chan_iax2.c.
struct ao2_container* iax_peercallno_pvts [static] |
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.
Definition at line 925 of file chan_iax2.c.
struct ao2_container* iax_transfercallno_pvts [static] |
Another container of iax2_pvt structures.
* Active IAX2 pvt stucts used during transfering a call are stored here.
Definition at line 941 of file chan_iax2.c.
int iaxactivethreadcount = 0 [static] |
Definition at line 500 of file chan_iax2.c.
Referenced by __unload_module(), iax2_process_thread(), and iax2_process_thread_cleanup().
int iaxcompat = 0 [static] |
Definition at line 161 of file chan_iax2.c.
int iaxdebug = 0 [static] |
Definition at line 231 of file chan_iax2.c.
int iaxdefaultdpcache = 10 * 60 [static] |
Definition at line 164 of file chan_iax2.c.
int iaxdefaulttimeout = 5 [static] |
Definition at line 166 of file chan_iax2.c.
int iaxdynamicthreadcount = 0 [static] |
Definition at line 498 of file chan_iax2.c.
Referenced by find_idle_thread(), and iax2_process_thread().
int iaxdynamicthreadnum = 0 [static] |
Definition at line 499 of file chan_iax2.c.
Referenced by find_idle_thread().
int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static] |
Definition at line 497 of file chan_iax2.c.
Referenced by find_idle_thread(), and set_config().
Definition at line 13078 of file chan_iax2.c.
struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static] |
an array of iax2 pvt structures
The container for active chan_iax2_pvt structures is implemented as an array for extremely quick direct access to the correct pvt structure based on the local call number. The local call number is used as the index into the array where the associated pvt structure is stored.
Definition at line 914 of file chan_iax2.c.
ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static] |
chan_iax2_pvt structure locks
These locks are used when accessing a pvt structure in the iaxs array. The index used here is the same as used in the iaxs array. It is the local call number for the associated pvt struct.
Definition at line 934 of file chan_iax2.c.
int iaxthreadcount = DEFAULT_THREAD_COUNT [static] |
Definition at line 496 of file chan_iax2.c.
Referenced by handle_cli_iax2_show_threads(), set_config(), and start_network_thread().
int iaxtrunkdebug = 0 [static] |
Definition at line 233 of file chan_iax2.c.
struct ast_custom_function iaxvar_function [static] |
Definition at line 9197 of file chan_iax2.c.
struct io_context* io [static] |
Definition at line 226 of file chan_iax2.c.
int jittertargetextra = 40 [static] |
Definition at line 152 of file chan_iax2.c.
int lagrq_time = 10 [static] |
Definition at line 148 of file chan_iax2.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 142 of file chan_iax2.c.
int last_authmethod = 0 [static] |
Definition at line 162 of file chan_iax2.c.
const time_t MAX_CALLTOKEN_DELAY = 10 [static] |
Definition at line 720 of file chan_iax2.c.
int max_reg_expire [static] |
Definition at line 174 of file chan_iax2.c.
int max_retries = 4 [static] |
Definition at line 146 of file chan_iax2.c.
int maxauthreq = 3 [static] |
Definition at line 145 of file chan_iax2.c.
int maxjitterbuffer = 1000 [static] |
Definition at line 149 of file chan_iax2.c.
int maxjitterinterps = 10 [static] |
Definition at line 151 of file chan_iax2.c.
int maxnontrunkcall = 1 [static] |
Definition at line 1015 of file chan_iax2.c.
int maxtrunkcall = TRUNK_CALL_START [static] |
Definition at line 1014 of file chan_iax2.c.
int min_reg_expire [static] |
Definition at line 173 of file chan_iax2.c.
char mohinterpret[MAX_MUSICCLASS] [static] |
Definition at line 244 of file chan_iax2.c.
char mohsuggest[MAX_MUSICCLASS] [static] |
Definition at line 245 of file chan_iax2.c.
Referenced by check_peer_ok(), create_addr_from_peer(), and sip_alloc().
struct ast_netsock_list* netsock [static] |
Definition at line 180 of file chan_iax2.c.
pthread_t netthreadid = AST_PTHREADT_NULL [static] |
Definition at line 253 of file chan_iax2.c.
struct ast_netsock_list* outsock [static] |
used if sourceaddress specified and bindaddr == INADDR_ANY
Definition at line 181 of file chan_iax2.c.
char* papp = "IAX2Provision" [static] |
Definition at line 11082 of file chan_iax2.c.
char* pdescrip [static] |
" IAX2Provision([template]): Provisions the calling IAXy (assuming\n" "the calling entity is in fact an IAXy) with the given template or\n" "default if one is not specified. Returns -1 on error or 0 on success.\n"
Definition at line 11084 of file chan_iax2.c.
struct ao2_container* peercnts [static] |
Table containing peercnt objects for every ip address consuming a callno
Definition at line 740 of file chan_iax2.c.
Referenced by __unload_module(), handle_cli_iax2_show_callno_limits(), load_objects(), peercnt_add(), peercnt_modify(), peercnt_remove(), peercnt_remove_by_addr(), reload_config(), and sched_delay_remove().
struct ao2_container* peers [static] |
Definition at line 734 of file chan_iax2.c.
int ping_time = 21 [static] |
Definition at line 147 of file chan_iax2.c.
struct ast_codec_pref prefs [static] |
Definition at line 126 of file chan_iax2.c.
Referenced by ast_best_codec(), build_peer(), build_user(), check_access(), create_addr(), new_iax(), and set_config().
char* psyn = "Provision a calling IAXy with a given template" [static] |
Definition at line 11083 of file chan_iax2.c.
struct { ... } qos [static] |
Referenced by peer_set_srcaddr(), and set_config().
int randomcalltokendata [static] |
Definition at line 718 of file chan_iax2.c.
char regcontext[AST_MAX_CONTEXT] = "" [static] |
Definition at line 143 of file chan_iax2.c.
int resyncthreshold = 1000 [static] |
Definition at line 150 of file chan_iax2.c.
struct sched_context* sched [static] |
Definition at line 227 of file chan_iax2.c.
ast_cond_t sched_cond [static] |
Definition at line 256 of file chan_iax2.c.
ast_mutex_t sched_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 255 of file chan_iax2.c.
Referenced by __unload_module(), iax2_sched_add(), iax2_sched_replace(), iax2_transmit(), and sched_thread().
pthread_t schedthreadid = AST_PTHREADT_NULL [static] |
Definition at line 254 of file chan_iax2.c.
int srvlookup = 0 [static] |
Definition at line 176 of file chan_iax2.c.
Referenced by build_peer().
const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)" [static] |
Definition at line 128 of file chan_iax2.c.
int test_losspct = 0 [static] |
Definition at line 235 of file chan_iax2.c.
Definition at line 178 of file chan_iax2.c.
Referenced by find_timer(), process_dahdi(), pthread_timer_ack(), pthread_timer_close(), pthread_timer_destructor(), pthread_timer_disable_continuous(), pthread_timer_enable_continuous(), pthread_timer_get_event(), pthread_timer_hash(), pthread_timer_open(), pthread_timer_set_rate(), run_timer(), and timing_test().
| unsigned int tos |
Definition at line 169 of file chan_iax2.c.
uint16_t total_nonval_callno_used = 0 [static] |
Definition at line 757 of file chan_iax2.c.
Referenced by get_unused_callno(), handle_cli_iax2_show_callno_limits(), and replace_callno().
int trunk_maxmtu [static] |
Definition at line 136 of file chan_iax2.c.
int trunk_nmaxmtu [static] |
Trunk MTU statistics
Definition at line 136 of file chan_iax2.c.
int trunk_timed [static] |
Definition at line 136 of file chan_iax2.c.
int trunk_untimed [static] |
Definition at line 136 of file chan_iax2.c.
int trunkfreq = 20 [static] |
Definition at line 156 of file chan_iax2.c.
int trunkmaxsize = MAX_TRUNKDATA [static] |
Definition at line 157 of file chan_iax2.c.
struct ao2_container* users [static] |
Definition at line 737 of file chan_iax2.c.
1.6.1