#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/translate.h"
#include "asterisk/md5.h"
#include "asterisk/cdr.h"
#include "asterisk/crypto.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/app.h"
#include "asterisk/astdb.h"
#include "asterisk/musiconhold.h"
#include "asterisk/features.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/localtime.h"
#include "asterisk/aes.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/netsock.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
#include "asterisk/astobj2.h"
#include "iax2.h"
#include "iax2-parser.h"
#include "iax2-provision.h"
#include "jitterbuf.h"
Go to the source code of this file.
Data Structures | |
| struct | ast_firmware_list |
| struct | ast_iax2_queue |
| struct | chan_iax2_pvt |
| struct | create_addr_info |
| struct | dpreq_data |
| 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 | parsed_dial_string |
Defines | |
| #define | CACHE_FLAG_CANEXIST (1 << 2) |
| #define | CACHE_FLAG_EXISTS (1 << 0) |
| #define | CACHE_FLAG_MATCHMORE (1 << 7) |
| #define | CACHE_FLAG_NONEXISTENT (1 << 1) |
| #define | CACHE_FLAG_PENDING (1 << 3) |
| #define | CACHE_FLAG_TIMEOUT (1 << 4) |
| #define | CACHE_FLAG_TRANSMITTED (1 << 5) |
| #define | CACHE_FLAG_UNKNOWN (1 << 6) |
| #define | CALLNO_TO_PTR(a) ((void *)(unsigned long)(a)) |
| #define | DEBUG_SCHED_MULTITHREAD |
| #define | DEBUG_SUPPORT |
| #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\n" |
| #define | FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
| #define | FORMAT "%-15.15s %-15d %-15d\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\n" |
| #define | FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
| #define | FORMAT2 "%-15.15s %-15.15s %-15.15s\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_CAPABILITY_FULLBANDWIDTH 0xFFFF |
| #define | IAX_CAPABILITY_LOWBANDWIDTH |
| #define | IAX_CAPABILITY_LOWFREE |
| #define | IAX_CAPABILITY_MEDBANDWIDTH |
| #define | IAX_IOSTATE_IDLE 0 |
| #define | IAX_IOSTATE_PROCESSING 2 |
| #define | IAX_IOSTATE_READY 1 |
| #define | IAX_IOSTATE_SCHEDREADY 3 |
| #define | IAX_TYPE_DYNAMIC 2 |
| #define | IAX_TYPE_POOL 1 |
| #define | IPTOS_MINCOST 0x02 |
| #define | MAX_JITTER_BUFFER 50 |
| #define | MAX_PEER_BUCKETS 1 |
| #define | MAX_RETRY_TIME 10000 |
| #define | MAX_TIMESTAMP_SKEW 160 |
| #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 | NEW_ALLOW 1 |
| #define | NEW_FORCE 2 |
| #define | NEW_PREVENT 0 |
| #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 | { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2), IAX_STATE_UNCHANGED = (1 << 3) } |
| enum | { 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 | 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 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 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 | AST_LIST_HEAD_STATIC (dynamic_list, iax2_thread) |
| static | AST_LIST_HEAD_STATIC (active_list, iax2_thread) |
| static | AST_LIST_HEAD_STATIC (idle_list, iax2_thread) |
| static | AST_LIST_HEAD_STATIC (registrations, iax2_registry) |
| AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Inter Asterisk eXchange (Ver 2)",.load=load_module,.unload=unload_module,.reload=reload,) | |
| AST_MUTEX_DEFINE_STATIC (dpcache_lock) | |
| AST_MUTEX_DEFINE_STATIC (tpeerlock) | |
| AST_MUTEX_DEFINE_STATIC (sched_lock) | |
| 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 struct iax2_context * | build_context (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 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 *tv) |
| 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_show_peer (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 | decode_frame (aes_decrypt_ctx *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 (aes_encrypt_ctx *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 unsigned int | fix_peerts (struct timeval *tv, int callno, unsigned int ts) |
| static void | free_context (struct iax2_context *con) |
| static int | function_iaxpeer (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
| static int | get_auth_methods (char *value) |
| static int | get_encrypt_methods (const char *s) |
| static int | get_from_jb (const void *p) |
| 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 | iax2_answer (struct ast_channel *c) |
| 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_debug (int fd, int argc, char *argv[]) |
| static int | iax2_do_jb_debug (int fd, int argc, char *argv[]) |
| static int | iax2_do_register (struct iax2_registry *reg) |
| static int | iax2_do_register_s (const void *data) |
| static int | iax2_do_trunk_debug (int fd, int argc, char *argv[]) |
| static void | iax2_dprequest (struct iax2_dpcache *dp, int callno) |
| 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 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_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_no_debug (int fd, int argc, char *argv[]) |
| static int | iax2_no_jb_debug (int fd, int argc, char *argv[]) |
| static int | iax2_no_trunk_debug (int fd, int argc, char *argv[]) |
| 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_prov_cmd (int fd, int argc, char *argv[]) |
| static char * | iax2_prov_complete_template_3rd (const char *line, const char *word, int pos, int state) |
| static int | iax2_provision (struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force) |
| static int | iax2_prune_realtime (int fd, int argc, char *argv[]) |
| 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 (char *value, int lineno) |
| static int | iax2_reload (int fd, int argc, char *argv[]) |
| 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_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_show_cache (int fd, int argc, char *argv[]) |
| static int | iax2_show_channels (int fd, int argc, char *argv[]) |
| static int | iax2_show_firmware (int fd, int argc, char *argv[]) |
| static int | iax2_show_netstats (int fd, int argc, char *argv[]) |
| static int | iax2_show_peer (int fd, int argc, char *argv[]) |
| Show one peer in detail. | |
| static int | iax2_show_peers (int fd, int argc, char *argv[]) |
| static int | iax2_show_registry (int fd, int argc, char *argv[]) |
| static int | iax2_show_stats (int fd, int argc, char *argv[]) |
| static int | iax2_show_threads (int fd, int argc, char *argv[]) |
| static int | iax2_show_users (int fd, int argc, char *argv[]) |
| static int | iax2_start_transfer (unsigned short callno0, unsigned short callno1, int mediaonly) |
| static int | iax2_test_losspct (int fd, int argc, char *argv[]) |
| 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 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 void | lock_both (unsigned short callno0, unsigned short callno1) |
| 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_peers (struct mansession *s, const struct message *m) |
| static int | match (struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, struct chan_iax2_pvt *cur, int check_dcallno) |
| static void | memcpy_decrypt (unsigned char *dst, const unsigned char *src, int len, aes_decrypt_ctx *dcx) |
| static void | memcpy_encrypt (unsigned char *dst, const unsigned char *src, int len, aes_encrypt_ctx *ecx) |
| static void | merge_encryption (struct chan_iax2_pvt *p, unsigned int enc) |
| 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 void | poke_all_peers (void) |
| 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 | save_rr (struct iax_frame *fr, struct iax_ies *ies) |
| static void * | sched_thread (void *ignore) |
| static int | schedule_delivery (struct iax_frame *fr, int updatehistory, int fromtrunk, unsigned int *tsout) |
| static int | send_apathetic_reply (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int command, int ts, unsigned char seqno) |
| 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 (char *config_file, int reload) |
| Load configuration. | |
| static void | set_config_destroy (void) |
| static void | set_timing (void) |
| static void | signal_condition (ast_mutex_t *lock, ast_cond_t *cond) |
| static int | socket_process (struct iax2_thread *thread) |
| 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 int | timing_read (int *id, int fd, short events, void *cbdata) |
| 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) |
Variables | |
| static char | accountcode [AST_MAX_ACCOUNT_CODE] |
| static int | adsi = 0 |
| static int | amaflags = 0 |
| static int | authdebug = 1 |
| static int | autokill = 0 |
| static struct ast_cli_entry | cli_iax2 [] |
| static struct ast_cli_entry | cli_iax2_jb_debug_deprecated |
| static struct ast_cli_entry | cli_iax2_no_debug_deprecated |
| static struct ast_cli_entry | cli_iax2_no_jb_debug_deprecated |
| static struct ast_cli_entry | cli_iax2_no_trunk_debug_deprecated |
| static struct ast_cli_entry | cli_iax2_trunk_debug_deprecated |
| static char | context [80] = "default" |
| static char | debug_jb_usage [] |
| static char | debug_trunk_usage [] |
| static char | debug_usage [] |
| static int | defaultsockfd = -1 |
| static int | delayreject = 0 |
| static struct iax2_dpcache * | dpcache |
| static int | global_rtautoclear = 120 |
| static struct ast_flags | globalflags = { 0 } |
| static int | iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH |
| static int | iax2_encryption = 0 |
| enum { ... } | iax2_flags |
| int(* | iax2_regfunk )(const char *username, int onoff) = NULL |
| static char | iax2_reload_usage [] |
| enum { ... } | iax2_state |
| static struct ast_switch | iax2_switch |
| static struct ast_channel_tech | iax2_tech |
| static char | iax2_test_losspct_usage [] |
| static struct ao2_container * | iax_peercallno_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 | iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT |
| struct ast_custom_function | iaxpeer_function |
| static struct ast_iax2_queue | iaxq |
| static struct chan_iax2_pvt * | iaxs [IAX_MAX_CALLS] |
| static ast_mutex_t | iaxsl [ARRAY_LEN(iaxs)] |
| static int | iaxthreadcount = DEFAULT_THREAD_COUNT |
| static int | iaxtrunkdebug = 0 |
| static struct io_context * | io |
| static int | lagrq_time = 10 |
| static char | language [MAX_LANGUAGE] = "" |
| static struct timeval | lastused [ARRAY_LEN(iaxs)] |
| 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 char | no_debug_jb_usage [] |
| static char | no_debug_trunk_usage [] |
| static char | no_debug_usage [] |
| static struct ast_netsock_list * | outsock |
| static char * | papp = "IAX2Provision" |
| static char * | pdescrip |
| static struct ao2_container * | peers |
| static int | ping_time = 21 |
| static struct ast_codec_pref | prefs |
| static char | prune_realtime_usage [] |
| static char * | psyn = "Provision a calling IAXy with a given template" |
| static char | regcontext [AST_MAX_CONTEXT] = "" |
| static int | resyncthreshold = 1000 |
| static struct sched_context * | sched |
| static ast_cond_t | sched_cond |
| static pthread_t | schedthreadid = AST_PTHREADT_NULL |
| static char | show_cache_usage [] |
| static char | show_channels_usage [] |
| static char | show_firmware_usage [] |
| static char | show_netstats_usage [] |
| static char | show_peer_usage [] |
| static char | show_peers_usage [] |
| static char | show_prov_usage [] |
| static char | show_reg_usage [] |
| static char | show_stats_usage [] |
| static char | show_threads_usage [] |
| static char | show_users_usage [] |
| static const char | tdesc [] = "Inter Asterisk eXchange Driver (Ver 2)" |
| static int | test_losspct = 0 |
| static int | timingfd = -1 |
| static unsigned int | tos = 0 |
| static struct iax2_trunk_peer * | tpeers |
| static int | trunkfreq = 20 |
| static struct ao2_container * | users |
| static struct ast_firmware_list | waresl |
Definition in file chan_iax2.c.
| #define CACHE_FLAG_CANEXIST (1 << 2) |
Extension can exist
Definition at line 667 of file chan_iax2.c.
Referenced by complete_dpreply(), iax2_canmatch(), and iax2_show_cache().
| #define CACHE_FLAG_EXISTS (1 << 0) |
Extension exists
Definition at line 663 of file chan_iax2.c.
Referenced by complete_dpreply(), iax2_exec(), iax2_exists(), and iax2_show_cache().
| #define CACHE_FLAG_MATCHMORE (1 << 7) |
Matchmore
Definition at line 677 of file chan_iax2.c.
Referenced by complete_dpreply(), iax2_matchmore(), and iax2_show_cache().
| #define CACHE_FLAG_NONEXISTENT (1 << 1) |
Extension is nonexistent
Definition at line 665 of file chan_iax2.c.
Referenced by complete_dpreply(), and iax2_show_cache().
| #define CACHE_FLAG_PENDING (1 << 3) |
Waiting to hear back response
Definition at line 669 of file chan_iax2.c.
Referenced by complete_dpreply(), find_cache(), and iax2_show_cache().
| #define CACHE_FLAG_TIMEOUT (1 << 4) |
Timed out
Definition at line 671 of file chan_iax2.c.
Referenced by find_cache(), and iax2_show_cache().
| #define CACHE_FLAG_TRANSMITTED (1 << 5) |
Request transmitted
Definition at line 673 of file chan_iax2.c.
Referenced by iax2_dprequest(), iax2_show_cache(), and socket_process().
| #define CACHE_FLAG_UNKNOWN (1 << 6) |
Timeout
Definition at line 675 of file chan_iax2.c.
Referenced by complete_dpreply(), and iax2_show_cache().
| #define CALLNO_TO_PTR | ( | a | ) | ((void *)(unsigned long)(a)) |
Definition at line 126 of file chan_iax2.c.
Referenced by ast_iax2_new(), iax2_call(), and update_jbsched().
| #define DEBUG_SCHED_MULTITHREAD |
Definition at line 114 of file chan_iax2.c.
| #define DEBUG_SUPPORT |
Definition at line 134 of file chan_iax2.c.
| #define DEFAULT_DROP 3 |
Definition at line 132 of file chan_iax2.c.
| #define DEFAULT_FREQ_NOTOK 10 * 1000 |
Definition at line 199 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 198 of file chan_iax2.c.
Referenced by build_peer(), and handle_response_peerpoke().
| #define DEFAULT_MAX_THREAD_COUNT 100 |
Definition at line 129 of file chan_iax2.c.
| #define DEFAULT_MAXMS 2000 |
Definition at line 197 of file chan_iax2.c.
| #define DEFAULT_RETRY_TIME 1000 |
| #define DEFAULT_THREAD_COUNT 10 |
Definition at line 128 of file chan_iax2.c.
| #define DEFAULT_TRUNKDATA 640 * 10 |
40ms, uncompressed linear * 10 channels
Definition at line 442 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\n" |
| #define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
| #define FORMAT "%-15.15s %-15d %-15d\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\n" |
| #define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
| #define FORMAT2 "%-15.15s %-15.15s %-15.15s\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 139 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)) |
| #define IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF |
Definition at line 180 of file chan_iax2.c.
Referenced by cache_get_callno_locked(), and set_config().
| #define IAX_CAPABILITY_LOWBANDWIDTH |
Value:
(IAX_CAPABILITY_MEDBANDWIDTH & \ ~AST_FORMAT_G726 & \ ~AST_FORMAT_G726_AAL2 & \ ~AST_FORMAT_ADPCM)
Definition at line 188 of file chan_iax2.c.
Referenced by set_config().
| #define IAX_CAPABILITY_LOWFREE |
Value:
Definition at line 193 of file chan_iax2.c.
| #define IAX_CAPABILITY_MEDBANDWIDTH |
Value:
(IAX_CAPABILITY_FULLBANDWIDTH & \ ~AST_FORMAT_SLINEAR & \ ~AST_FORMAT_ULAW & \ ~AST_FORMAT_ALAW & \ ~AST_FORMAT_G722)
Definition at line 182 of file chan_iax2.c.
Referenced by set_config().
| #define IAX_IOSTATE_IDLE 0 |
| #define IAX_IOSTATE_PROCESSING 2 |
| #define IAX_IOSTATE_READY 1 |
| #define IAX_IOSTATE_SCHEDREADY 3 |
Definition at line 701 of file chan_iax2.c.
Referenced by __schedule_action(), and iax2_process_thread().
| #define IAX_TYPE_DYNAMIC 2 |
Definition at line 704 of file chan_iax2.c.
Referenced by find_idle_thread(), iax2_process_thread(), iax2_show_threads(), and insert_idle_thread().
| #define IAX_TYPE_POOL 1 |
| #define IPTOS_MINCOST 0x02 |
Definition at line 117 of file chan_iax2.c.
| #define MAX_JITTER_BUFFER 50 |
Definition at line 439 of file chan_iax2.c.
| #define MAX_PEER_BUCKETS 1 |
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 649 of file chan_iax2.c.
Referenced by load_module(), and set_config().
| #define MAX_RETRY_TIME 10000 |
| #define MAX_TIMESTAMP_SKEW 160 |
maximum difference between actual and predicted ts for sending
Definition at line 445 of file chan_iax2.c.
| #define MAX_TRUNKDATA 640 * 200 |
40ms, uncompressed linear * 200 channels
Definition at line 443 of file chan_iax2.c.
Referenced by iax2_trunk_queue(), and timing_read().
| #define MAX_USER_BUCKETS MAX_PEER_BUCKETS |
| #define MEMORY_SIZE 100 |
Definition at line 131 of file chan_iax2.c.
| #define MIN_JITTER_BUFFER 10 |
Definition at line 440 of file chan_iax2.c.
| #define MIN_RETRY_TIME 100 |
| #define MIN_REUSE_TIME 60 |
| #define NEW_ALLOW 1 |
| #define NEW_FORCE 2 |
Definition at line 1436 of file chan_iax2.c.
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_poke_peer(), iax2_provision(), and iax2_request().
| #define NEW_PREVENT 0 |
| #define PTR_TO_CALLNO | ( | a | ) | ((unsigned short)(unsigned long)(a)) |
Definition at line 125 of file chan_iax2.c.
Referenced by __auto_congest(), __get_from_jb(), 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(), and iax2_write().
| #define SCHED_MULTITHREADED |
Definition at line 110 of file chan_iax2.c.
Definition at line 989 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 831 of file chan_iax2.c.
Referenced by __find_callno(), make_trunk(), update_max_nontrunk(), and update_max_trunk().
| #define TS_GAP_FOR_JB_RESYNC 5000 |
Definition at line 448 of file chan_iax2.c.
| anonymous enum |
Definition at line 233 of file chan_iax2.c.
00233 { 00234 IAX_STATE_STARTED = (1 << 0), 00235 IAX_STATE_AUTHENTICATED = (1 << 1), 00236 IAX_STATE_TBD = (1 << 2), 00237 IAX_STATE_UNCHANGED = (1 << 3), 00238 } iax2_state;
| anonymous enum |
Definition at line 245 of file chan_iax2.c.
00245 { 00246 IAX_HASCALLERID = (1 << 0), /*!< CallerID has been specified */ 00247 IAX_DELME = (1 << 1), /*!< Needs to be deleted */ 00248 IAX_TEMPONLY = (1 << 2), /*!< Temporary (realtime) */ 00249 IAX_TRUNK = (1 << 3), /*!< Treat as a trunk */ 00250 IAX_NOTRANSFER = (1 << 4), /*!< Don't native bridge */ 00251 IAX_USEJITTERBUF = (1 << 5), /*!< Use jitter buffer */ 00252 IAX_DYNAMIC = (1 << 6), /*!< dynamic peer */ 00253 IAX_SENDANI = (1 << 7), /*!< Send ANI along with CallerID */ 00254 /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */ 00255 IAX_ALREADYGONE = (1 << 9), /*!< Already disconnected */ 00256 IAX_PROVISION = (1 << 10), /*!< This is a provisioning request */ 00257 IAX_QUELCH = (1 << 11), /*!< Whether or not we quelch audio */ 00258 IAX_ENCRYPTED = (1 << 12), /*!< Whether we should assume encrypted tx/rx */ 00259 IAX_KEYPOPULATED = (1 << 13), /*!< Whether we have a key populated */ 00260 IAX_CODEC_USER_FIRST = (1 << 14), /*!< are we willing to let the other guy choose the codec? */ 00261 IAX_CODEC_NOPREFS = (1 << 15), /*!< Force old behaviour by turning off prefs */ 00262 IAX_CODEC_NOCAP = (1 << 16), /*!< only consider requested format and ignore capabilities*/ 00263 IAX_RTCACHEFRIENDS = (1 << 17), /*!< let realtime stay till your reload */ 00264 IAX_RTUPDATE = (1 << 18), /*!< Send a realtime update */ 00265 IAX_RTAUTOCLEAR = (1 << 19), /*!< erase me on expire */ 00266 IAX_FORCEJITTERBUF = (1 << 20), /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */ 00267 IAX_RTIGNOREREGEXPIRE = (1 << 21), /*!< When using realtime, ignore registration expiration */ 00268 IAX_TRUNKTIMESTAMPS = (1 << 22), /*!< Send trunk timestamps */ 00269 IAX_TRANSFERMEDIA = (1 << 23), /*!< When doing IAX2 transfers, transfer media only */ 00270 IAX_MAXAUTHREQ = (1 << 24), /*!< Maximum outstanding AUTHREQ restriction is in place */ 00271 IAX_DELAYPBXSTART = (1 << 25), /*!< Don't start a PBX on the channel until the peer sends us a 00272 response, so that we've achieved a three-way handshake with 00273 them before sending voice or anything else*/ 00274 IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */ 00275 } iax2_flags;
| 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 394 of file chan_iax2.c.
00394 { 00395 REG_STATE_UNREGISTERED = 0, 00396 REG_STATE_REGSENT, 00397 REG_STATE_AUTHSENT, 00398 REG_STATE_REGISTERED, 00399 REG_STATE_REJECTED, 00400 REG_STATE_TIMEOUT, 00401 REG_STATE_NOAUTH 00402 };
| 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 404 of file chan_iax2.c.
00404 { 00405 TRANSFER_NONE = 0, 00406 TRANSFER_BEGIN, 00407 TRANSFER_READY, 00408 TRANSFER_RELEASED, 00409 TRANSFER_PASSTHROUGH, 00410 TRANSFER_MBEGIN, 00411 TRANSFER_MREADY, 00412 TRANSFER_MRELEASED, 00413 TRANSFER_MPASSTHROUGH, 00414 TRANSFER_MEDIA, 00415 TRANSFER_MEDIAPASS 00416 };
| static void __attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 2166 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, iax2_registry::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, iaxq, iaxs, iaxsl, 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().
02167 { 02168 /* Attempt to transmit the frame to the remote peer... 02169 Called without iaxsl held. */ 02170 struct iax_frame *f = (struct iax_frame *)data; 02171 int freeme=0; 02172 int callno = f->callno; 02173 /* Make sure this call is still active */ 02174 if (callno) 02175 ast_mutex_lock(&iaxsl[callno]); 02176 if (callno && iaxs[callno]) { 02177 if ((f->retries < 0) /* Already ACK'd */ || 02178 (f->retries >= max_retries) /* Too many attempts */) { 02179 /* Record an error if we've transmitted too many times */ 02180 if (f->retries >= max_retries) { 02181 if (f->transfer) { 02182 /* Transfer timeout */ 02183 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 02184 } else if (f->final) { 02185 if (f->final) 02186 iax2_destroy(callno); 02187 } else { 02188 if (iaxs[callno]->owner) 02189 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); 02190 iaxs[callno]->error = ETIMEDOUT; 02191 if (iaxs[callno]->owner) { 02192 struct ast_frame fr = { 0, }; 02193 /* Hangup the fd */ 02194 fr.frametype = AST_FRAME_CONTROL; 02195 fr.subclass = AST_CONTROL_HANGUP; 02196 iax2_queue_frame(callno, &fr); // XXX 02197 /* Remember, owner could disappear */ 02198 if (iaxs[callno] && iaxs[callno]->owner) 02199 iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 02200 } else { 02201 if (iaxs[callno]->reg) { 02202 memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us)); 02203 iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT; 02204 iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE; 02205 } 02206 iax2_destroy(callno); 02207 } 02208 } 02209 02210 } 02211 freeme++; 02212 } else { 02213 /* Update it if it needs it */ 02214 update_packet(f); 02215 /* Attempt transmission */ 02216 send_packet(f); 02217 f->retries++; 02218 /* Try again later after 10 times as long */ 02219 f->retrytime *= 10; 02220 if (f->retrytime > MAX_RETRY_TIME) 02221 f->retrytime = MAX_RETRY_TIME; 02222 /* Transfer messages max out at one second */ 02223 if (f->transfer && (f->retrytime > 1000)) 02224 f->retrytime = 1000; 02225 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 02226 } 02227 } else { 02228 /* Make sure it gets freed */ 02229 f->retries = -1; 02230 freeme++; 02231 } 02232 if (callno) 02233 ast_mutex_unlock(&iaxsl[callno]); 02234 /* Do not try again */ 02235 if (freeme) { 02236 /* Don't attempt delivery, just remove it from the queue */ 02237 AST_LIST_LOCK(&iaxq.queue); 02238 AST_LIST_REMOVE(&iaxq.queue, f, list); 02239 iaxq.count--; 02240 AST_LIST_UNLOCK(&iaxq.queue); 02241 f->retrans = -1; 02242 /* Free the IAX frame */ 02243 iax2_frame_free(f); 02244 } 02245 }
| static void __auth_reject | ( | const void * | nothing | ) | [static] |
Definition at line 6380 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, iax2_registry::callno, IAX_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, iax_ie_data::pos, and send_command_final().
Referenced by auth_reject().
06381 { 06382 /* Called from IAX thread only, without iaxs lock */ 06383 int callno = (int)(long)(nothing); 06384 struct iax_ie_data ied; 06385 ast_mutex_lock(&iaxsl[callno]); 06386 if (iaxs[callno]) { 06387 memset(&ied, 0, sizeof(ied)); 06388 if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) { 06389 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused"); 06390 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED); 06391 } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) { 06392 iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found"); 06393 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 06394 } 06395 send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1); 06396 } 06397 ast_mutex_unlock(&iaxsl[callno]); 06398 }
| static void __auto_congest | ( | const void * | nothing | ) | [static] |
Definition at line 3121 of file chan_iax2.c.
References AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_queue_frame(), iaxs, iaxsl, chan_iax2_pvt::initid, LOG_NOTICE, and PTR_TO_CALLNO.
Referenced by auto_congest().
03122 { 03123 int callno = PTR_TO_CALLNO(nothing); 03124 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION }; 03125 ast_mutex_lock(&iaxsl[callno]); 03126 if (iaxs[callno]) { 03127 iaxs[callno]->initid = -1; 03128 iax2_queue_frame(callno, &f); 03129 ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n"); 03130 } 03131 ast_mutex_unlock(&iaxsl[callno]); 03132 }
| static void __auto_hangup | ( | const void * | nothing | ) | [static] |
Definition at line 6429 of file chan_iax2.c.
References AST_CAUSE_NO_USER_RESPONSE, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax_ie_data::buf, iax2_registry::callno, IAX_COMMAND_HANGUP, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, iax_ie_data::pos, and send_command_final().
Referenced by auto_hangup().
06430 { 06431 /* Called from IAX thread only, without iaxs lock */ 06432 int callno = (int)(long)(nothing); 06433 struct iax_ie_data ied; 06434 ast_mutex_lock(&iaxsl[callno]); 06435 if (iaxs[callno]) { 06436 memset(&ied, 0, sizeof(ied)); 06437 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout"); 06438 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE); 06439 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 06440 } 06441 ast_mutex_unlock(&iaxsl[callno]); 06442 }
| static int __do_deliver | ( | void * | data | ) | [static] |
IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] was valid before calling it, it may no longer be valid after calling it. This function calls iax2_queue_frame(), which may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.
Definition at line 2022 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, iaxs, and iax_frame::retrans.
Referenced by __get_from_jb(), and schedule_delivery().
02023 { 02024 /* Just deliver the packet by using queueing. This is called by 02025 the IAX thread with the iaxsl lock held. */ 02026 struct iax_frame *fr = data; 02027 fr->retrans = -1; 02028 ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO); 02029 if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE)) 02030 iax2_queue_frame(fr->callno, &fr->af); 02031 /* Free our iax frame */ 02032 iax2_frame_free(fr); 02033 /* And don't run again */ 02034 return 0; 02035 }
| static void __expire_registry | ( | const void * | data | ) | [static] |
Definition at line 6068 of file chan_iax2.c.
References iax2_peer::addr, ast_db_del(), ast_device_state_changed(), ast_log(), ast_test_flag, EVENT_FLAG_SYSTEM, iax2_peer::expire, iax2_peer::expiry, iax2_regfunk, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, LOG_DEBUG, manager_event(), option_debug, peer_unref(), realtime_update_peer(), register_peer_exten(), and unlink_peer().
Referenced by expire_registry().
06069 { 06070 struct iax2_peer *peer = (struct iax2_peer *) data; 06071 06072 if (!peer) 06073 return; 06074 06075 peer->expire = -1; 06076 06077 if (option_debug) 06078 ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name); 06079 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) 06080 realtime_update_peer(peer->name, &peer->addr, 0); 06081 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 06082 /* Reset the address */ 06083 memset(&peer->addr, 0, sizeof(peer->addr)); 06084 /* Reset expiry value */ 06085 peer->expiry = min_reg_expire; 06086 if (!ast_test_flag(peer, IAX_TEMPONLY)) 06087 ast_db_del("IAX/Registry", peer->name); 06088 register_peer_exten(peer, 0); 06089 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 06090 if (iax2_regfunk) 06091 iax2_regfunk(peer->name, 0); 06092 06093 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) 06094 unlink_peer(peer); 06095 06096 peer_unref(peer); 06097 }
| 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 1521 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::amaflags, ao2_find(), ao2_ref(), ast_copy_flags, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_string_field_set, chan_iax2_pvt::callno, DEFAULT_RETRY_TIME, chan_iax2_pvt::expiry, iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, iax_peercallno_pvts, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, match(), maxnontrunkcall, maxtrunkcall, MIN_REUSE_TIME, NEW_ALLOW, new_iax(), option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, chan_iax2_pvt::pingtime, send_lagrq(), send_ping(), chan_iax2_pvt::sockfd, store_by_peercallno(), TRUNK_CALL_START, and update_max_nontrunk().
Referenced by find_callno(), and find_callno_locked().
01522 { 01523 int res = 0; 01524 int x; 01525 struct timeval now; 01526 char host[80]; 01527 01528 if (new <= NEW_ALLOW) { 01529 if (callno) { 01530 struct chan_iax2_pvt *pvt; 01531 struct chan_iax2_pvt tmp_pvt = { 01532 .callno = dcallno, 01533 .peercallno = callno, 01534 /* hack!! */ 01535 .frames_received = check_dcallno, 01536 }; 01537 01538 memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr)); 01539 01540 if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) { 01541 if (return_locked) { 01542 ast_mutex_lock(&iaxsl[pvt->callno]); 01543 } 01544 res = pvt->callno; 01545 ao2_ref(pvt, -1); 01546 pvt = NULL; 01547 return res; 01548 } 01549 } 01550 01551 /* Look for an existing connection first */ 01552 for (x = 1; !res && x < maxnontrunkcall; x++) { 01553 ast_mutex_lock(&iaxsl[x]); 01554 if (iaxs[x]) { 01555 /* Look for an exact match */ 01556 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 01557 res = x; 01558 } 01559 } 01560 if (!res || !return_locked) 01561 ast_mutex_unlock(&iaxsl[x]); 01562 } 01563 for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) { 01564 ast_mutex_lock(&iaxsl[x]); 01565 if (iaxs[x]) { 01566 /* Look for an exact match */ 01567 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 01568 res = x; 01569 } 01570 } 01571 if (!res || !return_locked) 01572 ast_mutex_unlock(&iaxsl[x]); 01573 } 01574 } 01575 if (!res && (new >= NEW_ALLOW)) { 01576 int start, found = 0; 01577 01578 /* It may seem odd that we look through the peer list for a name for 01579 * this *incoming* call. Well, it is weird. However, users don't 01580 * have an IP address/port number that we can match against. So, 01581 * this is just checking for a peer that has that IP/port and 01582 * assuming that we have a user of the same name. This isn't always 01583 * correct, but it will be changed if needed after authentication. */ 01584 if (!iax2_getpeername(*sin, host, sizeof(host))) 01585 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 01586 01587 now = ast_tvnow(); 01588 start = 2 + (ast_random() % (TRUNK_CALL_START - 1)); 01589 for (x = start; 1; x++) { 01590 if (x == TRUNK_CALL_START) { 01591 x = 1; 01592 continue; 01593 } 01594 01595 /* Find first unused call number that hasn't been used in a while */ 01596 ast_mutex_lock(&iaxsl[x]); 01597 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01598 found = 1; 01599 break; 01600 } 01601 ast_mutex_unlock(&iaxsl[x]); 01602 01603 if (x == start - 1) { 01604 break; 01605 } 01606 } 01607 /* We've still got lock held if we found a spot */ 01608 if (x == start - 1 && !found) { 01609 ast_log(LOG_WARNING, "No more space\n"); 01610 return 0; 01611 } 01612 iaxs[x] = new_iax(sin, host); 01613 update_max_nontrunk(); 01614 if (iaxs[x]) { 01615 if (option_debug && iaxdebug) 01616 ast_log(LOG_DEBUG, "Creating new call structure %d\n", x); 01617 iaxs[x]->sockfd = sockfd; 01618 iaxs[x]->addr.sin_port = sin->sin_port; 01619 iaxs[x]->addr.sin_family = sin->sin_family; 01620 iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr; 01621 iaxs[x]->peercallno = callno; 01622 iaxs[x]->callno = x; 01623 iaxs[x]->pingtime = DEFAULT_RETRY_TIME; 01624 iaxs[x]->expiry = min_reg_expire; 01625 iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 01626 iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 01627 iaxs[x]->amaflags = amaflags; 01628 ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 01629 01630 ast_string_field_set(iaxs[x], accountcode, accountcode); 01631 ast_string_field_set(iaxs[x], mohinterpret, mohinterpret); 01632 ast_string_field_set(iaxs[x], mohsuggest, mohsuggest); 01633 01634 if (iaxs[x]->peercallno) { 01635 store_by_peercallno(iaxs[x]); 01636 } 01637 } else { 01638 ast_log(LOG_WARNING, "Out of resources\n"); 01639 ast_mutex_unlock(&iaxsl[x]); 01640 return 0; 01641 } 01642 if (!return_locked) 01643 ast_mutex_unlock(&iaxsl[x]); 01644 res = x; 01645 } 01646 return res; 01647 }
| static void __get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 2563 of file chan_iax2.c.
References __do_deliver(), ast_codec_interp_len(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_tvadd(), iax2_registry::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, iaxs, iaxsl, 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, 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().
02564 { 02565 int callno = PTR_TO_CALLNO(p); 02566 struct chan_iax2_pvt *pvt = NULL; 02567 struct iax_frame *fr; 02568 jb_frame frame; 02569 int ret; 02570 long now; 02571 long next; 02572 struct timeval tv; 02573 02574 /* Make sure we have a valid private structure before going on */ 02575 ast_mutex_lock(&iaxsl[callno]); 02576 pvt = iaxs[callno]; 02577 if (!pvt) { 02578 /* No go! */ 02579 ast_mutex_unlock(&iaxsl[callno]); 02580 return; 02581 } 02582 02583 pvt->jbid = -1; 02584 02585 gettimeofday(&tv,NULL); 02586 /* round up a millisecond since ast_sched_runq does; */ 02587 /* prevents us from spinning while waiting for our now */ 02588 /* to catch up with runq's now */ 02589 tv.tv_usec += 1000; 02590 02591 now = ast_tvdiff_ms(tv, pvt->rxcore); 02592 02593 if(now >= (next = jb_next(pvt->jb))) { 02594 ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat)); 02595 switch(ret) { 02596 case JB_OK: 02597 fr = frame.data; 02598 __do_deliver(fr); 02599 /* __do_deliver() can cause the call to disappear */ 02600 pvt = iaxs[callno]; 02601 break; 02602 case JB_INTERP: 02603 { 02604 struct ast_frame af = { 0, }; 02605 02606 /* create an interpolation frame */ 02607 af.frametype = AST_FRAME_VOICE; 02608 af.subclass = pvt->voiceformat; 02609 af.samples = frame.ms * 8; 02610 af.src = "IAX2 JB interpolation"; 02611 af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000)); 02612 af.offset = AST_FRIENDLY_OFFSET; 02613 02614 /* queue the frame: For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame, 02615 * which we'd need to malloc, and then it would free it. That seems like a drag */ 02616 if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) { 02617 iax2_queue_frame(callno, &af); 02618 /* iax2_queue_frame() could cause the call to disappear */ 02619 pvt = iaxs[callno]; 02620 } 02621 } 02622 break; 02623 case JB_DROP: 02624 iax2_frame_free(frame.data); 02625 break; 02626 case JB_NOFRAME: 02627 case JB_EMPTY: 02628 /* do nothing */ 02629 break; 02630 default: 02631 /* shouldn't happen */ 02632 break; 02633 } 02634 } 02635 if (pvt) 02636 update_jbsched(pvt); 02637 ast_mutex_unlock(&iaxsl[callno]); 02638 }
| static void __iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 5761 of file chan_iax2.c.
References iax2_registry::expire, and iax2_do_register().
Referenced by iax2_do_register_s().
05762 { 05763 struct iax2_registry *reg = (struct iax2_registry *)data; 05764 reg->expire = -1; 05765 iax2_do_register(reg); 05766 }
| static void __iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 8862 of file chan_iax2.c.
References ast_device_state_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_peer::callno, iax2_registry::callno, EVENT_FLAG_SYSTEM, iax2_destroy(), iax2_poke_peer_s(), iax2_sched_add(), iaxsl, iax2_peer::lastms, LOG_NOTICE, manager_event(), peer_ref(), peer_unref(), iax2_peer::pokeexpire, and iax2_peer::pokefreqnotok.
Referenced by iax2_poke_noanswer().
08863 { 08864 struct iax2_peer *peer = (struct iax2_peer *)data; 08865 int callno; 08866 08867 if (peer->lastms > -1) { 08868 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms); 08869 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms); 08870 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 08871 } 08872 if ((callno = peer->callno) > 0) { 08873 ast_mutex_lock(&iaxsl[callno]); 08874 iax2_destroy(callno); 08875 ast_mutex_unlock(&iaxsl[callno]); 08876 } 08877 peer->callno = 0; 08878 peer->lastms = -1; 08879 /* Try again quickly */ 08880 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 08881 if (peer->pokeexpire == -1) 08882 peer_unref(peer); 08883 }
| static void __iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 6492 of file chan_iax2.c.
References iax2_poke_peer(), and peer_unref().
Referenced by iax2_poke_peer_s().
06493 { 06494 struct iax2_peer *peer = (struct iax2_peer *)data; 06495 iax2_poke_peer(peer, 0); 06496 peer_unref(peer); 06497 }
| static int __iax2_show_peers | ( | int | manager, | |
| int | fd, | |||
| struct mansession * | s, | |||
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4550 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_cli(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), iax2_peer::encmethods, FORMAT, FORMAT2, IAX_DYNAMIC, IAX_TRUNK, iax2_peer::mask, name, peer_status(), peer_unref(), peers, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by iax2_show_peers(), and manager_iax2_show_peers().
04551 { 04552 regex_t regexbuf; 04553 int havepattern = 0; 04554 int total_peers = 0; 04555 int online_peers = 0; 04556 int offline_peers = 0; 04557 int unmonitored_peers = 0; 04558 struct ao2_iterator i; 04559 04560 #define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" 04561 #define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" 04562 04563 struct iax2_peer *peer = NULL; 04564 char name[256]; 04565 int registeredonly=0; 04566 char *term = manager ? "\r\n" : "\n"; 04567 04568 switch (argc) { 04569 case 6: 04570 if (!strcasecmp(argv[3], "registered")) 04571 registeredonly = 1; 04572 else 04573 return RESULT_SHOWUSAGE; 04574 if (!strcasecmp(argv[4], "like")) { 04575 if (regcomp(®exbuf, argv[5], REG_EXTENDED | REG_NOSUB)) 04576 return RESULT_SHOWUSAGE; 04577 havepattern = 1; 04578 } else 04579 return RESULT_SHOWUSAGE; 04580 break; 04581 case 5: 04582 if (!strcasecmp(argv[3], "like")) { 04583 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 04584 return RESULT_SHOWUSAGE; 04585 havepattern = 1; 04586 } else 04587 return RESULT_SHOWUSAGE; 04588 break; 04589 case 4: 04590 if (!strcasecmp(argv[3], "registered")) 04591 registeredonly = 1; 04592 else 04593 return RESULT_SHOWUSAGE; 04594 break; 04595 case 3: 04596 break; 04597 default: 04598 return RESULT_SHOWUSAGE; 04599 } 04600 04601 04602 if (s) 04603 astman_append(s, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 04604 else 04605 ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 04606 04607 i = ao2_iterator_init(peers, 0); 04608 for (peer = ao2_iterator_next(&i); peer; 04609 peer_unref(peer), peer = ao2_iterator_next(&i)) { 04610 char nm[20]; 04611 char status[20]; 04612 char srch[2000]; 04613 int retstatus; 04614 04615 if (registeredonly && !peer->addr.sin_addr.s_addr) 04616 continue; 04617 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) 04618 continue; 04619 04620 if (!ast_strlen_zero(peer->username)) 04621 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 04622 else 04623 ast_copy_string(name, peer->name, sizeof(name)); 04624 04625 retstatus = peer_status(peer, status, sizeof(status)); 04626 if (retstatus > 0) 04627 online_peers++; 04628 else if (!retstatus) 04629 offline_peers++; 04630 else 04631 unmonitored_peers++; 04632 04633 ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); 04634 04635 snprintf(srch, sizeof(srch), FORMAT, name, 04636 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 04637 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04638 nm, 04639 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04640 peer->encmethods ? "(E)" : " ", status, term); 04641 04642 if (s) 04643 astman_append(s, FORMAT, name, 04644 peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)", 04645 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04646 nm, 04647 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04648 peer->encmethods ? "(E)" : " ", status, term); 04649 else 04650 ast_cli(fd, FORMAT, name, 04651 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 04652 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04653 nm, 04654 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04655 peer->encmethods ? "(E)" : " ", status, term); 04656 total_peers++; 04657 } 04658 04659 if (s) 04660 astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 04661 else 04662 ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 04663 04664 if (havepattern) 04665 regfree(®exbuf); 04666 04667 return RESULT_SUCCESS; 04668 #undef FORMAT 04669 #undef FORMAT2 04670 }
| static int __schedule_action | ( | void(*)(const void *data) | func, | |
| const void * | data, | |||
| const char * | funcname | |||
| ) | [static] |
Definition at line 964 of file chan_iax2.c.
References ast_log(), find_idle_thread(), func, IAX_IOSTATE_SCHEDREADY, LOG_DEBUG, option_debug, signal_condition(), t, and thread.
00965 { 00966 struct iax2_thread *thread = NULL; 00967 static time_t lasterror; 00968 static time_t t; 00969 00970 thread = find_idle_thread(); 00971 00972 if (thread != NULL) { 00973 thread->schedfunc = func; 00974 thread->scheddata = data; 00975 thread->iostate = IAX_IOSTATE_SCHEDREADY; 00976 #ifdef DEBUG_SCHED_MULTITHREAD 00977 ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc)); 00978 #endif 00979 signal_condition(&thread->lock, &thread->cond); 00980 return 0; 00981 } 00982 time(&t); 00983 if (t != lasterror && option_debug) 00984 ast_log(LOG_DEBUG, "Out of idle IAX2 threads for scheduling!\n"); 00985 lasterror = t; 00986 00987 return -1; 00988 }
| 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 5051 of file chan_iax2.c.
References ast_frame::data, ast_frame::datalen, ast_frame::frametype, iax2_send(), ast_frame::src, and ast_frame::subclass.
Referenced by send_command(), send_command_final(), send_command_immediate(), and send_command_transfer().
05053 { 05054 struct ast_frame f = { 0, }; 05055 05056 f.frametype = type; 05057 f.subclass = command; 05058 f.datalen = datalen; 05059 f.src = __FUNCTION__; 05060 f.data = (void *) data; 05061 05062 return iax2_send(i, &f, ts, seqno, now, transfer, final); 05063 }
| static void __send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1044 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_sched_add(), IAX_COMMAND_LAGRQ, iaxs, iaxsl, chan_iax2_pvt::lagid, send_command(), and send_lagrq().
Referenced by send_lagrq().
01045 { 01046 int callno = (long) data; 01047 01048 ast_mutex_lock(&iaxsl[callno]); 01049 01050 while (iaxs[callno] && iaxs[callno]->lagid > -1) { 01051 if (iaxs[callno]->peercallno) { 01052 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1); 01053 } 01054 iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data); 01055 break; 01056 } 01057 01058 ast_mutex_unlock(&iaxsl[callno]); 01059 }
| static void __send_ping | ( | const void * | data | ) | [static] |
Definition at line 1004 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_sched_add(), IAX_COMMAND_PING, iaxs, iaxsl, chan_iax2_pvt::pingid, send_command(), and send_ping().
Referenced by send_ping().
01005 { 01006 int callno = (long) data; 01007 01008 ast_mutex_lock(&iaxsl[callno]); 01009 01010 while (iaxs[callno] && iaxs[callno]->pingid != -1) { 01011 if (iaxs[callno]->peercallno) { 01012 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1); 01013 } 01014 iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data); 01015 break; 01016 } 01017 01018 ast_mutex_unlock(&iaxsl[callno]); 01019 }
| static int __unload_module | ( | void | ) | [static] |
Definition at line 10989 of file chan_iax2.c.
References ao2_ref(), ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_signal(), AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_release(), AST_PTHREADT_NULL, ast_unregister_application(), ast_unregister_switch(), cli_iax2, delete_users(), iax2_destroy(), iax2_switch, iax2_tech, iax_peercallno_pvts, iax_provision_unload(), iaxactivethreadcount, iaxq, iaxs, iaxsl, ast_firmware_list::lock, papp, peers, reload_firmware(), sched_context_destroy(), thread, users, and waresl.
Referenced by load_module(), and unload_module().
10990 { 10991 struct iax2_thread *thread = NULL; 10992 int x; 10993 10994 /* Make sure threads do not hold shared resources when they are canceled */ 10995 10996 /* Grab the sched lock resource to keep it away from threads about to die */ 10997 /* Cancel the network thread, close the net socket */ 10998 if (netthreadid != AST_PTHREADT_NULL) { 10999 AST_LIST_LOCK(&iaxq.queue); 11000 ast_mutex_lock(&sched_lock); 11001 pthread_cancel(netthreadid); 11002 ast_cond_signal(&sched_cond); 11003 ast_mutex_unlock(&sched_lock); /* Release the schedule lock resource */ 11004 AST_LIST_UNLOCK(&iaxq.queue); 11005 pthread_join(netthreadid, NULL); 11006 } 11007 if (schedthreadid != AST_PTHREADT_NULL) { 11008 ast_mutex_lock(&sched_lock); 11009 pthread_cancel(schedthreadid); 11010 ast_cond_signal(&sched_cond); 11011 ast_mutex_unlock(&sched_lock); 11012 pthread_join(schedthreadid, NULL); 11013 } 11014 11015 /* Call for all threads to halt */ 11016 AST_LIST_LOCK(&idle_list); 11017 AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) { 11018 AST_LIST_REMOVE_CURRENT(&idle_list, list); 11019 pthread_cancel(thread->threadid); 11020 } 11021 AST_LIST_TRAVERSE_SAFE_END 11022 AST_LIST_UNLOCK(&idle_list); 11023 11024 AST_LIST_LOCK(&active_list); 11025 AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) { 11026 AST_LIST_REMOVE_CURRENT(&active_list, list); 11027 pthread_cancel(thread->threadid); 11028 } 11029 AST_LIST_TRAVERSE_SAFE_END 11030 AST_LIST_UNLOCK(&active_list); 11031 11032 AST_LIST_LOCK(&dynamic_list); 11033 AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) { 11034 AST_LIST_REMOVE_CURRENT(&dynamic_list, list); 11035 pthread_cancel(thread->threadid); 11036 } 11037 AST_LIST_TRAVERSE_SAFE_END 11038 AST_LIST_UNLOCK(&dynamic_list); 11039 11040 AST_LIST_HEAD_DESTROY(&iaxq.queue); 11041 11042 /* Wait for threads to exit */ 11043 while(0 < iaxactivethreadcount) 11044 usleep(10000); 11045 11046 ast_netsock_release(netsock); 11047 ast_netsock_release(outsock); 11048 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 11049 if (iaxs[x]) { 11050 iax2_destroy(x); 11051 } 11052 } 11053 ast_manager_unregister( "IAXpeers" ); 11054 ast_manager_unregister( "IAXnetstats" ); 11055 ast_unregister_application(papp); 11056 ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 11057 ast_unregister_switch(&iax2_switch); 11058 ast_channel_unregister(&iax2_tech); 11059 delete_users(); 11060 iax_provision_unload(); 11061 sched_context_destroy(sched); 11062 reload_firmware(1); 11063 11064 ast_mutex_destroy(&waresl.lock); 11065 11066 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 11067 ast_mutex_destroy(&iaxsl[x]); 11068 } 11069 11070 ao2_ref(peers, -1); 11071 ao2_ref(users, -1); 11072 ao2_ref(iax_peercallno_pvts, -1); 11073 11074 return 0; 11075 }
| static int apply_context | ( | struct iax2_context * | con, | |
| const char * | context | |||
| ) | [static] |
Definition at line 5104 of file chan_iax2.c.
References iax2_context::context, and iax2_context::next.
Referenced by check_access().
05105 { 05106 while(con) { 05107 if (!strcmp(con->context, context) || !strcmp(con->context, "*")) 05108 return -1; 05109 con = con->next; 05110 } 05111 return 0; 05112 }
| static int ast_cli_netstats | ( | struct mansession * | s, | |
| int | fd, | |||
| int | limit_fmt | |||
| ) | [static] |
Definition at line 4878 of file chan_iax2.c.
References ARRAY_LEN, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, astman_append(), jb_info::current, iax_rr::delay, iax_rr::dropped, fmt, jb_info::frames_dropped, jb_info::frames_lost, jb_info::frames_ooo, chan_iax2_pvt::frames_received, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), iax_rr::jitter, jb_info::jitter, iax_rr::losscnt, iax_rr::losspct, jb_info::losspct, jb_info::min, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::pingtime, and chan_iax2_pvt::remote_rr.
Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().
04879 { 04880 int x; 04881 int numchans = 0; 04882 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 04883 ast_mutex_lock(&iaxsl[x]); 04884 if (iaxs[x]) { 04885 int localjitter, localdelay, locallost, locallosspct, localdropped, localooo; 04886 char *fmt; 04887 jb_info jbinfo; 04888 04889 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 04890 jb_getinfo(iaxs[x]->jb, &jbinfo); 04891 localjitter = jbinfo.jitter; 04892 localdelay = jbinfo.current - jbinfo.min; 04893 locallost = jbinfo.frames_lost; 04894 locallosspct = jbinfo.losspct/1000; 04895 localdropped = jbinfo.frames_dropped; 04896 localooo = jbinfo.frames_ooo; 04897 } else { 04898 localjitter = -1; 04899 localdelay = 0; 04900 locallost = -1; 04901 locallosspct = -1; 04902 localdropped = 0; 04903 localooo = -1; 04904 } 04905 if (limit_fmt) 04906 fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n"; 04907 else 04908 fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"; 04909 if (s) 04910 04911 astman_append(s, fmt, 04912 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04913 iaxs[x]->pingtime, 04914 localjitter, 04915 localdelay, 04916 locallost, 04917 locallosspct, 04918 localdropped, 04919 localooo, 04920 iaxs[x]->frames_received/1000, 04921 iaxs[x]->remote_rr.jitter, 04922 iaxs[x]->remote_rr.delay, 04923 iaxs[x]->remote_rr.losscnt, 04924 iaxs[x]->remote_rr.losspct, 04925 iaxs[x]->remote_rr.dropped, 04926 iaxs[x]->remote_rr.ooo, 04927 iaxs[x]->remote_rr.packets/1000); 04928 else 04929 ast_cli(fd, fmt, 04930 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04931 iaxs[x]->pingtime, 04932 localjitter, 04933 localdelay, 04934 locallost, 04935 locallosspct, 04936 localdropped, 04937 localooo, 04938 iaxs[x]->frames_received/1000, 04939 iaxs[x]->remote_rr.jitter, 04940 iaxs[x]->remote_rr.delay, 04941 iaxs[x]->remote_rr.losscnt, 04942 iaxs[x]->remote_rr.losspct, 04943 iaxs[x]->remote_rr.dropped, 04944 iaxs[x]->remote_rr.ooo, 04945 iaxs[x]->remote_rr.packets/1000 04946 ); 04947 numchans++; 04948 } 04949 ast_mutex_unlock(&iaxsl[x]); 04950 } 04951 return numchans; 04952 }
| 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 3742 of file chan_iax2.c.
References chan_iax2_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, chan_iax2_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc(), ast_channel_free(), ast_hangup(), 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(), 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, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, iax2_tech, iaxs, iaxsl, LOG_WARNING, ast_variable::name, ast_channel::nativeformats, ast_variable::next, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), chan_iax2_pvt::peeradsicpe, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, ast_variable::value, chan_iax2_pvt::vars, and ast_channel::writeformat.
Referenced by iax2_request(), and socket_process().
03743 { 03744 struct ast_channel *tmp; 03745 struct chan_iax2_pvt *i; 03746 struct ast_variable *v = NULL; 03747 03748 if (!(i = iaxs[callno])) { 03749 ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno); 03750 return NULL; 03751 } 03752 03753 /* Don't hold call lock */ 03754 ast_mutex_unlock(&iaxsl[callno]); 03755 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); 03756 ast_mutex_lock(&iaxsl[callno]); 03757 if (!iaxs[callno]) { 03758 if (tmp) { 03759 ast_channel_free(tmp); 03760 } 03761 ast_mutex_unlock(&iaxsl[callno]); 03762 return NULL; 03763 } 03764 03765 if (!tmp) 03766 return NULL; 03767 tmp->tech = &iax2_tech; 03768 /* We can support any format by default, until we get restricted */ 03769 tmp->nativeformats = capability; 03770 tmp->readformat = ast_best_codec(capability); 03771 tmp->writeformat = ast_best_codec(capability); 03772 tmp->tech_pvt = CALLNO_TO_PTR(i->callno); 03773 03774 /* Don't use ast_set_callerid() here because it will 03775 * generate a NewCallerID event before the NewChannel event */ 03776 if (!ast_strlen_zero(i->ani)) 03777 tmp->cid.cid_ani = ast_strdup(i->ani); 03778 else 03779 tmp->cid.cid_ani = ast_strdup(i->cid_num); 03780 tmp->cid.cid_dnid = ast_strdup(i->dnid); 03781 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 03782 tmp->cid.cid_pres = i->calling_pres; 03783 tmp->cid.cid_ton = i->calling_ton; 03784 tmp->cid.cid_tns = i->calling_tns; 03785 if (!ast_strlen_zero(i->language)) 03786 ast_string_field_set(tmp, language, i->language); 03787 if (!ast_strlen_zero(i->accountcode)) 03788 ast_string_field_set(tmp, accountcode, i->accountcode); 03789 if (i->amaflags) 03790 tmp->amaflags = i->amaflags; 03791 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 03792 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 03793 if (i->adsi) 03794 tmp->adsicpe = i->peeradsicpe; 03795 else 03796 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 03797 i->owner = tmp; 03798 i->capability = capability; 03799 03800 for (v = i->vars ; v ; v = v->next) 03801 pbx_builtin_setvar_helper(tmp, v->name, v->value); 03802 03803 if (state != AST_STATE_DOWN) { 03804 if (ast_pbx_start(tmp)) { 03805 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 03806 ast_hangup(tmp); 03807 i->owner = NULL; 03808 return NULL; 03809 } 03810 } 03811 03812 ast_module_ref(ast_module_info->self); 03813 03814 return tmp; 03815 }
| static AST_LIST_HEAD_STATIC | ( | dynamic_list | , | |
| iax2_thread | ||||
| ) | [static] |
| static AST_LIST_HEAD_STATIC | ( | active_list | , | |
| iax2_thread | ||||
| ) | [static] |
| static AST_LIST_HEAD_STATIC | ( | idle_list | , | |
| iax2_thread | ||||
| ) | [static] |
| static AST_LIST_HEAD_STATIC | ( | registrations | , | |
| iax2_registry | ||||
| ) | [static] |
| AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
| AST_MODFLAG_DEFAULT | , | |||
| "Inter Asterisk eXchange (Ver 2)" | , | |||
| . | load = load_module, |
|||
| . | unload = unload_module, |
|||
| . | reload = reload | |||
| ) |
| AST_MUTEX_DEFINE_STATIC | ( | dpcache_lock | ) |
| AST_MUTEX_DEFINE_STATIC | ( | tpeerlock | ) |
| AST_MUTEX_DEFINE_STATIC | ( | sched_lock | ) |
| static int attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 2247 of file chan_iax2.c.
References __attempt_transmit(), and schedule_action.
Referenced by __attempt_transmit(), and network_thread().
02248 { 02249 #ifdef SCHED_MULTITHREADED 02250 if (schedule_action(__attempt_transmit, data)) 02251 #endif 02252 __attempt_transmit(data); 02253 return 0; 02254 }
| static int auth_fail | ( | int | callno, | |
| int | failcode | |||
| ) | [static] |
Definition at line 6414 of file chan_iax2.c.
References AST_SCHED_DEL, auth_reject(), chan_iax2_pvt::authfail, chan_iax2_pvt::authid, iax2_sched_add(), and iaxs.
Referenced by socket_process().
06415 { 06416 /* Schedule sending the authentication failure in one second, to prevent 06417 guessing */ 06418 if (iaxs[callno]) { 06419 iaxs[callno]->authfail = failcode; 06420 if (delayreject) { 06421 AST_SCHED_DEL(sched, iaxs[callno]->authid); 06422 iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno); 06423 } else 06424 auth_reject((void *)(long)callno); 06425 } 06426 return 0; 06427 }
| static int auth_reject | ( | const void * | data | ) | [static] |
Definition at line 6400 of file chan_iax2.c.
References __auth_reject(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::authid, iax2_registry::callno, iaxs, iaxsl, and schedule_action.
Referenced by auth_fail().
06401 { 06402 int callno = (int)(long)(data); 06403 ast_mutex_lock(&iaxsl[callno]); 06404 if (iaxs[callno]) 06405 iaxs[callno]->authid = -1; 06406 ast_mutex_unlock(&iaxsl[callno]); 06407 #ifdef SCHED_MULTITHREADED 06408 if (schedule_action(__auth_reject, data)) 06409 #endif 06410 __auth_reject(data); 06411 return 0; 06412 }
| 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 5629 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().
05630 { 05631 int res = -1; 05632 int x; 05633 if (!ast_strlen_zero(keyn)) { 05634 if (!(authmethods & IAX_AUTH_RSA)) { 05635 if (ast_strlen_zero(secret)) 05636 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)); 05637 } else if (ast_strlen_zero(challenge)) { 05638 ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr)); 05639 } else { 05640 char sig[256]; 05641 struct ast_key *key; 05642 key = ast_key_get(keyn, AST_KEY_PRIVATE); 05643 if (!key) { 05644 ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn); 05645 } else { 05646 if (ast_sign(key, (char*)challenge, sig)) { 05647 ast_log(LOG_NOTICE, "Unable to sign challenge with key\n"); 05648 res = -1; 05649 } else { 05650 iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig); 05651 res = 0; 05652 } 05653 } 05654 } 05655 } 05656 /* Fall back */ 05657 if (res && !ast_strlen_zero(secret)) { 05658 if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) { 05659 struct MD5Context md5; 05660 unsigned char digest[16]; 05661 char digres[128]; 05662 MD5Init(&md5); 05663 MD5Update(&md5, (unsigned char *)challenge, strlen(challenge)); 05664 MD5Update(&md5, (unsigned char *)secret, strlen(secret)); 05665 MD5Final(digest, &md5); 05666 /* If they support md5, authenticate with it. */ 05667 for (x=0;x<16;x++) 05668 sprintf(digres + (x << 1), "%2.2x", digest[x]); /* safe */ 05669 if (pvt) { 05670 build_encryption_keys(digest, pvt); 05671 } 05672 iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres); 05673 res = 0; 05674 } else if (authmethods & IAX_AUTH_PLAINTEXT) { 05675 iax_ie_append_str(ied, IAX_IE_PASSWORD, secret); 05676 res = 0; 05677 } else 05678 ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods); 05679 } 05680 return res; 05681 }
| 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 5687 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), authenticate(), iax_ies::authmethods, iax2_peer::authmethods, iax_ie_data::buf, chan_iax2_pvt::callno, iax2_registry::callno, iax_ies::challenge, chan_iax2_pvt::encmethods, iax_ies::encmethods, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, iaxs, iaxsl, iax2_peer::mask, merge_encryption(), peer_unref(), peers, iax_ie_data::pos, realtime_peer(), send_command(), and iax_ies::username.
Referenced by socket_process().
05688 { 05689 struct iax2_peer *peer = NULL; 05690 /* Start pessimistic */ 05691 int res = -1; 05692 int authmethods = 0; 05693 struct iax_ie_data ied; 05694 uint16_t callno = p->callno; 05695 05696 memset(&ied, 0, sizeof(ied)); 05697 05698 if (ies->username) 05699 ast_string_field_set(p, username, ies->username); 05700 if (ies->challenge) 05701 ast_string_field_set(p, challenge, ies->challenge); 05702 if (ies->authmethods) 05703 authmethods = ies->authmethods; 05704 if (authmethods & IAX_AUTH_MD5) 05705 merge_encryption(p, ies->encmethods); 05706 else 05707 p->encmethods = 0; 05708 05709 /* Check for override RSA authentication first */ 05710 if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) { 05711 /* Normal password authentication */ 05712 res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, p); 05713 } else { 05714 struct ao2_iterator i = ao2_iterator_init(peers, 0); 05715 while ((peer = ao2_iterator_next(&i))) { 05716 if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 05717 /* No peer specified at our end, or this is the peer */ 05718 && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username))) 05719 /* No username specified in peer rule, or this is the right username */ 05720 && (!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))) 05721 /* No specified host, or this is our host */ 05722 ) { 05723 res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, p); 05724 if (!res) { 05725 peer_unref(peer); 05726 break; 05727 } 05728 } 05729 peer_unref(peer); 05730 } 05731 if (!peer) { 05732 /* We checked our list and didn't find one. It's unlikely, but possible, 05733 that we're trying to authenticate *to* a realtime peer */ 05734 const char *peer_name = ast_strdupa(p->peer); 05735 ast_mutex_unlock(&iaxsl[callno]); 05736 if ((peer = realtime_peer(peer_name, NULL))) { 05737 ast_mutex_lock(&iaxsl[callno]); 05738 if (!(p = iaxs[callno])) { 05739 peer_unref(peer); 05740 return -1; 05741 } 05742 res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, p); 05743 peer_unref(peer); 05744 } 05745 if (!peer) { 05746 ast_mutex_lock(&iaxsl[callno]); 05747 if (!(p = iaxs[callno])) 05748 return -1; 05749 } 05750 } 05751 } 05752 if (ies->encmethods) 05753 ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED); 05754 if (!res) 05755 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1); 05756 return res; 05757 }
| static int authenticate_request | ( | int | call_num | ) | [static] |
Definition at line 5364 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, 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, iaxs, iax2_user::maxauthreq, iax_ie_data::pos, send_command(), send_command_final(), user_unref(), and users.
Referenced by socket_process().
05365 { 05366 struct iax_ie_data ied; 05367 int res = -1, authreq_restrict = 0; 05368 char challenge[10]; 05369 struct chan_iax2_pvt *p = iaxs[call_num]; 05370 05371 memset(&ied, 0, sizeof(ied)); 05372 05373 /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */ 05374 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 05375 struct iax2_user *user, tmp_user = { 05376 .name = p->username, 05377 }; 05378 05379 user = ao2_find(users, &tmp_user, OBJ_POINTER); 05380 if (user) { 05381 if (user->curauthreq == user->maxauthreq) 05382 authreq_restrict = 1; 05383 else 05384 user->curauthreq++; 05385 user = user_unref(user); 05386 } 05387 } 05388 05389 /* If the AUTHREQ limit test failed, send back an error */ 05390 if (authreq_restrict) { 05391 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached"); 05392 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED); 05393 send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1); 05394 return 0; 05395 } 05396 05397 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 05398 if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) { 05399 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 05400 ast_string_field_set(p, challenge, challenge); 05401 /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */ 05402 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge); 05403 } 05404 if (p->encmethods) 05405 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods); 05406 05407 iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username); 05408 05409 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1); 05410 05411 if (p->encmethods) 05412 ast_set_flag(p, IAX_ENCRYPTED); 05413 05414 return res; 05415 }
| static int authenticate_verify | ( | struct chan_iax2_pvt * | p, | |
| struct iax_ies * | ies | |||
| ) | [static] |
Definition at line 5417 of file chan_iax2.c.
References ao2_find(), ast_check_signature, ast_clear_flag, ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, chan_iax2_pvt::authmethods, iax2_user::curauthreq, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_MAXAUTHREQ, IAX_STATE_AUTHENTICATED, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, iax_ies::rsa_result, iax2_registry::secret, chan_iax2_pvt::state, strsep(), user_unref(), and users.
Referenced by socket_process().
05418 { 05419 char requeststr[256]; 05420 char md5secret[256] = ""; 05421 char secret[256] = ""; 05422 char rsasecret[256] = ""; 05423 int res = -1; 05424 int x; 05425 struct iax2_user *user, tmp_user = { 05426 .name = p->username, 05427 }; 05428 05429 user = ao2_find(users, &tmp_user, OBJ_POINTER); 05430 if (user) { 05431 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 05432 ast_atomic_fetchadd_int(&user->curauthreq, -1); 05433 ast_clear_flag(p, IAX_MAXAUTHREQ); 05434 } 05435 ast_string_field_set(p, host, user->name); 05436 user = user_unref(user); 05437 } 05438 05439 if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED)) 05440 return res; 05441 if (ies->password) 05442 ast_copy_string(secret, ies->password, sizeof(secret)); 05443 if (ies->md5_result) 05444 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 05445 if (ies->rsa_result) 05446 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 05447 if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) { 05448 struct ast_key *key; 05449 char *keyn; 05450 char tmpkey[256]; 05451 char *stringp=NULL; 05452 ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey)); 05453 stringp=tmpkey; 05454 keyn = strsep(&stringp, ":"); 05455 while(keyn) { 05456 key = ast_key_get(keyn, AST_KEY_PUBLIC); 05457 if (key && !ast_check_signature(key, p->challenge, rsasecret)) { 05458 res = 0; 05459 break; 05460 } else if (!key) 05461 ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn); 05462 keyn = strsep(&stringp, ":"); 05463 } 05464 } else if (p->authmethods & IAX_AUTH_MD5) { 05465 struct MD5Context md5; 05466 unsigned char digest[16]; 05467 char *tmppw, *stringp; 05468 05469 tmppw = ast_strdupa(p->secret); 05470 stringp = tmppw; 05471 while((tmppw = strsep(&stringp, ";"))) { 05472 MD5Init(&md5); 05473 MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge)); 05474 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 05475 MD5Final(digest, &md5); 05476 /* If they support md5, authenticate with it. */ 05477 for (x=0;x<16;x++) 05478 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 05479 if (!strcasecmp(requeststr, md5secret)) { 05480 res = 0; 05481 break; 05482 } 05483 } 05484 } else if (p->authmethods & IAX_AUTH_PLAINTEXT) { 05485 if (!strcmp(secret, p->secret)) 05486 res = 0; 05487 } 05488 return res; 05489 }
| static int auto_congest | ( | const void * | data | ) | [static] |
Definition at line 3134 of file chan_iax2.c.
References __auto_congest(), and schedule_action.
Referenced by iax2_call(), and sip_call().
03135 { 03136 #ifdef SCHED_MULTITHREADED 03137 if (schedule_action(__auto_congest, data)) 03138 #endif 03139 __auto_congest(data); 03140 return 0; 03141 }
| static int auto_hangup | ( | const void * | data | ) | [static] |
Definition at line 6444 of file chan_iax2.c.
References __auto_hangup(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::autoid, iax2_registry::callno, iaxs, iaxsl, and schedule_action.
Referenced by iax2_dprequest(), and iax2_provision().
06445 { 06446 int callno = (int)(long)(data); 06447 ast_mutex_lock(&iaxsl[callno]); 06448 if (iaxs[callno]) { 06449 iaxs[callno]->autoid = -1; 06450 } 06451 ast_mutex_unlock(&iaxsl[callno]); 06452 #ifdef SCHED_MULTITHREADED 06453 if (schedule_action(__auto_hangup, data)) 06454 #endif 06455 __auto_hangup(data); 06456 return 0; 06457 }
| static struct iax2_context* build_context | ( | char * | context | ) | [static, read] |
Definition at line 9183 of file chan_iax2.c.
References ast_calloc, and iax2_context::context.
Referenced by build_user().
09184 { 09185 struct iax2_context *con; 09186 09187 if ((con = ast_calloc(1, sizeof(*con)))) 09188 ast_copy_string(con->context, context, sizeof(con->context)); 09189 09190 return con; 09191 }
| static void build_ecx_key | ( | const unsigned char * | digest, | |
| struct chan_iax2_pvt * | pvt | |||
| ) | [static] |
Definition at line 4128 of file chan_iax2.c.
References aes_decrypt_key128(), aes_encrypt_key128(), chan_iax2_pvt::ecx, and chan_iax2_pvt::mydcx.
Referenced by build_encryption_keys().
04129 { 04130 /* it is required to hold the corresponding decrypt key to our encrypt key 04131 * in the pvt struct because queued frames occasionally need to be decrypted and 04132 * re-encrypted when updated for a retransmission */ 04133 aes_encrypt_key128(digest, &pvt->ecx); 04134 aes_decrypt_key128(digest, &pvt->mydcx); 04135 }
| static void build_encryption_keys | ( | const unsigned char * | digest, | |
| struct chan_iax2_pvt * | pvt | |||
| ) | [static] |
Definition at line 4122 of file chan_iax2.c.
References aes_decrypt_key128(), build_ecx_key(), and chan_iax2_pvt::dcx.
Referenced by authenticate(), and decrypt_frame().
04123 { 04124 build_ecx_key(digest, pvt); 04125 aes_decrypt_key128(digest, &pvt->dcx); 04126 }
| 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 9329 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_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_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), iax2_peer::authmethods, iax2_peer::capability, cid_name, cid_num, 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, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mask, iax2_peer::maxms, ast_variable::name, ast_variable::next, peer_destructor(), peer_set_srcaddr(), peer_unref(), peers, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, prefs, iax2_peer::prefs, iax2_registry::secret, iax2_peer::smoothing, iax2_peer::sockfd, unlink_peer(), and ast_variable::value.
09330 { 09331 struct iax2_peer *peer = NULL; 09332 struct ast_ha *oldha = NULL; 09333 int maskfound=0; 09334 int found=0; 09335 int firstpass=1; 09336 struct iax2_peer tmp_peer = { 09337 .name = name, 09338 }; 09339 09340 if (!temponly) { 09341 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 09342 if (peer && !ast_test_flag(peer, IAX_DELME)) 09343 firstpass = 0; 09344 } 09345 09346 if (peer) { 09347 found++; 09348 if (firstpass) { 09349 oldha = peer->ha; 09350 peer->ha = NULL; 09351 } 09352 unlink_peer(peer); 09353 } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) { 09354 peer->expire = -1; 09355 peer->pokeexpire = -1; 09356 peer->sockfd = defaultsockfd; 09357 if (ast_string_field_init(peer, 32)) 09358 peer = peer_unref(peer); 09359 } 09360 09361 if (peer) { 09362 if (firstpass) { 09363 ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 09364 peer->encmethods = iax2_encryption; 09365 peer->adsi = adsi; 09366 ast_string_field_set(peer,secret,""); 09367 if (!found) { 09368 ast_string_field_set(peer, name, name); 09369 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 09370 peer->expiry = min_reg_expire; 09371 } 09372 peer->prefs = prefs; 09373 peer->capability = iax2_capability; 09374 peer->smoothing = 0; 09375 peer->pokefreqok = DEFAULT_FREQ_OK; 09376 peer->pokefreqnotok = DEFAULT_FREQ_NOTOK; 09377 ast_string_field_set(peer,context,""); 09378 ast_string_field_set(peer,peercontext,""); 09379 ast_clear_flag(peer, IAX_HASCALLERID); 09380 ast_string_field_set(peer, cid_name, ""); 09381 ast_string_field_set(peer, cid_num, ""); 09382 } 09383 09384 if (!v) { 09385 v = alt; 09386 alt = NULL; 09387 } 09388 while(v) { 09389 if (!strcasecmp(v->name, "secret")) { 09390 ast_string_field_set(peer, secret, v->value); 09391 } else if (!strcasecmp(v->name, "mailbox")) { 09392 ast_string_field_set(peer, mailbox, v->value); 09393 } else if (!strcasecmp(v->name, "mohinterpret")) { 09394 ast_string_field_set(peer, mohinterpret, v->value); 09395 } else if (!strcasecmp(v->name, "mohsuggest")) { 09396 ast_string_field_set(peer, mohsuggest, v->value); 09397 } else if (!strcasecmp(v->name, "dbsecret")) { 09398 ast_string_field_set(peer, dbsecret, v->value); 09399 } else if (!strcasecmp(v->name, "trunk")) { 09400 ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK); 09401 if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) { 09402 ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without zaptel timing\n", peer->name); 09403 ast_clear_flag(peer, IAX_TRUNK); 09404 } 09405 } else if (!strcasecmp(v->name, "auth")) { 09406 peer->authmethods = get_auth_methods(v->value); 09407 } else if (!strcasecmp(v->name, "encryption")) { 09408 peer->encmethods = get_encrypt_methods(v->value); 09409 } else if (!strcasecmp(v->name, "notransfer")) { 09410 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 09411 ast_clear_flag(peer, IAX_TRANSFERMEDIA); 09412 ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 09413 } else if (!strcasecmp(v->name, "transfer")) { 09414 if (!strcasecmp(v->value, "mediaonly")) { 09415 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 09416 } else if (ast_true(v->value)) { 09417 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 09418 } else 09419 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 09420 } else if (!strcasecmp(v->name, "jitterbuffer")) { 09421 ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF); 09422 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 09423 ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF); 09424 } else if (!strcasecmp(v->name, "host")) { 09425 if (!strcasecmp(v->value, "dynamic")) { 09426 /* They'll register with us */ 09427 ast_set_flag(peer, IAX_DYNAMIC); 09428 if (!found) { 09429 /* Initialize stuff iff we're not found, otherwise 09430 we keep going with what we had */ 09431 memset(&peer->addr.sin_addr, 0, 4); 09432 if (peer->addr.sin_port) { 09433 /* If we've already got a port, make it the default rather than absolute */ 09434 peer->defaddr.sin_port = peer->addr.sin_port; 09435 peer->addr.sin_port = 0; 09436 } 09437 } 09438 } else { 09439 /* Non-dynamic. Make sure we become that way if we're not */ 09440 AST_SCHED_DEL(sched, peer->expire); 09441 ast_clear_flag(peer, IAX_DYNAMIC); 09442 if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr)) 09443 return peer_unref(peer); 09444 if (!peer->addr.sin_port) 09445 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 09446 } 09447 if (!maskfound) 09448 inet_aton("255.255.255.255", &peer->mask); 09449 } else if (!strcasecmp(v->name, "defaultip")) { 09450 if (ast_get_ip(&peer->defaddr, v->value)) 09451 return peer_unref(peer); 09452 } else if (!strcasecmp(v->name, "sourceaddress")) { 09453 peer_set_srcaddr(peer, v->value); 09454 } else if (!strcasecmp(v->name, "permit") || 09455 !strcasecmp(v->name, "deny")) { 09456 peer->ha = ast_append_ha(v->name, v->value, peer->ha); 09457 } else if (!strcasecmp(v->name, "mask")) { 09458 maskfound++; 09459 inet_aton(v->value, &peer->mask); 09460 } else if (!strcasecmp(v->name, "context")) { 09461 ast_string_field_set(peer, context, v->value); 09462 } else if (!strcasecmp(v->name, "regexten")) { 09463 ast_string_field_set(peer, regexten, v->value); 09464 } else if (!strcasecmp(v->name, "peercontext")) { 09465 ast_string_field_set(peer, peercontext, v->value); 09466 } else if (!strcasecmp(v->name, "port")) { 09467 if (ast_test_flag(peer, IAX_DYNAMIC)) 09468 peer->defaddr.sin_port = htons(atoi(v->value)); 09469 else 09470 peer->addr.sin_port = htons(atoi(v->value)); 09471 } else if (!strcasecmp(v->name, "username")) { 09472 ast_string_field_set(peer, username, v->value); 09473 } else if (!strcasecmp(v->name, "allow")) { 09474 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1); 09475 } else if (!strcasecmp(v->name, "disallow")) { 09476 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); 09477 } else if (!strcasecmp(v->name, "callerid")) { 09478 if (!ast_strlen_zero(v->value)) { 09479 char name2[80]; 09480 char num2[80]; 09481 ast_callerid_split(v->value, name2, 80, num2, 80); 09482 ast_string_field_set(peer, cid_name, name2); 09483 ast_string_field_set(peer, cid_num, num2); 09484 ast_set_flag(peer, IAX_HASCALLERID); 09485 } else { 09486 ast_clear_flag(peer, IAX_HASCALLERID); 09487 ast_string_field_set(peer, cid_name, ""); 09488 ast_string_field_set(peer, cid_num, ""); 09489 } 09490 } else if (!strcasecmp(v->name, "fullname")) { 09491 if (!ast_strlen_zero(v->value)) { 09492 ast_string_field_set(peer, cid_name, v->value); 09493 ast_set_flag(peer, IAX_HASCALLERID); 09494 } else { 09495 ast_string_field_set(peer, cid_name, ""); 09496 if (ast_strlen_zero(peer->cid_num)) 09497 ast_clear_flag(peer, IAX_HASCALLERID); 09498 } 09499 } else if (!strcasecmp(v->name, "cid_number")) { 09500 if (!ast_strlen_zero(v->value)) { 09501 ast_string_field_set(peer, cid_num, v->value); 09502 ast_set_flag(peer, IAX_HASCALLERID); 09503 } else { 09504 ast_string_field_set(peer, cid_num, ""); 09505 if (ast_strlen_zero(peer->cid_name)) 09506 ast_clear_flag(peer, IAX_HASCALLERID); 09507 } 09508 } else if (!strcasecmp(v->name, "sendani")) { 09509 ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 09510 } else if (!strcasecmp(v->name, "inkeys")) { 09511 ast_string_field_set(peer, inkeys, v->value); 09512 } else if (!strcasecmp(v->name, "outkey")) { 09513 ast_string_field_set(peer, outkey, v->value); 09514 } else if (!strcasecmp(v->name, "qualify")) { 09515 if (!strcasecmp(v->value, "no")) { 09516 peer->maxms = 0; 09517 } else if (!strcasecmp(v->value, "yes")) { 09518 peer->maxms = DEFAULT_MAXMS; 09519 } else if (sscanf(v->value, "%d", &peer->maxms) != 1) { 09520 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); 09521 peer->maxms = 0; 09522 } 09523 } else if (!strcasecmp(v->name, "qualifysmoothing")) { 09524 peer->smoothing = ast_true(v->value); 09525 } else if (!strcasecmp(v->name, "qualifyfreqok")) { 09526 if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) { 09527 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); 09528 } 09529 } else if (!strcasecmp(v->name, "qualifyfreqnotok")) { 09530 if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) { 09531 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); 09532 } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok); 09533 } else if (!strcasecmp(v->name, "timezone")) { 09534 ast_string_field_set(peer, zonetag, v->value); 09535 } else if (!strcasecmp(v->name, "adsi")) { 09536 peer->adsi = ast_true(v->value); 09537 }/* else if (strcasecmp(v->name,"type")) */ 09538 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 09539 v = v->next; 09540 if (!v) { 09541 v = alt; 09542 alt = NULL; 09543 } 09544 } 09545 if (!peer->authmethods) 09546 peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09547 ast_clear_flag(peer, IAX_DELME); 09548 /* Make sure these are IPv4 addresses */ 09549 peer->addr.sin_family = AF_INET; 09550 } 09551 if (oldha) 09552 ast_free_ha(oldha); 09553 return peer; 09554 }
| 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 9570 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_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(), iax2_user::capability, cid_name, cid_num, cleanup(), iax2_user::contexts, iax2_user::curauthreq, 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, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, iax2_context::next, prefs, iax2_user::prefs, iax2_registry::secret, user_destructor(), user_unref(), users, ast_variable::value, and iax2_user::vars.
09571 { 09572 struct iax2_user *user = NULL; 09573 struct iax2_context *con, *conl = NULL; 09574 struct ast_ha *oldha = NULL; 09575 struct iax2_context *oldcon = NULL; 09576 int format; 09577 int firstpass=1; 09578 int oldcurauthreq = 0; 09579 char *varname = NULL, *varval = NULL; 09580 struct ast_variable *tmpvar = NULL; 09581 struct iax2_user tmp_user = { 09582 .name = name, 09583 }; 09584 09585 if (!temponly) { 09586 user = ao2_find(users, &tmp_user, OBJ_POINTER); 09587 if (user && !ast_test_flag(user, IAX_DELME)) 09588 firstpass = 0; 09589 } 09590 09591 if (user) { 09592 if (firstpass) { 09593 oldcurauthreq = user->curauthreq; 09594 oldha = user->ha; 09595 oldcon = user->contexts; 09596 user->ha = NULL; 09597 user->contexts = NULL; 09598 } 09599 /* Already in the list, remove it and it will be added back (or FREE'd) */ 09600 ao2_unlink(users, user); 09601 } else { 09602 user = ao2_alloc(sizeof(*user), user_destructor); 09603 } 09604 09605 if (user) { 09606 if (firstpass) { 09607 ast_string_field_free_memory(user); 09608 memset(user, 0, sizeof(struct iax2_user)); 09609 if (ast_string_field_init(user, 32)) { 09610 user = user_unref(user); 09611 goto cleanup; 09612 } 09613 user->maxauthreq = maxauthreq; 09614 user->curauthreq = oldcurauthreq; 09615 user->prefs = prefs; 09616 user->capability = iax2_capability; 09617 user->encmethods = iax2_encryption; 09618 user->adsi = adsi; 09619 ast_string_field_set(user, name, name); 09620 ast_string_field_set(user, language, language); 09621 ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP); 09622 ast_clear_flag(user, IAX_HASCALLERID); 09623 ast_string_field_set(user, cid_name, ""); 09624 ast_string_field_set(user, cid_num, ""); 09625 } 09626 if (!v) { 09627 v = alt; 09628 alt = NULL; 09629 } 09630 while(v) { 09631 if (!strcasecmp(v->name, "context")) { 09632 con = build_context(v->value); 09633 if (con) { 09634 if (conl) 09635 conl->next = con; 09636 else 09637 user->contexts = con; 09638 conl = con; 09639 } 09640 } else if (!strcasecmp(v->name, "permit") || 09641 !strcasecmp(v->name, "deny")) { 09642 user->ha = ast_append_ha(v->name, v->value, user->ha); 09643 } else if (!strcasecmp(v->name, "setvar")) { 09644 varname = ast_strdupa(v->value); 09645 if (varname && (varval = strchr(varname,'='))) { 09646 *varval = '\0'; 09647 varval++; 09648 if((tmpvar = ast_variable_new(varname, varval))) { 09649 tmpvar->next = user->vars; 09650 user->vars = tmpvar; 09651 } 09652 } 09653 } else if (!strcasecmp(v->name, "allow")) { 09654 ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1); 09655 } else if (!strcasecmp(v->name, "disallow")) { 09656 ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0); 09657 } else if (!strcasecmp(v->name, "trunk")) { 09658 ast_set2_flag(user, ast_true(v->value), IAX_TRUNK); 09659 if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) { 09660 ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without zaptel timing\n", user->name); 09661 ast_clear_flag(user, IAX_TRUNK); 09662 } 09663 } else if (!strcasecmp(v->name, "auth")) { 09664 user->authmethods = get_auth_methods(v->value); 09665 } else if (!strcasecmp(v->name, "encryption")) { 09666 user->encmethods = get_encrypt_methods(v->value); 09667 } else if (!strcasecmp(v->name, "notransfer")) { 09668 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 09669 ast_clear_flag(user, IAX_TRANSFERMEDIA); 09670 ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 09671 } else if (!strcasecmp(v->name, "transfer")) { 09672 if (!strcasecmp(v->value, "mediaonly")) { 09673 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 09674 } else if (ast_true(v->value)) { 09675 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 09676 } else 09677 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 09678 } else if (!strcasecmp(v->name, "codecpriority")) { 09679 if(!strcasecmp(v->value, "caller")) 09680 ast_set_flag(user, IAX_CODEC_USER_FIRST); 09681 else if(!strcasecmp(v->value, "disabled")) 09682 ast_set_flag(user, IAX_CODEC_NOPREFS); 09683 else if(!strcasecmp(v->value, "reqonly")) { 09684 ast_set_flag(user, IAX_CODEC_NOCAP); 09685 ast_set_flag(user, IAX_CODEC_NOPREFS); 09686 } 09687 } else if (!strcasecmp(v->name, "jitterbuffer")) { 09688 ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF); 09689 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 09690 ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF); 09691 } else if (!strcasecmp(v->name, "dbsecret")) { 09692 ast_string_field_set(user, dbsecret, v->value); 09693 } else if (!strcasecmp(v->name, "secret")) { 09694 if (!ast_strlen_zero(user->secret)) { 09695 char *old = ast_strdupa(user->secret); 09696 09697 ast_string_field_build(user, secret, "%s;%s", old, v->value); 09698 } else 09699 ast_string_field_set(user, secret, v->value); 09700 } else if (!strcasecmp(v->name, "callerid")) { 09701 if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) { 09702 char name2[80]; 09703 char num2[80]; 09704 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 09705 ast_string_field_set(user, cid_name, name2); 09706 ast_string_field_set(user, cid_num, num2); 09707 ast_set_flag(user, IAX_HASCALLERID); 09708 } else { 09709 ast_clear_flag(user, IAX_HASCALLERID); 09710 ast_string_field_set(user, cid_name, ""); 09711 ast_string_field_set(user, cid_num, ""); 09712 } 09713 } else if (!strcasecmp(v->name, "fullname")) { 09714 if (!ast_strlen_zero(v->value)) { 09715 ast_string_field_set(user, cid_name, v->value); 09716 ast_set_flag(user, IAX_HASCALLERID); 09717 } else { 09718 ast_string_field_set(user, cid_name, ""); 09719 if (ast_strlen_zero(user->cid_num)) 09720 ast_clear_flag(user, IAX_HASCALLERID); 09721 } 09722 } else if (!strcasecmp(v->name, "cid_number")) { 09723 if (!ast_strlen_zero(v->value)) { 09724 ast_string_field_set(user, cid_num, v->value); 09725 ast_set_flag(user, IAX_HASCALLERID); 09726 } else { 09727 ast_string_field_set(user, cid_num, ""); 09728 if (ast_strlen_zero(user->cid_name)) 09729 ast_clear_flag(user, IAX_HASCALLERID); 09730 } 09731 } else if (!strcasecmp(v->name, "accountcode")) { 09732 ast_string_field_set(user, accountcode, v->value); 09733 } else if (!strcasecmp(v->name, "mohinterpret")) { 09734 ast_string_field_set(user, mohinterpret, v->value); 09735 } else if (!strcasecmp(v->name, "mohsuggest")) { 09736 ast_string_field_set(user, mohsuggest, v->value); 09737 } else if (!strcasecmp(v->name, "language")) { 09738 ast_string_field_set(user, language, v->value); 09739 } else if (!strcasecmp(v->name, "amaflags")) { 09740 format = ast_cdr_amaflags2int(v->value); 09741 if (format < 0) { 09742 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 09743 } else { 09744 user->amaflags = format; 09745 } 09746 } else if (!strcasecmp(v->name, "inkeys")) { 09747 ast_string_field_set(user, inkeys, v->value); 09748 } else if (!strcasecmp(v->name, "maxauthreq")) { 09749 user->maxauthreq = atoi(v->value); 09750 if (user->maxauthreq < 0) 09751 user->maxauthreq = 0; 09752 } else if (!strcasecmp(v->name, "adsi")) { 09753 user->adsi = ast_true(v->value); 09754 }/* else if (strcasecmp(v->name,"type")) */ 09755 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 09756 v = v->next; 09757 if (!v) { 09758 v = alt; 09759 alt = NULL; 09760 } 09761 } 09762 if (!user->authmethods) { 09763 if (!ast_strlen_zero(user->secret)) { 09764 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09765 if (!ast_strlen_zero(user->inkeys)) 09766 user->authmethods |= IAX_AUTH_RSA; 09767 } else if (!ast_strlen_zero(user->inkeys)) { 09768 user->authmethods = IAX_AUTH_RSA; 09769 } else { 09770 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09771 } 09772 } 09773 ast_clear_flag(user, IAX_DELME); 09774 } 09775 cleanup: 09776 if (oldha) 09777 ast_free_ha(oldha); 09778 if (oldcon) 09779 free_context(oldcon); 09780 return user; 09781 }
| static int cache_get_callno_locked | ( | const char * | data | ) | [static] |
Definition at line 10286 of file chan_iax2.c.
References ARRAY_LEN, AST_FRAME_IAX, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), iax_ie_data::buf, iax2_registry::callno, 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, iaxs, iaxsl, parsed_dial_string::key, LOG_DEBUG, LOG_WARNING, NEW_FORCE, option_debug, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, iax_ie_data::pos, iax2_registry::secret, send_command(), create_addr_info::sockfd, and parsed_dial_string::username.
Referenced by find_cache().
10287 { 10288 struct sockaddr_in sin; 10289 int x; 10290 int callno; 10291 struct iax_ie_data ied; 10292 struct create_addr_info cai; 10293 struct parsed_dial_string pds; 10294 char *tmpstr; 10295 10296 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 10297 /* Look for an *exact match* call. Once a call is negotiated, it can only 10298 look up entries for a single context */ 10299 if (!ast_mutex_trylock(&iaxsl[x])) { 10300 if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot)) 10301 return x; 10302 ast_mutex_unlock(&iaxsl[x]); 10303 } 10304 } 10305 10306 /* No match found, we need to create a new one */ 10307 10308 memset(&cai, 0, sizeof(cai)); 10309 memset(&ied, 0, sizeof(ied)); 10310 memset(&pds, 0, sizeof(pds)); 10311 10312 tmpstr = ast_strdupa(data); 10313 parse_dial_string(tmpstr, &pds); 10314 10315 if (ast_strlen_zero(pds.peer)) { 10316 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data); 10317 return -1; 10318 } 10319 10320 /* Populate our address from the given */ 10321 if (create_addr(pds.peer, NULL, &sin, &cai)) 10322 return -1; 10323 10324 if (option_debug) 10325 ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n", 10326 pds.peer, pds.username, pds.password, pds.context); 10327 10328 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 10329 if (callno < 1) { 10330 ast_log(LOG_WARNING, "Unable to create call\n"); 10331 return -1; 10332 } 10333 10334 ast_string_field_set(iaxs[callno], dproot, data); 10335 iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH; 10336 10337 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 10338 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD"); 10339 /* the string format is slightly different from a standard dial string, 10340 because the context appears in the 'exten' position 10341 */ 10342 if (pds.exten) 10343 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten); 10344 if (pds.username) 10345 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 10346 iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH); 10347 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH); 10348 /* Keep password handy */ 10349 if (pds.password) 10350 ast_string_field_set(iaxs[callno], secret, pds.password); 10351 if (pds.key) 10352 ast_string_field_set(iaxs[callno], outkey, pds.key); 10353 /* Start the call going */ 10354 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 10355 10356 return callno; 10357 }
| static unsigned int calc_rxstamp | ( | struct chan_iax2_pvt * | p, | |
| unsigned int | offset | |||
| ) | [static] |
Definition at line 3990 of file chan_iax2.c.
References ast_log(), ast_random(), ast_tvsub(), chan_iax2_pvt::callno, LOG_DEBUG, option_debug, and chan_iax2_pvt::rxcore.
03991 { 03992 /* Returns where in "receive time" we are. That is, how many ms 03993 since we received (or would have received) the frame with timestamp 0 */ 03994 int ms; 03995 #ifdef IAXTESTS 03996 int jit; 03997 #endif /* IAXTESTS */ 03998 /* Setup rxcore if necessary */ 03999 if (ast_tvzero(p->rxcore)) { 04000 p->rxcore = ast_tvnow(); 04001 if (option_debug && iaxdebug) 04002 ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n", 04003 p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset); 04004 p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000)); 04005 #if 1 04006 if (option_debug && iaxdebug) 04007 ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n", 04008 p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec)); 04009 #endif 04010 } 04011 04012 ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore); 04013 #ifdef IAXTESTS 04014 if (test_jit) { 04015 if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) { 04016 jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0)); 04017 if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0))) 04018 jit = -jit; 04019 ms += jit; 04020 } 04021 } 04022 if (test_late) { 04023 ms += test_late; 04024 test_late = 0; 04025 } 04026 #endif /* IAXTESTS */ 04027 return ms; 04028 }
| static unsigned int calc_timestamp | ( | struct chan_iax2_pvt * | p, | |
| unsigned int | ts, | |||
| struct ast_frame * | f | |||
| ) | [static] |
Definition at line 3861 of file chan_iax2.c.
References AST_FRAME_CNG, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_tvadd(), ast_tvsub(), chan_iax2_pvt::callno, ast_frame::delivery, ast_frame::frametype, iaxs, chan_iax2_pvt::lastsent, LOG_DEBUG, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, chan_iax2_pvt::offset, option_debug, chan_iax2_pvt::peercallno, and ast_frame::samples.
Referenced by iax2_send(), and socket_process().
03862 { 03863 int ms; 03864 int voice = 0; 03865 int genuine = 0; 03866 int adjust; 03867 struct timeval *delivery = NULL; 03868 03869 03870 /* What sort of frame do we have?: voice is self-explanatory 03871 "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK 03872 non-genuine frames are CONTROL frames [ringing etc], DTMF 03873 The "genuine" distinction is needed because genuine frames must get a clock-based timestamp, 03874 the others need a timestamp slaved to the voice frames so that they go in sequence 03875 */ 03876 if (f) { 03877 if (f->frametype == AST_FRAME_VOICE) { 03878 voice = 1; 03879 delivery = &f->delivery; 03880 } else if (f->frametype == AST_FRAME_IAX) { 03881 genuine = 1; 03882 } else if (f->frametype == AST_FRAME_CNG) { 03883 p->notsilenttx = 0; 03884 } 03885 } 03886 if (ast_tvzero(p->offset)) { 03887 gettimeofday(&p->offset, NULL); 03888 /* Round to nearest 20ms for nice looking traces */ 03889 p->offset.tv_usec -= p->offset.tv_usec % 20000; 03890 } 03891 /* If the timestamp is specified, just send it as is */ 03892 if (ts) 03893 return ts; 03894 /* If we have a time that the frame arrived, always use it to make our timestamp */ 03895 if (delivery && !ast_tvzero(*delivery)) { 03896 ms = ast_tvdiff_ms(*delivery, p->offset); 03897 if (option_debug > 2 && iaxdebug) 03898 ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno); 03899 } else { 03900 ms = ast_tvdiff_ms(ast_tvnow(), p->offset); 03901 if (ms < 0) 03902 ms = 0; 03903 if (voice) { 03904 /* On a voice frame, use predicted values if appropriate */ 03905 if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) { 03906 /* Adjust our txcore, keeping voice and non-voice synchronized */ 03907 /* AN EXPLANATION: 03908 When we send voice, we usually send "calculated" timestamps worked out 03909 on the basis of the number of samples sent. When we send other frames, 03910 we usually send timestamps worked out from the real clock. 03911 The problem is that they can tend to drift out of step because the 03912 source channel's clock and our clock may not be exactly at the same rate. 03913 We fix this by continuously "tweaking" p->offset. p->offset is "time zero" 03914 for this call. Moving it adjusts timestamps for non-voice frames. 03915 We make the adjustment in the style of a moving average. Each time we 03916 adjust p->offset by 10% of the difference between our clock-derived 03917 timestamp and the predicted timestamp. That's why you see "10000" 03918 below even though IAX2 timestamps are in milliseconds. 03919 The use of a moving average avoids offset moving too radically. 03920 Generally, "adjust" roams back and forth around 0, with offset hardly 03921 changing at all. But if a consistent different starts to develop it 03922 will be eliminated over the course of 10 frames (200-300msecs) 03923 */ 03924 adjust = (ms - p->nextpred); 03925 if (adjust < 0) 03926 p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000)); 03927 else if (adjust > 0) 03928 p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000)); 03929 03930 if (!p->nextpred) { 03931 p->nextpred = ms; /*f->samples / 8;*/ 03932 if (p->nextpred <= p->lastsent) 03933 p->nextpred = p->lastsent + 3; 03934 } 03935 ms = p->nextpred; 03936 } else { 03937 /* in this case, just use the actual 03938 * time, since we're either way off 03939 * (shouldn't happen), or we're ending a 03940 * silent period -- and seed the next 03941 * predicted time. Also, round ms to the 03942 * next multiple of frame size (so our 03943 * silent periods are multiples of 03944 * frame size too) */ 03945 03946 if (option_debug && iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW ) 03947 ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n", 03948 abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW); 03949 03950 if (f->samples >= 8) /* check to make sure we dont core dump */ 03951 { 03952 int diff = ms % (f->samples / 8); 03953 if (diff) 03954 ms += f->samples/8 - diff; 03955 } 03956 03957 p->nextpred = ms; 03958 p->notsilenttx = 1; 03959 } 03960 } else if ( f->frametype == AST_FRAME_VIDEO ) { 03961 /* 03962 * IAX2 draft 03 says that timestamps MUST be in order. 03963 * It does not say anything about several frames having the same timestamp 03964 * When transporting video, we can have a frame that spans multiple iax packets 03965 * (so called slices), so it would make sense to use the same timestamp for all of 03966 * them 03967 * We do want to make sure that frames don't go backwards though 03968 */ 03969 if ( (unsigned int)ms < p->lastsent ) 03970 ms = p->lastsent; 03971 } else { 03972 /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless 03973 it's a genuine frame */ 03974 if (genuine) { 03975 /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */ 03976 if (ms <= p->lastsent) 03977 ms = p->lastsent + 3; 03978 } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) { 03979 /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */ 03980 ms = p->lastsent + 3; 03981 } 03982 } 03983 } 03984 p->lastsent = ms; 03985 if (voice) 03986 p->nextpred = p->nextpred + f->samples / 8; 03987 return ms; 03988 }
| static unsigned int calc_txpeerstamp | ( | struct iax2_trunk_peer * | tpeer, | |
| int | sampms, | |||
| struct timeval * | tv | |||
| ) | [static] |
Definition at line 3817 of file chan_iax2.c.
References iax2_trunk_peer::lastsent, iax2_trunk_peer::lasttxtime, MAX_TIMESTAMP_SKEW, iax2_trunk_peer::trunkact, and iax2_trunk_peer::txtrunktime.
Referenced by send_trunk().
03818 { 03819 unsigned long int mssincetx; /* unsigned to handle overflows */ 03820 long int ms, pred; 03821 03822 tpeer->trunkact = *tv; 03823 mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime); 03824 if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) { 03825 /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */ 03826 tpeer->txtrunktime = *tv; 03827 tpeer->lastsent = 999999; 03828 } 03829 /* Update last transmit time now */ 03830 tpeer->lasttxtime = *tv; 03831 03832 /* Calculate ms offset */ 03833 ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime); 03834 /* Predict from last value */ 03835 pred = tpeer->lastsent + sampms; 03836 if (abs(ms - pred) < MAX_TIMESTAMP_SKEW) 03837 ms = pred; 03838 03839 /* We never send the same timestamp twice, so fudge a little if we must */ 03840 if (ms == tpeer->lastsent) 03841 ms = tpeer->lastsent + 1; 03842 tpeer->lastsent = ms; 03843 return ms; 03844 }
| static int check_access | ( | int | callno, | |
| struct sockaddr_in * | sin, | |||
| struct iax_ies * | ies | |||
| ) | [static] |
Definition at line 5115 of file chan_iax2.c.
References 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, 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, cid_name, cid_num, iax_ies::codec_prefs, iax2_context::context, iax2_user::contexts, iax_ies::dnid, iax2_user::encmethods, chan_iax2_pvt::encmethods, exten, iax_ies::format, iax2_user::ha, iax2_getpeertrunk(), 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, iaxs, iax_ies::language, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, 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(), iax2_registry::secret, user_unref(), iax_ies::username, users, ast_variable::value, chan_iax2_pvt::vars, iax2_user::vars, and iax_ies::version.
Referenced by socket_process().
05116 { 05117 /* Start pessimistic */ 05118 int res = -1; 05119 int version = 2; 05120 struct iax2_user *user = NULL, *best = NULL; 05121 int bestscore = 0; 05122 int gotcapability = 0; 05123 struct ast_variable *v = NULL, *tmpvar = NULL; 05124 struct ao2_iterator i; 05125 05126 if (!iaxs[callno]) 05127 return res; 05128 if (ies->called_number) 05129 ast_string_field_set(iaxs[callno], exten, ies->called_number); 05130 if (ies->calling_number) { 05131 ast_shrink_phone_number(ies->calling_number); 05132 ast_string_field_set(iaxs[callno], cid_num, ies->calling_number); 05133 } 05134 if (ies->calling_name) 05135 ast_string_field_set(iaxs[callno], cid_name, ies->calling_name); 05136 if (ies->calling_ani) 05137 ast_string_field_set(iaxs[callno], ani, ies->calling_ani); 05138 if (ies->dnid) 05139 ast_string_field_set(iaxs[callno], dnid, ies->dnid); 05140 if (ies->rdnis) 05141 ast_string_field_set(iaxs[callno], rdnis, ies->rdnis); 05142 if (ies->called_context) 05143 ast_string_field_set(iaxs[callno], context, ies->called_context); 05144 if (ies->language) 05145 ast_string_field_set(iaxs[callno], language, ies->language); 05146 if (ies->username) 05147 ast_string_field_set(iaxs[callno], username, ies->username); 05148 if (ies->calling_ton > -1) 05149 iaxs[callno]->calling_ton = ies->calling_ton; 05150 if (ies->calling_tns > -1) 05151 iaxs[callno]->calling_tns = ies->calling_tns; 05152 if (ies->calling_pres > -1) 05153 iaxs[callno]->calling_pres = ies->calling_pres; 05154 if (ies->format) 05155 iaxs[callno]->peerformat = ies->format; 05156 if (ies->adsicpe) 05157 iaxs[callno]->peeradsicpe = ies->adsicpe; 05158 if (ies->capability) { 05159 gotcapability = 1; 05160 iaxs[callno]->peercapability = ies->capability; 05161 } 05162 if (ies->version) 05163 version = ies->version; 05164 05165 /* Use provided preferences until told otherwise for actual preferences */ 05166 if(ies->codec_prefs) { 05167 ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0); 05168 ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0); 05169 } 05170 05171 if (!gotcapability) 05172 iaxs[callno]->peercapability = iaxs[callno]->peerformat; 05173 if (version > IAX_PROTO_VERSION) { 05174 ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 05175 ast_inet_ntoa(sin->sin_addr), version); 05176 return res; 05177 } 05178 /* Search the userlist for a compatible entry, and fill in the rest */ 05179 i = ao2_iterator_init(users, 0); 05180 while ((user = ao2_iterator_next(&i))) { 05181 if ((ast_strlen_zero(iaxs[callno]->username) || /* No username specified */ 05182 !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */ 05183 && ast_apply_ha(user->ha, sin) /* Access is permitted from this IP */ 05184 && (ast_strlen_zero(iaxs[callno]->context) || /* No context specified */ 05185 apply_context(user->contexts, iaxs[callno]->context))) { /* Context is permitted */ 05186 if (!ast_strlen_zero(iaxs[callno]->username)) { 05187 /* Exact match, stop right now. */ 05188 if (best) 05189 user_unref(best); 05190 best = user; 05191 break; 05192 } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) { 05193 /* No required authentication */ 05194 if (user->ha) { 05195 /* There was host authentication and we passed, bonus! */ 05196 if (bestscore < 4) { 05197 bestscore = 4; 05198 if (best) 05199 user_unref(best); 05200 best = user; 05201 continue; 05202 } 05203 } else { 05204 /* No host access, but no secret, either, not bad */ 05205 if (bestscore < 3) { 05206 bestscore = 3; 05207 if (best) 05208 user_unref(best); 05209 best = user; 05210 continue; 05211 } 05212 } 05213 } else { 05214 if (user->ha) { 05215 /* Authentication, but host access too, eh, it's something.. */ 05216 if (bestscore < 2) { 05217 bestscore = 2; 05218 if (best) 05219 user_unref(best); 05220 best = user; 05221 continue; 05222 } 05223 } else { 05224 /* Authentication and no host access... This is our baseline */ 05225 if (bestscore < 1) { 05226 bestscore = 1; 05227 if (best) 05228 user_unref(best); 05229 best = user; 05230 continue; 05231 } 05232 } 05233 } 05234 } 05235 user_unref(user); 05236 } 05237 user = best; 05238 if (!user && !ast_strlen_zero(iaxs[callno]->username)) { 05239 user = realtime_user(iaxs[callno]->username, sin); 05240 if (user && !ast_strlen_zero(iaxs[callno]->context) && /* No context specified */ 05241 !apply_context(user->contexts, iaxs[callno]->context)) { /* Context is permitted */ 05242 user = user_unref(user); 05243 } 05244 } 05245 if (user) { 05246 /* We found our match (use the first) */ 05247 /* copy vars */ 05248 for (v = user->vars ; v ; v = v->next) { 05249 if((tmpvar = ast_variable_new(v->name, v->value))) { 05250 tmpvar->next = iaxs[callno]->vars; 05251 iaxs[callno]->vars = tmpvar; 05252 } 05253 } 05254 /* If a max AUTHREQ restriction is in place, activate it */ 05255 if (user->maxauthreq > 0) 05256 ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ); 05257 iaxs[callno]->prefs = user->prefs; 05258 ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST); 05259 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS); 05260 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP); 05261 iaxs[callno]->encmethods = user->encmethods; 05262 /* Store the requested username if not specified */ 05263 if (ast_strlen_zero(iaxs[callno]->username)) 05264 ast_string_field_set(iaxs[callno], username, user->name); 05265 /* Store whether this is a trunked call, too, of course, and move if appropriate */ 05266 ast_copy_flags(iaxs[callno], user, IAX_TRUNK); 05267 iaxs[callno]->capability = user->capability; 05268 /* And use the default context */ 05269 if (ast_strlen_zero(iaxs[callno]->context)) { 05270 if (user->contexts) 05271 ast_string_field_set(iaxs[callno], context, user->contexts->context); 05272 else 05273 ast_string_field_set(iaxs[callno], context, context); 05274 } 05275 /* And any input keys */ 05276 ast_string_field_set(iaxs[callno], inkeys, user->inkeys); 05277 /* And the permitted authentication methods */ 05278 iaxs[callno]->authmethods = user->authmethods; 05279 iaxs[callno]->adsi = user->adsi; 05280 /* If they have callerid, override the given caller id. Always store the ANI */ 05281 if (!ast_strlen_zero(iaxs[callno]->cid_num) || !ast_strlen_zero(iaxs[callno]->cid_name)) { 05282 if (ast_test_flag(user, IAX_HASCALLERID)) { 05283 iaxs[callno]->calling_tns = 0; 05284 iaxs[callno]->calling_ton = 0; 05285 ast_string_field_set(iaxs[callno], cid_num, user->cid_num); 05286 ast_string_field_set(iaxs[callno], cid_name, user->cid_name); 05287 iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 05288 } 05289 if (ast_strlen_zero(iaxs[callno]->ani)) 05290 ast_string_field_set(iaxs[callno], ani, user->cid_num); 05291 } else { 05292 iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE; 05293 } 05294 if (!ast_strlen_zero(user->accountcode)) 05295 ast_string_field_set(iaxs[callno], accountcode, user->accountcode); 05296 if (!ast_strlen_zero(user->mohinterpret)) 05297 ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret); 05298 if (!ast_strlen_zero(user->mohsuggest)) 05299 ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest); 05300 if (user->amaflags) 05301 iaxs[callno]->amaflags = user->amaflags; 05302 if (!ast_strlen_zero(user->language)) 05303 ast_string_field_set(iaxs[callno], language, user->language); 05304 ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 05305 /* Keep this check last */ 05306 if (!ast_strlen_zero(user->dbsecret)) { 05307 char *family, *key=NULL; 05308 char buf[80]; 05309 family = ast_strdupa(user->dbsecret); 05310 key = strchr(family, '/'); 05311 if (key) { 05312 *key = '\0'; 05313 key++; 05314 } 05315 if (!key || ast_db_get(family, key, buf, sizeof(buf))) 05316 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret); 05317 else 05318 ast_string_field_set(iaxs[callno], secret, buf); 05319 } else 05320 ast_string_field_set(iaxs[callno], secret, user->secret); 05321 res = 0; 05322 user = user_unref(user); 05323 } 05324 ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK); 05325 return res; 05326 }
| static int check_provisioning | ( | struct sockaddr_in * | sin, | |
| int | sockfd, | |||
| char * | si, | |||
| unsigned int | ver | |||
| ) | [static] |
Definition at line 6802 of file chan_iax2.c.
References ast_log(), iax2_provision(), iax_provision_version(), LOG_DEBUG, and option_debug.
Referenced by socket_process().
06803 { 06804 unsigned int ourver; 06805 char rsi[80]; 06806 snprintf(rsi, sizeof(rsi), "si-%s", si); 06807 if (iax_provision_version(&ourver, rsi, 1)) 06808 return 0; 06809 if (option_debug) 06810 ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver); 06811 if (ourver != ver) 06812 iax2_provision(sin, sockfd, NULL, rsi, 1); 06813 return 0; 06814 }
| static int check_srcaddr | ( | struct sockaddr * | sa, | |
| socklen_t | salen | |||
| ) | [static] |
Check if address can be used as packet source.
Definition at line 9209 of file chan_iax2.c.
References ast_log(), errno, LOG_DEBUG, LOG_ERROR, and option_debug.
Referenced by peer_set_srcaddr().
09210 { 09211 int sd; 09212 int res; 09213 09214 sd = socket(AF_INET, SOCK_DGRAM, 0); 09215 if (sd < 0) { 09216 ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno)); 09217 return -1; 09218 } 09219 09220 res = bind(sd, sa, salen); 09221 if (res < 0) { 09222 if (option_debug) 09223 ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno)); 09224 close(sd); 09225 return 1; 09226 } 09227 09228 close(sd); 09229 return 0; 09230 }
| static int complete_dpreply | ( | struct chan_iax2_pvt * | pvt, | |
| struct iax_ies * | ies | |||
| ) | [static] |
Definition at line 5806 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_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, chan_iax2_pvt::dpentries, iax_ies::dpstatus, iax2_dpcache::expiry, expiry, iax2_dpcache::exten, exten, iax2_dpcache::flags, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax2_dpcache::orig, iax2_dpcache::peer, iax_ies::refresh, and iax2_dpcache::waiters.
Referenced by socket_process().
05807 { 05808 char exten[256] = ""; 05809 int status = CACHE_FLAG_UNKNOWN; 05810 int expiry = iaxdefaultdpcache; 05811 int x; 05812 int matchmore = 0; 05813 struct iax2_dpcache *dp, *prev; 05814 05815 if (ies->called_number) 05816 ast_copy_string(exten, ies->called_number, sizeof(exten)); 05817 05818 if (ies->dpstatus & IAX_DPSTATUS_EXISTS) 05819 status = CACHE_FLAG_EXISTS; 05820 else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST) 05821 status = CACHE_FLAG_CANEXIST; 05822 else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT) 05823 status = CACHE_FLAG_NONEXISTENT; 05824 05825 if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) { 05826 /* Don't really do anything with this */ 05827 } 05828 if (ies->refresh) 05829 expiry = ies->refresh; 05830 if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE) 05831 matchmore = CACHE_FLAG_MATCHMORE; 05832 ast_mutex_lock(&dpcache_lock); 05833 prev = NULL; 05834 dp = pvt->dpentries; 05835 while(dp) { 05836 if (!strcmp(dp->exten, exten)) { 05837 /* Let them go */ 05838 if (prev) 05839 prev->peer = dp->peer; 05840 else 05841 pvt->dpentries = dp->peer; 05842 dp->peer = NULL; 05843 dp->callno = 0; 05844 dp->expiry.tv_sec = dp->orig.tv_sec + expiry; 05845 if (dp->flags & CACHE_FLAG_PENDING) { 05846 dp->flags &= ~CACHE_FLAG_PENDING; 05847 dp->flags |= status; 05848 dp->flags |= matchmore; 05849 } 05850 /* Wake up waiters */ 05851 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 05852 if (dp->waiters[x] > -1) 05853 write(dp->waiters[x], "asdf", 4); 05854 } 05855 prev = dp; 05856 dp = dp->peer; 05857 } 05858 ast_mutex_unlock(&dpcache_lock); 05859 return 0; 05860 }
| static char* complete_iax2_show_peer | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 2409 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_strdup, peer_unref(), and peers.
02410 { 02411 int which = 0; 02412 struct iax2_peer *peer; 02413 char *res = NULL; 02414 int wordlen = strlen(word); 02415 struct ao2_iterator i; 02416 02417 /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */ 02418 if (pos != 3) 02419 return NULL; 02420 02421 i = ao2_iterator_init(peers, 0); 02422 while ((peer = ao2_iterator_next(&i))) { 02423 if (!strncasecmp(peer->name, word, wordlen) && ++which > state) { 02424 res = ast_strdup(peer->name); 02425 peer_unref(peer); 02426 break; 02427 } 02428 peer_unref(peer); 02429 } 02430 02431 return res; 02432 }
| static int complete_transfer | ( | int | callno, | |
| struct iax_ies * | ies | |||
| ) | [static] |
Definition at line 5862 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(), iaxq, iaxs, 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, chan_iax2_pvt::pingtime, remove_by_peercallno(), 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().
05863 { 05864 int peercallno = 0; 05865 struct chan_iax2_pvt *pvt = iaxs[callno]; 05866 struct iax_frame *cur; 05867 jb_frame frame; 05868 05869 if (ies->callno) 05870 peercallno = ies->callno; 05871 05872 if (peercallno < 1) { 05873 ast_log(LOG_WARNING, "Invalid transfer request\n"); 05874 return -1; 05875 } 05876 memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr)); 05877 memset(&pvt->transfer, 0, sizeof(pvt->transfer)); 05878 /* Reset sequence numbers */ 05879 pvt->oseqno = 0; 05880 pvt->rseqno = 0; 05881 pvt->iseqno = 0; 05882 pvt->aseqno = 0; 05883 05884 if (pvt->peercallno) { 05885 remove_by_peercallno(pvt); 05886 } 05887 pvt->peercallno = peercallno; 05888 store_by_peercallno(pvt); 05889 05890 pvt->transferring = TRANSFER_NONE; 05891 pvt->svoiceformat = -1; 05892 pvt->voiceformat = 0; 05893 pvt->svideoformat = -1; 05894 pvt->videoformat = 0; 05895 pvt->transfercallno = -1; 05896 memset(&pvt->rxcore, 0, sizeof(pvt->rxcore)); 05897 memset(&pvt->offset, 0, sizeof(pvt->offset)); 05898 /* reset jitterbuffer */ 05899 while(jb_getall(pvt->jb,&frame) == JB_OK) 05900 iax2_frame_free(frame.data); 05901 jb_reset(pvt->jb); 05902 pvt->lag = 0; 05903 pvt->last = 0; 05904 pvt->lastsent = 0; 05905 pvt->nextpred = 0; 05906 pvt->pingtime = DEFAULT_RETRY_TIME; 05907 AST_LIST_LOCK(&iaxq.queue); 05908 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 05909 /* We must cancel any packets that would have been transmitted 05910 because now we're talking to someone new. It's okay, they 05911 were transmitted to someone that didn't care anyway. */ 05912 if (callno == cur->callno) 05913 cur->retries = -1; 05914 } 05915 AST_LIST_UNLOCK(&iaxq.queue); 05916 return 0; 05917 }
| static unsigned char compress_subclass | ( | int | subclass | ) | [static] |
Definition at line 1070 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().
01071 { 01072 int x; 01073 int power=-1; 01074 /* If it's 128 or smaller, just return it */ 01075 if (subclass < IAX_FLAG_SC_LOG) 01076 return subclass; 01077 /* Otherwise find its power */ 01078 for (x = 0; x < IAX_MAX_SHIFT; x++) { 01079 if (subclass & (1 << x)) { 01080 if (power > -1) { 01081 ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass); 01082 return 0; 01083 } else 01084 power = x; 01085 } 01086 } 01087 return power | IAX_FLAG_SC_LOG; 01088 }
| static void construct_rr | ( | struct chan_iax2_pvt * | pvt, | |
| struct iax_ie_data * | iep | |||
| ) | [static] |
Definition at line 6816 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().
06817 { 06818 jb_info stats; 06819 jb_getinfo(pvt->jb, &stats); 06820 06821 memset(iep, 0, sizeof(*iep)); 06822 06823 iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter); 06824 if(stats.frames_in == 0) stats.frames_in = 1; 06825 iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff))); 06826 iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in); 06827 iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min); 06828 iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped); 06829 iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo); 06830 }
| static int create_addr | ( | const char * | peername, | |
| struct ast_channel * | c, | |||
| struct sockaddr_in * | sin, | |||
| struct create_addr_info * | cai | |||
| ) | [static] |
Definition at line 3026 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_db_get(), ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::capability, create_addr_info::capability, create_addr_info::context, iax2_peer::defaddr, iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, hp, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_peer::lastms, LOG_DEBUG, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, create_addr_info::outkey, peer_unref(), create_addr_info::peercontext, iax2_peer::prefs, create_addr_info::prefs, prefs, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, and create_addr_info::username.
03027 { 03028 struct ast_hostent ahp; 03029 struct hostent *hp; 03030 struct iax2_peer *peer; 03031 int res = -1; 03032 struct ast_codec_pref ourprefs; 03033 03034 ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK); 03035 cai->sockfd = defaultsockfd; 03036 cai->maxtime = 0; 03037 sin->sin_family = AF_INET; 03038 03039 if (!(peer = find_peer(peername, 1))) { 03040 cai->found = 0; 03041 03042 hp = ast_gethostbyname(peername, &ahp); 03043 if (hp) { 03044 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 03045 sin->sin_port = htons(IAX_DEFAULT_PORTNO); 03046 /* use global iax prefs for unknown peer/user */ 03047 /* But move the calling channel's native codec to the top of the preference list */ 03048 memcpy(&ourprefs, &prefs, sizeof(ourprefs)); 03049 if (c) 03050 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 03051 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 03052 return 0; 03053 } else { 03054 ast_log(LOG_WARNING, "No such host: %s\n", peername); 03055 return -1; 03056 } 03057 } 03058 03059 cai->found = 1; 03060 03061 /* if the peer has no address (current or default), return failure */ 03062 if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) 03063 goto return_unref; 03064 03065 /* if the peer is being monitored and is currently unreachable, return failure */ 03066 if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0))) 03067 goto return_unref; 03068 03069 ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 03070 cai->maxtime = peer->maxms; 03071 cai->capability = peer->capability; 03072 cai->encmethods = peer->encmethods; 03073 cai->sockfd = peer->sockfd; 03074 cai->adsi = peer->adsi; 03075 memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs)); 03076 /* Move the calling channel's native codec to the top of the preference list */ 03077 if (c) { 03078 ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats); 03079 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 03080 } 03081 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 03082 ast_copy_string(cai->context, peer->context, sizeof(cai->context)); 03083 ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext)); 03084 ast_copy_string(cai->username, peer->username, sizeof(cai->username)); 03085 ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone)); 03086 ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey)); 03087 ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret)); 03088 ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest)); 03089 if (ast_strlen_zero(peer->dbsecret)) { 03090 ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret)); 03091 } else { 03092 char *family; 03093 char *key = NULL; 03094 03095 family = ast_strdupa(peer->dbsecret); 03096 key = strchr(family, '/'); 03097 if (key) 03098 *key++ = '\0'; 03099 if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) { 03100 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret); 03101 goto return_unref; 03102 } 03103 } 03104 03105 if (peer->addr.sin_addr.s_addr) { 03106 sin->sin_addr = peer->addr.sin_addr; 03107 sin->sin_port = peer->addr.sin_port; 03108 } else { 03109 sin->sin_addr = peer->defaddr.sin_addr; 03110 sin->sin_port = peer->defaddr.sin_port; 03111 } 03112 03113 res = 0; 03114 03115 return_unref: 03116 peer_unref(peer); 03117 03118 return res; 03119 }
| static int decode_frame | ( | aes_decrypt_ctx * | dcx, | |
| struct ast_iax2_full_hdr * | fh, | |||
| struct ast_frame * | f, | |||
| int * | datalen | |||
| ) | [static] |
Definition at line 4185 of file chan_iax2.c.
References AST_FRAME_VIDEO, ast_log(), ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, ast_frame::frametype, IAX_FLAG_FULL, LOG_DEBUG, memcpy_decrypt(), option_debug, ast_iax2_full_hdr::scallno, ast_frame::subclass, ast_iax2_full_hdr::type, and uncompress_subclass().
Referenced by decrypt_frame(), and update_packet().
04186 { 04187 int padding; 04188 unsigned char *workspace; 04189 04190 workspace = alloca(*datalen); 04191 memset(f, 0, sizeof(*f)); 04192 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 04193 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 04194 if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr)) 04195 return -1; 04196 /* Decrypt */ 04197 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx); 04198 04199 padding = 16 + (workspace[15] & 0xf); 04200 if (option_debug && iaxdebug) 04201 ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]); 04202 if (*datalen < padding + sizeof(struct ast_iax2_full_hdr)) 04203 return -1; 04204 04205 *datalen -= padding; 04206 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 04207 f->frametype = fh->type; 04208 if (f->frametype == AST_FRAME_VIDEO) { 04209 f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 04210 } else { 04211 f->subclass = uncompress_subclass(fh->csub); 04212 } 04213 } else { 04214 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 04215 if (option_debug && iaxdebug) 04216 ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen); 04217 if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr)) 04218 return -1; 04219 /* Decrypt */ 04220 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx); 04221 padding = 16 + (workspace[15] & 0x0f); 04222 if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr)) 04223 return -1; 04224 *datalen -= padding; 04225 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 04226 } 04227 return 0; 04228 }
| static int decrypt_frame | ( | int | callno, | |
| struct ast_iax2_full_hdr * | fh, | |||
| struct ast_frame * | f, | |||
| int * | datalen | |||
| ) | [static] |
Definition at line 4271 of file chan_iax2.c.
References ast_set_flag, ast_strdupa, ast_test_flag, build_encryption_keys(), decode_frame(), IAX_KEYPOPULATED, iaxs, MD5Final(), MD5Init(), MD5Update(), iax2_registry::secret, and strsep().
Referenced by socket_process().
04272 { 04273 int res=-1; 04274 if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) { 04275 /* Search for possible keys, given secrets */ 04276 struct MD5Context md5; 04277 unsigned char digest[16]; 04278 char *tmppw, *stringp; 04279 04280 tmppw = ast_strdupa(iaxs[callno]->secret); 04281 stringp = tmppw; 04282 while ((tmppw = strsep(&stringp, ";"))) { 04283 MD5Init(&md5); 04284 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 04285 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 04286 MD5Final(digest, &md5); 04287 build_encryption_keys(digest, iaxs[callno]); 04288 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 04289 if (!res) { 04290 ast_set_flag(iaxs[callno], IAX_KEYPOPULATED); 04291 break; 04292 } 04293 } 04294 } else 04295 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 04296 return res; 04297 }
| 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 6878 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(), and ast_iax2_full_hdr::oseqno.
Referenced by socket_read().
06879 { 06880 struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf; 06881 struct ast_iax2_full_hdr *fh, *cur_fh; 06882 06883 if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len))) 06884 return; 06885 06886 pkt_buf->len = from_here->buf_len; 06887 memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len); 06888 06889 fh = (struct ast_iax2_full_hdr *) pkt_buf->buf; 06890 ast_mutex_lock(&to_here->lock); 06891 AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) { 06892 cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf; 06893 if (fh->oseqno < cur_fh->oseqno) { 06894 AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry); 06895 break; 06896 } 06897 } 06898 AST_LIST_TRAVERSE_SAFE_END 06899 06900 if (!cur_pkt_buf) 06901 AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry); 06902 06903 ast_mutex_unlock(&to_here->lock); 06904 }
| static void delete_users | ( | void | ) | [static] |
Definition at line 9801 of file chan_iax2.c.
References ao2_callback(), ast_dnsmgr_release(), 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, free, iax2_destroy(), iaxs, iaxsl, peer_delme_cb(), peers, chan_iax2_pvt::reg, user_delme_cb(), and users.
09802 { 09803 struct iax2_registry *reg; 09804 09805 ao2_callback(users, 0, user_delme_cb, NULL); 09806 09807 AST_LIST_LOCK(®istrations); 09808 while ((reg = AST_LIST_REMOVE_HEAD(®istrations, entry))) { 09809 ast_sched_del(sched, reg->expire); 09810 if (reg->callno) { 09811 ast_mutex_lock(&iaxsl[reg->callno]); 09812 if (iaxs[reg->callno]) { 09813 iaxs[reg->callno]->reg = NULL; 09814 iax2_destroy(reg->callno); 09815 } 09816 ast_mutex_unlock(&iaxsl[reg->callno]); 09817 } 09818 if (reg->dnsmgr) 09819 ast_dnsmgr_release(reg->dnsmgr); 09820 free(reg); 09821 } 09822 AST_LIST_UNLOCK(®istrations); 09823 09824 ao2_callback(peers, 0, peer_delme_cb, NULL); 09825 }
| static void destroy_firmware | ( | struct iax_firmware * | cur | ) | [static] |
Definition at line 1749 of file chan_iax2.c.
References ast_iax2_firmware_header::datalen, iax_firmware::fd, free, and iax_firmware::fwh.
Referenced by reload_firmware().
01750 { 01751 /* Close firmware */ 01752 if (cur->fwh) { 01753 munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh))); 01754 } 01755 close(cur->fd); 01756 free(cur); 01757 }
| static void dp_lookup | ( | int | callno, | |
| const char * | context, | |||
| const char * | callednum, | |||
| const char * | callerid, | |||
| int | skiplock | |||
| ) | [static] |
Definition at line 6650 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, iaxs, iaxsl, iax_ie_data::pos, and send_command().
Referenced by dp_lookup_thread(), and socket_process().
06651 { 06652 unsigned short dpstatus = 0; 06653 struct iax_ie_data ied1; 06654 int mm; 06655 06656 memset(&ied1, 0, sizeof(ied1)); 06657 mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid); 06658 /* Must be started */ 06659 if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) { 06660 dpstatus = IAX_DPSTATUS_EXISTS; 06661 } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) { 06662 dpstatus = IAX_DPSTATUS_CANEXIST; 06663 } else { 06664 dpstatus = IAX_DPSTATUS_NONEXISTENT; 06665 } 06666 if (ast_ignore_pattern(context, callednum)) 06667 dpstatus |= IAX_DPSTATUS_IGNOREPAT; 06668 if (mm) 06669 dpstatus |= IAX_DPSTATUS_MATCHMORE; 06670 if (!skiplock) 06671 ast_mutex_lock(&iaxsl[callno]); 06672 if (iaxs[callno]) { 06673 iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum); 06674 iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus); 06675 iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache); 06676 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1); 06677 } 06678 if (!skiplock) 06679 ast_mutex_unlock(&iaxsl[callno]); 06680 }
| static void* dp_lookup_thread | ( | void * | data | ) | [static] |
Definition at line 6682 of file chan_iax2.c.
References dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, dp_lookup(), and free.
Referenced by spawn_dp_lookup().
06683 { 06684 /* Look up for dpreq */ 06685 struct dpreq_data *dpr = data; 06686 dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0); 06687 if (dpr->callerid) 06688 free(dpr->callerid); 06689 free(dpr); 06690 return NULL; 06691 }
| static int encrypt_frame | ( | aes_encrypt_ctx * | ecx, | |
| struct ast_iax2_full_hdr * | fh, | |||
| unsigned char * | poo, | |||
| int * | datalen | |||
| ) | [static] |
Definition at line 4230 of file chan_iax2.c.
References ast_log(), ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, IAX_FLAG_FULL, LOG_DEBUG, memcpy_encrypt(), option_debug, ast_iax2_full_hdr::scallno, and ast_iax2_full_hdr::type.
Referenced by iax2_send(), and update_packet().
04231 { 04232 int padding; 04233 unsigned char *workspace; 04234 workspace = alloca(*datalen + 32); 04235 if (!workspace) 04236 return -1; 04237 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 04238 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 04239 if (option_debug && iaxdebug) 04240 ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen); 04241 padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16); 04242 padding = 16 + (padding & 0xf); 04243 memcpy(workspace, poo, padding); 04244 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 04245 workspace[15] &= 0xf0; 04246 workspace[15] |= (padding & 0xf); 04247 if (option_debug && iaxdebug) 04248 ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d + %d padding (15=%02x)\n", fh->type, fh->csub, *datalen, padding, workspace[15]); 04249 *datalen += padding; 04250 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx); 04251 if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr)) 04252 memcpy(poo, workspace + *datalen - 32, 32); 04253 } else { 04254 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 04255 if (option_debug && iaxdebug) 04256 ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen); 04257 padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16); 04258 padding = 16 + (padding & 0xf); 04259 memcpy(workspace, poo, padding); 04260 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 04261 workspace[15] &= 0xf0; 04262 workspace[15] |= (padding & 0x0f); 04263 *datalen += padding; 04264 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx); 04265 if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr)) 04266 memcpy(poo, workspace + *datalen - 32, 32); 04267 } 04268 return 0; 04269 }
| static int expire_registry | ( | const void * | data | ) | [static] |
Definition at line 6099 of file chan_iax2.c.
References __expire_registry(), and schedule_action.
Referenced by iax2_prune_realtime(), realtime_peer(), reg_source_db(), and update_registry().
06100 { 06101 #ifdef SCHED_MULTITHREADED 06102 if (schedule_action(__expire_registry, data)) 06103 #endif 06104 __expire_registry(data); 06105 return 0; 06106 }
| 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 10359 of file chan_iax2.c.
References ast_calloc, ast_channel_defer_dtmf(), ast_channel_undefer_dtmf(), ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_test_flag, ast_waitfor_nandfds(), CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, cache_get_callno_locked(), iax2_dpcache::callno, iax2_registry::callno, dpcache, chan_iax2_pvt::dpentries, iax2_dpcache::expiry, iax2_dpcache::exten, f, iax2_dpcache::flags, free, iax2_dprequest(), IAX_STATE_STARTED, iaxs, iaxsl, LOG_WARNING, iax2_dpcache::next, iax2_dpcache::orig, iax2_dpcache::peer, iax2_dpcache::peercontext, and iax2_dpcache::waiters.
Referenced by iax2_canmatch(), iax2_exec(), iax2_exists(), and iax2_matchmore().
10360 { 10361 struct iax2_dpcache *dp, *prev = NULL, *next; 10362 struct timeval tv; 10363 int x; 10364 int com[2]; 10365 int timeout; 10366 int old=0; 10367 int outfd; 10368 int abort; 10369 int callno; 10370 struct ast_channel *c; 10371 struct ast_frame *f; 10372 gettimeofday(&tv, NULL); 10373 dp = dpcache; 10374 while(dp) { 10375 next = dp->next; 10376 /* Expire old caches */ 10377 if (ast_tvcmp(tv, dp->expiry) > 0) { 10378 /* It's expired, let it disappear */ 10379 if (prev) 10380 prev->next = dp->next; 10381 else 10382 dpcache = dp->next; 10383 if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) { 10384 /* Free memory and go again */ 10385 free(dp); 10386 } else { 10387 ast_log(LOG_WARNING, "DP still has peer field or pending or callno (flags = %d, peer = %p callno = %d)\n", dp->flags, dp->peer, dp->callno); 10388 } 10389 dp = next; 10390 continue; 10391 } 10392 /* We found an entry that matches us! */ 10393 if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 10394 break; 10395 prev = dp; 10396 dp = next; 10397 } 10398 if (!dp) { 10399 /* No matching entry. Create a new one. */ 10400 /* First, can we make a callno? */ 10401 callno = cache_get_callno_locked(data); 10402 if (callno < 0) { 10403 ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data); 10404 return NULL; 10405 } 10406 if (!(dp = ast_calloc(1, sizeof(*dp)))) { 10407 ast_mutex_unlock(&iaxsl[callno]); 10408 return NULL; 10409 } 10410 ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext)); 10411 ast_copy_string(dp->exten, exten, sizeof(dp->exten)); 10412 gettimeofday(&dp->expiry, NULL); 10413 dp->orig = dp->expiry; 10414 /* Expires in 30 mins by default */ 10415 dp->expiry.tv_sec += iaxdefaultdpcache; 10416 dp->next = dpcache; 10417 dp->flags = CACHE_FLAG_PENDING; 10418 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 10419 dp->waiters[x] = -1; 10420 dpcache = dp; 10421 dp->peer = iaxs[callno]->dpentries; 10422 iaxs[callno]->dpentries = dp; 10423 /* Send the request if we're already up */ 10424 if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 10425 iax2_dprequest(dp, callno); 10426 ast_mutex_unlock(&iaxsl[callno]); 10427 } 10428 /* By here we must have a dp */ 10429 if (dp->flags & CACHE_FLAG_PENDING) { 10430 /* Okay, here it starts to get nasty. We need a pipe now to wait 10431 for a reply to come back so long as it's pending */ 10432 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) { 10433 /* Find an empty slot */ 10434 if (dp->waiters[x] < 0) 10435 break; 10436 } 10437 if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) { 10438 ast_log(LOG_WARNING, "No more waiter positions available\n"); 10439 return NULL; 10440 } 10441 if (pipe(com)) { 10442 ast_log(LOG_WARNING, "Unable to create pipe for comm\n"); 10443 return NULL; 10444 } 10445 dp->waiters[x] = com[1]; 10446 /* Okay, now we wait */ 10447 timeout = iaxdefaulttimeout * 1000; 10448 /* Temporarily unlock */ 10449 ast_mutex_unlock(&dpcache_lock); 10450 /* Defer any dtmf */ 10451 if (chan) 10452 old = ast_channel_defer_dtmf(chan); 10453 abort = 0; 10454 while(timeout) { 10455 c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout); 10456 if (outfd > -1) { 10457 break; 10458 } 10459 if (c) { 10460 f = ast_read(c); 10461 if (f) 10462 ast_frfree(f); 10463 else { 10464 /* Got hung up on, abort! */ 10465 break; 10466 abort = 1; 10467 } 10468 } 10469 } 10470 if (!timeout) { 10471 ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten); 10472 } 10473 ast_mutex_lock(&dpcache_lock); 10474 dp->waiters[x] = -1; 10475 close(com[1]); 10476 close(com[0]); 10477 if (abort) { 10478 /* Don't interpret anything, just abort. Not sure what th epoint 10479 of undeferring dtmf on a hung up channel is but hey whatever */ 10480 if (!old && chan) 10481 ast_channel_undefer_dtmf(chan); 10482 return NULL; 10483 } 10484 if (!(dp->flags & CACHE_FLAG_TIMEOUT)) { 10485 /* Now to do non-independent analysis the results of our wait */ 10486 if (dp->flags & CACHE_FLAG_PENDING) { 10487 /* Still pending... It's a timeout. Wake everybody up. Consider it no longer 10488 pending. Don't let it take as long to timeout. */ 10489 dp->flags &= ~CACHE_FLAG_PENDING; 10490 dp->flags |= CACHE_FLAG_TIMEOUT; 10491 /* Expire after only 60 seconds now. This is designed to help reduce backlog in heavily loaded 10492 systems without leaving it unavailable once the server comes back online */ 10493 dp->expiry.tv_sec = dp->orig.tv_sec + 60; 10494 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 10495 if (dp->waiters[x] > -1) 10496 write(dp->waiters[x], "asdf", 4); 10497 } 10498 } 10499 /* Our caller will obtain the rest */ 10500 if (!old && chan) 10501 ast_channel_undefer_dtmf(chan); 10502 } 10503 return dp; 10504 }
| 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 1649 of file chan_iax2.c.
References __find_callno().
Referenced by iax2_poke_peer(), and socket_process().
01649 { 01650 01651 return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame); 01652 }
| 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 1654 of file chan_iax2.c.
References __find_callno().
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_provision(), iax2_request(), and socket_process().
01654 { 01655 01656 return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame); 01657 }
| static struct iax2_thread* find_idle_thread | ( | void | ) | [static, read] |
Definition at line 915 of file chan_iax2.c.
References ast_calloc, ast_cond_init(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_init(), ast_pthread_create, iax2_thread::ffinfo, free, iax2_process_thread(), IAX_TYPE_DYNAMIC, iaxdynamicthreadcount, iaxmaxthreadcount, and thread.
Referenced by __schedule_action(), and socket_read().
00916 { 00917 pthread_attr_t attr; 00918 struct iax2_thread *thread = NULL; 00919 00920 /* Pop the head of the list off */ 00921 AST_LIST_LOCK(&idle_list); 00922 thread = AST_LIST_REMOVE_HEAD(&idle_list, list); 00923 AST_LIST_UNLOCK(&idle_list); 00924 00925 /* If no idle thread is available from the regular list, try dynamic */ 00926 if (thread == NULL) { 00927 AST_LIST_LOCK(&dynamic_list); 00928 thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list); 00929 /* Make sure we absolutely have a thread... if not, try to make one if allowed */ 00930 if (thread == NULL && iaxmaxthreadcount > iaxdynamicthreadcount) { 00931 /* We need to MAKE a thread! */ 00932 if ((thread = ast_calloc(1, sizeof(*thread)))) { 00933 thread->threadnum = iaxdynamicthreadcount; 00934 thread->type = IAX_TYPE_DYNAMIC; 00935 ast_mutex_init(&thread->lock); 00936 ast_cond_init(&thread->cond, NULL); 00937 pthread_attr_init(&attr); 00938 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00939 if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) { 00940 free(thread); 00941 thread = NULL; 00942 } else { 00943 /* All went well and the thread is up, so increment our count */ 00944 iaxdynamicthreadcount++; 00945 00946 /* Wait for the thread to be ready before returning it to the caller */ 00947 while (!thread->ready_for_signal) 00948 usleep(1); 00949 } 00950 } 00951 } 00952 AST_LIST_UNLOCK(&dynamic_list); 00953 } 00954 00955 /* this thread is not processing a full frame (since it is idle), 00956 so ensure that the field for the full frame call number is empty */ 00957 if (thread) 00958 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 00959 00960 return thread; 00961 }
| static struct iax2_peer* find_peer | ( | const char * | name, | |
| int | realtime | |||
| ) | [static, read] |
Definition at line 1148 of file chan_iax2.c.
References ao2_find(), peers, and realtime_peer().
01149 { 01150 struct iax2_peer *peer = NULL; 01151 struct iax2_peer tmp_peer = { 01152 .name = name, 01153 }; 01154 01155 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 01156 01157 /* Now go for realtime if applicable */ 01158 if(!peer && realtime) 01159 peer = realtime_peer(name, NULL); 01160 01161 return peer; 01162 }
| static struct iax2_trunk_peer* find_tpeer | ( | struct sockaddr_in * | sin, | |
| int | fd | |||
| ) | [static, read] |
Definition at line 4030 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_calloc, ast_inet_ntoa(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), inaddrcmp(), iax2_trunk_peer::lastsent, iax2_trunk_peer::lock, LOG_DEBUG, iax2_trunk_peer::next, option_debug, iax2_trunk_peer::sockfd, tpeers, and iax2_trunk_peer::trunkact.
Referenced by iax2_trunk_queue(), and socket_process().
04031 { 04032 struct iax2_trunk_peer *tpeer; 04033 04034 /* Finds and locks trunk peer */ 04035 ast_mutex_lock(&tpeerlock); 04036 for (tpeer = tpeers; tpeer; tpeer = tpeer->next) { 04037 /* We don't lock here because tpeer->addr *never* changes */ 04038 if (!inaddrcmp(&tpeer->addr, sin)) { 04039 ast_mutex_lock(&tpeer->lock); 04040 break; 04041 } 04042 } 04043 if (!tpeer) { 04044 if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) { 04045 ast_mutex_init(&tpeer->lock); 04046 tpeer->lastsent = 9999; 04047 memcpy(&tpeer->addr, sin, sizeof(tpeer->addr)); 04048 tpeer->trunkact = ast_tvnow(); 04049 ast_mutex_lock(&tpeer->lock); 04050 tpeer->next = tpeers; 04051 tpeer->sockfd = fd; 04052 tpeers = tpeer; 04053 #ifdef SO_NO_CHECK 04054 setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 04055 #endif 04056 if (option_debug) 04057 ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port)); 04058 } 04059 } 04060 ast_mutex_unlock(&tpeerlock); 04061 return tpeer; 04062 }
| static unsigned int fix_peerts | ( | struct timeval * | tv, | |
| int | callno, | |||
| unsigned int | ts | |||
| ) | [static] |
Definition at line 3846 of file chan_iax2.c.
References iaxs, and chan_iax2_pvt::rxcore.
Referenced by socket_process().
03847 { 03848 long ms; /* NOT unsigned */ 03849 if (ast_tvzero(iaxs[callno]->rxcore)) { 03850 /* Initialize rxcore time if appropriate */ 03851 gettimeofday(&iaxs[callno]->rxcore, NULL); 03852 /* Round to nearest 20ms so traces look pretty */ 03853 iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000; 03854 } 03855 /* Calculate difference between trunk and channel */ 03856 ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore); 03857 /* Return as the sum of trunk time and the difference between trunk and real time */ 03858 return ms + ts; 03859 }
| static void free_context | ( | struct iax2_context * | con | ) | [static] |
Definition at line 8968 of file chan_iax2.c.
References free, and iax2_context::next.
Referenced by build_user(), and user_destructor().
08969 { 08970 struct iax2_context *conl; 08971 while(con) { 08972 conl = con; 08973 con = con->next; 08974 free(conl); 08975 } 08976 }
| static int function_iaxpeer | ( | struct ast_channel * | chan, | |
| char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 10628 of file chan_iax2.c.
References iax2_peer::addr, iax2_registry::addr, ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strdupa, ast_test_flag, iax2_registry::callno, iax2_peer::capability, iax2_peer::expire, find_peer(), iax2_tech, IAX_DYNAMIC, iaxs, peer_status(), peer_unref(), iax2_peer::prefs, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.
10629 { 10630 struct iax2_peer *peer; 10631 char *peername, *colname; 10632 10633 peername = ast_strdupa(data); 10634 10635 /* if our channel, return the IP address of the endpoint of current channel */ 10636 if (!strcmp(peername,"CURRENTCHANNEL")) { 10637 unsigned short callno; 10638 if (chan->tech != &iax2_tech) 10639 return -1; 10640 callno = PTR_TO_CALLNO(chan->tech_pvt); 10641 ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len); 10642 return 0; 10643 } 10644 10645 if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */ 10646 *colname++ = '\0'; 10647 else if ((colname = strchr(peername, '|'))) 10648 *colname++ = '\0'; 10649 else 10650 colname = "ip"; 10651 10652 if (!(peer = find_peer(peername, 1))) 10653 return -1; 10654 10655 if (!strcasecmp(colname, "ip")) { 10656 ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); 10657 } else if (!strcasecmp(colname, "status")) { 10658 peer_status(peer, buf, len); 10659 } else if (!strcasecmp(colname, "mailbox")) { 10660 ast_copy_string(buf, peer->mailbox, len); 10661 } else if (!strcasecmp(colname, "context")) { 10662 ast_copy_string(buf, peer->context, len); 10663 } else if (!strcasecmp(colname, "expire")) { 10664 snprintf(buf, len, "%d", peer->expire); 10665 } else if (!strcasecmp(colname, "dynamic")) { 10666 ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len); 10667 } else if (!strcasecmp(colname, "callerid_name")) { 10668 ast_copy_string(buf, peer->cid_name, len); 10669 } else if (!strcasecmp(colname, "callerid_num")) { 10670 ast_copy_string(buf, peer->cid_num, len); 10671 } else if (!strcasecmp(colname, "codecs")) { 10672 ast_getformatname_multiple(buf, len -1, peer->capability); 10673 } else if (!strncasecmp(colname, "codec[", 6)) { 10674 char *codecnum, *ptr; 10675 int index = 0, codec = 0; 10676 10677 codecnum = strchr(colname, '['); 10678 *codecnum = '\0'; 10679 codecnum++; 10680 if ((ptr = strchr(codecnum, ']'))) { 10681 *ptr = '\0'; 10682 } 10683 index = atoi(codecnum); 10684 if((codec = ast_codec_pref_index(&peer->prefs, index))) { 10685 ast_copy_string(buf, ast_getformatname(codec), len); 10686 } 10687 } 10688 10689 peer_unref(peer); 10690 10691 return 0; 10692 }
| static int get_auth_methods | ( | char * | value | ) | [static] |
Definition at line 9193 of file chan_iax2.c.
References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.
Referenced by build_peer(), and build_user().
09194 { 09195 int methods = 0; 09196 if (strstr(value, "rsa")) 09197 methods |= IAX_AUTH_RSA; 09198 if (strstr(value, "md5")) 09199 methods |= IAX_AUTH_MD5; 09200 if (strstr(value, "plaintext")) 09201 methods |= IAX_AUTH_PLAINTEXT; 09202 return methods; 09203 }
| static int get_encrypt_methods | ( | const char * | s | ) | [static] |
Definition at line 1030 of file chan_iax2.c.
References ast_true(), and IAX_ENCRYPT_AES128.
Referenced by build_peer(), build_user(), and set_config().
01031 { 01032 int e; 01033 if (!strcasecmp(s, "aes128")) 01034 e = IAX_ENCRYPT_AES128; 01035 else if (ast_true(s)) 01036 e = IAX_ENCRYPT_AES128; 01037 else 01038 e = 0; 01039 return e; 01040 }
| static int get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 2640 of file chan_iax2.c.
References __get_from_jb(), and schedule_action.
Referenced by update_jbsched().
02641 { 02642 #ifdef SCHED_MULTITHREADED 02643 if (schedule_action(__get_from_jb, data)) 02644 #endif 02645 __get_from_jb(data); 02646 return 0; 02647 }
| static void handle_deferred_full_frames | ( | struct iax2_thread * | thread | ) | [static] |
Handle any deferred full frames for this thread.
Definition at line 6848 of file chan_iax2.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), and socket_process().
Referenced by iax2_process_thread().
06849 { 06850 struct iax2_pkt_buf *pkt_buf; 06851 06852 ast_mutex_lock(&thread->lock); 06853 06854 while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) { 06855 ast_mutex_unlock(&thread->lock); 06856 06857 thread->buf = pkt_buf->buf; 06858 thread->buf_len = pkt_buf->len; 06859 thread->buf_size = pkt_buf->len + 1; 06860 06861 socket_process(thread); 06862 06863 thread->buf = NULL; 06864 ast_free(pkt_buf); 06865 06866 ast_mutex_lock(&thread->lock); 06867 } 06868 06869 ast_mutex_unlock(&thread->lock); 06870 }
| static int handle_error | ( | void | ) | [static] |
Definition at line 2037 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().
02038 { 02039 /* XXX Ideally we should figure out why an error occured and then abort those 02040 rather than continuing to try. Unfortunately, the published interface does 02041 not seem to work XXX */ 02042 #if 0 02043 struct sockaddr_in *sin; 02044 int res; 02045 struct msghdr m; 02046 struct sock_extended_err e; 02047 m.msg_name = NULL; 02048 m.msg_namelen = 0; 02049 m.msg_iov = NULL; 02050 m.msg_control = &e; 02051 m.msg_controllen = sizeof(e); 02052 m.msg_flags = 0; 02053 res = recvmsg(netsocket, &m, MSG_ERRQUEUE); 02054 if (res < 0) 02055 ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno)); 02056 else { 02057 if (m.msg_controllen) { 02058 sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e); 02059 if (sin) 02060 ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr)); 02061 else 02062 ast_log(LOG_WARNING, "No address detected??\n"); 02063 } else { 02064 ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno)); 02065 } 02066 } 02067 #endif 02068 return 0; 02069 }
| static int iax2_ack_registry | ( | struct iax_ies * | ies, | |
| struct sockaddr_in * | sin, | |||
| int | callno | |||
| ) | [static] |
Acknowledgment received for OUR registration.
Definition at line 5920 of file chan_iax2.c.
References iax2_registry::addr, iax_ies::apparent_addr, ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), iax_ies::calling_number, EVENT_FLAG_SYSTEM, iax2_registry::expire, iax2_do_register_s(), iax2_sched_add(), iaxs, inaddrcmp(), LOG_WARNING, manager_event(), iax2_registry::messages, iax_ies::msgcount, option_verbose, iax_ies::refresh, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGISTERED, iax2_registry::regstate, iax2_registry::us, iax_ies::username, and VERBOSE_PREFIX_3.
Referenced by socket_process().
05921 { 05922 struct iax2_registry *reg; 05923 /* Start pessimistic */ 05924 char peer[256] = ""; 05925 char msgstatus[60]; 05926 int refresh = 60; 05927 char ourip[256] = "<Unspecified>"; 05928 struct sockaddr_in oldus; 05929 struct sockaddr_in us; 05930 int oldmsgs; 05931 05932 memset(&us, 0, sizeof(us)); 05933 if (ies->apparent_addr) 05934 bcopy(ies->apparent_addr, &us, sizeof(us)); 05935 if (ies->username) 05936 ast_copy_string(peer, ies->username, sizeof(peer)); 05937 if (ies->refresh) 05938 refresh = ies->refresh; 05939 if (ies->calling_number) { 05940 /* We don't do anything with it really, but maybe we should */ 05941 } 05942 reg = iaxs[callno]->reg; 05943 if (!reg) { 05944 ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer); 05945 return -1; 05946 } 05947 memcpy(&oldus, ®->us, sizeof(oldus)); 05948 oldmsgs = reg->messages; 05949 if (inaddrcmp(®->addr, sin)) { 05950 ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 05951 return -1; 05952 } 05953 memcpy(®->us, &us, sizeof(reg->us)); 05954 if (ies->msgcount >= 0) 05955 reg->messages = ies->msgcount & 0xffff; /* only low 16 bits are used in the transmission of the IE */ 05956 /* always refresh the registration at the interval requested by the server 05957 we are registering to 05958 */ 05959 reg->refresh = refresh; 05960 AST_SCHED_DEL(sched, reg->expire); 05961 reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 05962 if (inaddrcmp(&oldus, ®->us) || (reg->messages != oldmsgs)) { 05963 if (option_verbose > 2) { 05964 if (reg->messages > 255) 05965 snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8); 05966 else if (reg->messages > 1) 05967 snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages); 05968 else if (reg->messages > 0) 05969 snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n"); 05970 else 05971 snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n"); 05972 snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 05973 ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus); 05974 } 05975 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr)); 05976 } 05977 reg->regstate = REG_STATE_REGISTERED; 05978 return 0; 05979 }
| static int iax2_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3646 of file chan_iax2.c.
References AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_log(), iax2_registry::callno, LOG_DEBUG, option_debug, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03647 { 03648 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03649 if (option_debug) 03650 ast_log(LOG_DEBUG, "Answering IAX2 call\n"); 03651 return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1); 03652 }
| 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 3496 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_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_verbose(), ast_waitfor_n(), ast_write(), chan_iax2_pvt::bridgecallno, f, ast_frame::frametype, iax2_start_transfer(), iax2_tech, IAX_LINGER_TIMEOUT, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, iaxs, iaxsl, lock_both(), LOG_WARNING, ast_channel::nativeformats, option_verbose, PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, TRANSFER_RELEASED, tv, unlock_both(), and VERBOSE_PREFIX_3.
03497 { 03498 struct ast_channel *cs[3]; 03499 struct ast_channel *who, *other; 03500 int to = -1; 03501 int res = -1; 03502 int transferstarted=0; 03503 struct ast_frame *f; 03504 unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt); 03505 unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt); 03506 struct timeval waittimer = {0, 0}, tv; 03507 03508 lock_both(callno0, callno1); 03509 if (!iaxs[callno0] || !iaxs[callno1]) { 03510 unlock_both(callno0, callno1); 03511 return AST_BRIDGE_FAILED; 03512 } 03513 /* Put them in native bridge mode */ 03514 if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) { 03515 iaxs[callno0]->bridgecallno = callno1; 03516 iaxs[callno1]->bridgecallno = callno0; 03517 } 03518 unlock_both(callno0, callno1); 03519 03520 /* If not, try to bridge until we can execute a transfer, if we can */ 03521 cs[0] = c0; 03522 cs[1] = c1; 03523 for (/* ever */;;) { 03524 /* Check in case we got masqueraded into */ 03525 if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) { 03526 if (option_verbose > 2) 03527 ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n"); 03528 /* Remove from native mode */ 03529 if (c0->tech == &iax2_tech) { 03530 ast_mutex_lock(&iaxsl[callno0]); 03531 iaxs[callno0]->bridgecallno = 0; 03532 ast_mutex_unlock(&iaxsl[callno0]); 03533 } 03534 if (c1->tech == &iax2_tech) { 03535 ast_mutex_lock(&iaxsl[callno1]); 03536 iaxs[callno1]->bridgecallno = 0; 03537 ast_mutex_unlock(&iaxsl[callno1]); 03538 } 03539 return AST_BRIDGE_FAILED_NOWARN; 03540 } 03541 if (c0->nativeformats != c1->nativeformats) { 03542 if (option_verbose > 2) { 03543 char buf0[255]; 03544 char buf1[255]; 03545 ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats); 03546 ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats); 03547 ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1); 03548 } 03549 /* Remove from native mode */ 03550 lock_both(callno0, callno1); 03551 if (iaxs[callno0]) 03552 iaxs[callno0]->bridgecallno = 0; 03553 if (iaxs[callno1]) 03554 iaxs[callno1]->bridgecallno = 0; 03555 unlock_both(callno0, callno1); 03556 return AST_BRIDGE_FAILED_NOWARN; 03557 } 03558 /* check if transfered and if we really want native bridging */ 03559 if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) { 03560 /* Try the transfer */ 03561 if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) || 03562 ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA))) 03563 ast_log(LOG_WARNING, "Unable to start the transfer\n"); 03564 transferstarted = 1; 03565 } 03566 if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) { 03567 /* Call has been transferred. We're no longer involved */ 03568 gettimeofday(&tv, NULL); 03569 if (ast_tvzero(waittimer)) { 03570 waittimer = tv; 03571 } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) { 03572 c0->_softhangup |= AST_SOFTHANGUP_DEV; 03573 c1->_softhangup |= AST_SOFTHANGUP_DEV; 03574 *fo = NULL; 03575 *rc = c0; 03576 res = AST_BRIDGE_COMPLETE; 03577 break; 03578 } 03579 } 03580 to = 1000; 03581 who = ast_waitfor_n(cs, 2, &to); 03582 if (timeoutms > -1) { 03583 timeoutms -= (1000 - to); 03584 if (timeoutms < 0) 03585 timeoutms = 0; 03586 } 03587 if (!who) { 03588 if (!timeoutms) { 03589 res = AST_BRIDGE_RETRY; 03590 break; 03591 } 03592 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03593 res = AST_BRIDGE_FAILED; 03594 break; 03595 } 03596 continue; 03597 } 03598 f = ast_read(who); 03599 if (!f) { 03600 *fo = NULL; 03601 *rc = who; 03602 res = AST_BRIDGE_COMPLETE; 03603 break; 03604 } 03605 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03606 *fo = f; 03607 *rc = who; 03608 res = AST_BRIDGE_COMPLETE; 03609 break; 03610 } 03611 other = (who == c0) ? c1 : c0; /* the 'other' channel */ 03612 if ((f->frametype == AST_FRAME_VOICE) || 03613 (f->frametype == AST_FRAME_TEXT) || 03614 (f->frametype == AST_FRAME_VIDEO) || 03615 (f->frametype == AST_FRAME_IMAGE) || 03616 (f->frametype == AST_FRAME_DTMF)) { 03617 /* monitored dtmf take out of the bridge. 03618 * check if we monitor the specific source. 03619 */ 03620 int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1; 03621 if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) { 03622 *rc = who; 03623 *fo = f; 03624 res = AST_BRIDGE_COMPLETE; 03625 /* Remove from native mode */ 03626 break; 03627 } 03628 /* everything else goes to the other side */ 03629 ast_write(other, f); 03630 } 03631 ast_frfree(f); 03632 /* Swap who gets priority */ 03633 cs[2] = cs[0]; 03634 cs[0] = cs[1]; 03635 cs[1] = cs[2]; 03636 } 03637 lock_both(callno0, callno1); 03638 if(iaxs[callno0]) 03639 iaxs[callno0]->bridgecallno = 0; 03640 if(iaxs[callno1]) 03641 iaxs[callno1]->bridgecallno = 0; 03642 unlock_both(callno0, callno1); 03643 return res; 03644 }
| static int iax2_call | ( | struct ast_channel * | c, | |
| char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 3240 of file chan_iax2.c.
References ast_channel::_state, create_addr_info::adsi, chan_iax2_pvt::adsi, ast_channel::adsicpe, AST_FRAME_IAX, 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, auto_congest(), iax_ie_data::buf, iax2_registry::callno, 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, create_addr_info::context, ast_channel::context, parsed_dial_string::context, create_addr(), 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_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_RDNIS, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, IAX_SENDANI, iaxs, iaxsl, chan_iax2_pvt::initid, parsed_dial_string::key, LOG_WARNING, chan_iax2_pvt::maxtime, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, parsed_dial_string::options, 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, iax2_registry::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, and parsed_dial_string::username.
03241 { 03242 struct sockaddr_in sin; 03243 char *l=NULL, *n=NULL, *tmpstr; 03244 struct iax_ie_data ied; 03245 char *defaultrdest = "s"; 03246 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03247 struct parsed_dial_string pds; 03248 struct create_addr_info cai; 03249 03250 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { 03251 ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name); 03252 return -1; 03253 } 03254 03255 memset(&cai, 0, sizeof(cai)); 03256 cai.encmethods = iax2_encryption; 03257 03258 memset(&pds, 0, sizeof(pds)); 03259 tmpstr = ast_strdupa(dest); 03260 parse_dial_string(tmpstr, &pds); 03261 03262 if (ast_strlen_zero(pds.peer)) { 03263 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest); 03264 return -1; 03265 } 03266 03267 if (!pds.exten) { 03268 pds.exten = defaultrdest; 03269 } 03270 03271 if (create_addr(pds.peer, c, &sin, &cai)) { 03272 ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer); 03273 return -1; 03274 } 03275 03276 if (!pds.username && !ast_strlen_zero(cai.username)) 03277 pds.username = cai.username; 03278 if (!pds.password && !ast_strlen_zero(cai.secret)) 03279 pds.password = cai.secret; 03280 if (!pds.key && !ast_strlen_zero(cai.outkey)) 03281 pds.key = cai.outkey; 03282 if (!pds.context && !ast_strlen_zero(cai.peercontext)) 03283 pds.context = cai.peercontext; 03284 03285 /* Keep track of the context for outgoing calls too */ 03286 ast_copy_string(c->context, cai.context, sizeof(c->context)); 03287 03288 if (pds.port) 03289 sin.sin_port = htons(atoi(pds.port)); 03290 03291 l = c->cid.cid_num; 03292 n = c->cid.cid_name; 03293 03294 /* Now build request */ 03295 memset(&ied, 0, sizeof(ied)); 03296 03297 /* On new call, first IE MUST be IAX version of caller */ 03298 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 03299 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten); 03300 if (pds.options && strchr(pds.options, 'a')) { 03301 /* Request auto answer */ 03302 iax_ie_append(&ied, IAX_IE_AUTOANSWER); 03303 } 03304 03305 iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs); 03306 03307 if (l) { 03308 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l); 03309 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 03310 } else { 03311 if (n) 03312 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 03313 else 03314 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE); 03315 } 03316 03317 iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton); 03318 iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns); 03319 03320 if (n) 03321 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n); 03322 if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani) 03323 iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani); 03324 03325 if (!ast_strlen_zero(c->language)) 03326 iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language); 03327 if (!ast_strlen_zero(c->cid.cid_dnid)) 03328 iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid); 03329 if (!ast_strlen_zero(c->cid.cid_rdnis)) 03330 iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis); 03331 03332 if (pds.context) 03333 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context); 03334 03335 if (pds.username) 03336 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 03337 03338 if (cai.encmethods) 03339 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods); 03340 03341 ast_mutex_lock(&iaxsl[callno]); 03342 03343 if (!ast_strlen_zero(c->context)) 03344 ast_string_field_set(iaxs[callno], context, c->context); 03345 03346 if (pds.username) 03347 ast_string_field_set(iaxs[callno], username, pds.username); 03348 03349 iaxs[callno]->encmethods = cai.encmethods; 03350 03351 iaxs[callno]->adsi = cai.adsi; 03352 03353 ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret); 03354 ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest); 03355 03356 if (pds.key) 03357 ast_string_field_set(iaxs[callno], outkey, pds.key); 03358 if (pds.password) 03359 ast_string_field_set(iaxs[callno], secret, pds.password); 03360 03361 iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats); 03362 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability); 03363 iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe); 03364 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone)); 03365 03366 if (iaxs[callno]->maxtime) { 03367 /* Initialize pingtime and auto-congest time */ 03368 iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2; 03369 iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno)); 03370 } else if (autokill) { 03371 iaxs[callno]->pingtime = autokill / 2; 03372 iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno)); 03373 } 03374 03375 /* send the command using the appropriate socket for this peer */ 03376 iaxs[callno]->sockfd = cai.sockfd; 03377 03378 /* Transmit the string in a "NEW" request */ 03379 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 03380 03381 ast_mutex_unlock(&iaxsl[callno]); 03382 ast_setstate(c, AST_STATE_RINGING); 03383 03384 return 0; 03385 }
| 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 10530 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_CANEXIST, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
10531 { 10532 int res = 0; 10533 struct iax2_dpcache *dp; 10534 #if 0 10535 ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 10536 #endif 10537 if ((priority != 1) && (priority != 2)) 10538 return 0; 10539 ast_mutex_lock(&dpcache_lock); 10540 dp = find_cache(chan, data, context, exten, priority); 10541 if (dp) { 10542 if (dp->flags & CACHE_FLAG_CANEXIST) 10543 res= 1; 10544 } 10545 ast_mutex_unlock(&dpcache_lock); 10546 if (!dp) { 10547 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 10548 } 10549 return res; 10550 }
| static unsigned int iax2_datetime | ( | const char * | tz | ) | [static] |
Definition at line 3143 of file chan_iax2.c.
References ast_localtime(), ast_strlen_zero(), and t.
Referenced by iax2_call(), and update_registry().
03144 { 03145 time_t t; 03146 struct tm tm; 03147 unsigned int tmp; 03148 time(&t); 03149 if (!ast_strlen_zero(tz)) 03150 ast_localtime(&t, &tm, tz); 03151 else 03152 ast_localtime(&t, &tm, NULL); 03153 tmp = (tm.tm_sec >> 1) & 0x1f; /* 5 bits of seconds */ 03154 tmp |= (tm.tm_min & 0x3f) << 5; /* 6 bits of minutes */ 03155 tmp |= (tm.tm_hour & 0x1f) << 11; /* 5 bits of hours */ 03156 tmp |= (tm.tm_mday & 0x1f) << 16; /* 5 bits of day of month */ 03157 tmp |= ((tm.tm_mon + 1) & 0xf) << 21; /* 4 bits of month */ 03158 tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */ 03159 return tmp; 03160 }
| static void iax2_destroy | ( | int | callno | ) | [static] |
Definition at line 1288 of file chan_iax2.c.
References ao2_ref(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, lastused, ast_channel::lock, LOG_DEBUG, option_debug, chan_iax2_pvt::owner, chan_iax2_pvt::peercallno, remove_by_peercallno(), 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(), and socket_process().
01289 { 01290 struct chan_iax2_pvt *pvt; 01291 struct ast_channel *owner; 01292 01293 retry: 01294 pvt = iaxs[callno]; 01295 gettimeofday(&lastused[callno], NULL); 01296 01297 owner = pvt ? pvt->owner : NULL; 01298 01299 if (owner) { 01300 if (ast_mutex_trylock(&owner->lock)) { 01301 if (option_debug > 2) 01302 ast_log(LOG_DEBUG, "Avoiding IAX destroy deadlock\n"); 01303 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01304 goto retry; 01305 } 01306 } 01307 if (!owner) { 01308 iaxs[callno] = NULL; 01309 } 01310 01311 if (pvt) { 01312 if (!owner) { 01313 pvt->owner = NULL; 01314 } else { 01315 /* If there's an owner, prod it to give up */ 01316 /* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup() 01317 * because we already hold the owner channel lock. */ 01318 ast_queue_hangup(owner); 01319 } 01320 01321 if (pvt->peercallno) { 01322 remove_by_peercallno(pvt); 01323 } 01324 01325 if (!owner) { 01326 ao2_ref(pvt, -1); 01327 pvt = NULL; 01328 } 01329 } 01330 01331 if (owner) { 01332 ast_mutex_unlock(&owner->lock); 01333 } 01334 01335 if (callno & 0x4000) { 01336 update_max_trunk(); 01337 } 01338 }
| static void iax2_destroy_helper | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1218 of file chan_iax2.c.
References ao2_find(), ast_clear_flag, AST_SCHED_DEL, ast_test_flag, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, iax2_user::curauthreq, IAX_MAXAUTHREQ, chan_iax2_pvt::initid, chan_iax2_pvt::jbid, chan_iax2_pvt::lagid, chan_iax2_pvt::pingid, user_unref(), and users.
Referenced by iax2_predestroy(), pvt_destructor(), and stop_stuff().
01219 { 01220 /* Decrement AUTHREQ count if needed */ 01221 if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) { 01222 struct iax2_user *user; 01223 struct iax2_user tmp_user = { 01224 .name = pvt->username, 01225 }; 01226 01227 user = ao2_find(users, &tmp_user, OBJ_POINTER); 01228 if (user) { 01229 ast_atomic_fetchadd_int(&user->curauthreq, -1); 01230 user = user_unref(user); 01231 } 01232 01233 ast_clear_flag(pvt, IAX_MAXAUTHREQ); 01234 } 01235 01236 /* No more pings or lagrq's */ 01237 AST_SCHED_DEL(sched, pvt->pingid); 01238 AST_SCHED_DEL(sched, pvt->lagid); 01239 AST_SCHED_DEL(sched, pvt->autoid); 01240 AST_SCHED_DEL(sched, pvt->authid); 01241 AST_SCHED_DEL(sched, pvt->initid); 01242 AST_SCHED_DEL(sched, pvt->jbid); 01243 }
| static int iax2_devicestate | ( | void * | data | ) | [static] |
Part of the device state notification system ---.
Definition at line 10717 of file chan_iax2.c.
References iax2_peer::addr, 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_DEBUG, LOG_WARNING, iax2_peer::maxms, option_debug, parse_dial_string(), parsed_dial_string::peer, and peer_unref().
10718 { 10719 struct parsed_dial_string pds; 10720 char *tmp = ast_strdupa(data); 10721 struct iax2_peer *p; 10722 int res = AST_DEVICE_INVALID; 10723 10724 memset(&pds, 0, sizeof(pds)); 10725 parse_dial_string(tmp, &pds); 10726 10727 if (ast_strlen_zero(pds.peer)) { 10728 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 10729 return res; 10730 } 10731 10732 if (option_debug > 2) 10733 ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer); 10734 10735 /* SLD: FIXME: second call to find_peer during registration */ 10736 if (!(p = find_peer(pds.peer, 1))) 10737 return res; 10738 10739 res = AST_DEVICE_UNAVAILABLE; 10740 if (option_debug > 2) 10741 ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n", 10742 pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms); 10743 10744 if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) && 10745 (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) { 10746 /* Peer is registered, or have default IP address 10747 and a valid registration */ 10748 if (p->historicms == 0 || p->historicms <= p->maxms) 10749 /* let the core figure out whether it is in use or not */ 10750 res = AST_DEVICE_UNKNOWN; 10751 } 10752 10753 peer_unref(p); 10754 10755 return res; 10756 }
| static int iax2_digit_begin | ( | struct ast_channel * | c, | |
| char | digit | |||
| ) | [static] |
Definition at line 2759 of file chan_iax2.c.
References AST_FRAME_DTMF_BEGIN, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02760 { 02761 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1); 02762 }
| static int iax2_digit_end | ( | struct ast_channel * | c, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 2764 of file chan_iax2.c.
References AST_FRAME_DTMF_END, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02765 { 02766 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1); 02767 }
| static int iax2_do_debug | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4966 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04967 { 04968 if (argc < 2 || argc > 3) 04969 return RESULT_SHOWUSAGE; 04970 iaxdebug = 1; 04971 ast_cli(fd, "IAX2 Debugging Enabled\n"); 04972 return RESULT_SUCCESS; 04973 }
| static int iax2_do_jb_debug | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4984 of file chan_iax2.c.
References ast_cli(), jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04985 { 04986 if (argc < 3 || argc > 4) 04987 return RESULT_SHOWUSAGE; 04988 jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output); 04989 ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n"); 04990 return RESULT_SUCCESS; 04991 }
| static int iax2_do_register | ( | struct iax2_registry * | reg | ) | [static] |
Definition at line 8687 of file chan_iax2.c.
References iax2_registry::addr, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax_ie_data::buf, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno_locked(), iax2_destroy(), iax2_do_register_s(), iax2_sched_add(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, iaxsl, LOG_DEBUG, LOG_WARNING, NEW_FORCE, option_debug, 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().
08688 { 08689 struct iax_ie_data ied; 08690 if (option_debug && iaxdebug) 08691 ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username); 08692 08693 if (reg->dnsmgr && 08694 ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) { 08695 /* Maybe the IP has changed, force DNS refresh */ 08696 ast_dnsmgr_refresh(reg->dnsmgr); 08697 } 08698 08699 /* 08700 * if IP has Changed, free allocated call to create a new one with new IP 08701 * call has the pointer to IP and must be updated to the new one 08702 */ 08703 if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) { 08704 ast_mutex_lock(&iaxsl[reg->callno]); 08705 iax2_destroy(reg->callno); 08706 ast_mutex_unlock(&iaxsl[reg->callno]); 08707 reg->callno = 0; 08708 } 08709 if (!reg->addr.sin_addr.s_addr) { 08710 if (option_debug && iaxdebug) 08711 ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username); 08712 /* Setup the next registration attempt */ 08713 AST_SCHED_DEL(sched, reg->expire); 08714 reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 08715 return -1; 08716 } 08717 08718 if (!reg->callno) { 08719 if (option_debug) 08720 ast_log(LOG_DEBUG, "Allocate call number\n"); 08721 reg->callno = find_callno_locked(0, 0, ®->addr, NEW_FORCE, defaultsockfd, 0); 08722 if (reg->callno < 1) { 08723 ast_log(LOG_WARNING, "Unable to create call for registration\n"); 08724 return -1; 08725 } else if (option_debug) 08726 ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno); 08727 iaxs[reg->callno]->reg = reg; 08728 ast_mutex_unlock(&iaxsl[reg->callno]); 08729 } 08730 /* Schedule the next registration attempt */ 08731 AST_SCHED_DEL(sched, reg->expire); 08732 /* Setup the next registration a little early */ 08733 reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 08734 /* Send the request */ 08735 memset(&ied, 0, sizeof(ied)); 08736 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 08737 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 08738 send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 08739 reg->regstate = REG_STATE_REGSENT; 08740 return 0; 08741 }
| static int iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 5768 of file chan_iax2.c.
References __iax2_do_register_s(), and schedule_action.
Referenced by iax2_ack_registry(), and iax2_do_register().
05769 { 05770 #ifdef SCHED_MULTITHREADED 05771 if (schedule_action(__iax2_do_register_s, data)) 05772 #endif 05773 __iax2_do_register_s(data); 05774 return 0; 05775 }
| static int iax2_do_trunk_debug | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4975 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04976 { 04977 if (argc < 3 || argc > 4) 04978 return RESULT_SHOWUSAGE; 04979 iaxtrunkdebug = 1; 04980 ast_cli(fd, "IAX2 Trunk Debug Requested\n"); 04981 return RESULT_SUCCESS; 04982 }
| static void iax2_dprequest | ( | struct iax2_dpcache * | dp, | |
| int | callno | |||
| ) | [static] |
Definition at line 6459 of file chan_iax2.c.
References AST_FRAME_IAX, AST_SCHED_DEL, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, iax2_dpcache::exten, iax2_dpcache::flags, iax2_sched_add(), IAX_COMMAND_DPREQ, iax_ie_append_str(), IAX_IE_CALLED_NUMBER, iaxs, iax_ie_data::pos, and send_command().
Referenced by find_cache(), and socket_process().
06460 { 06461 struct iax_ie_data ied; 06462 /* Auto-hangup with 30 seconds of inactivity */ 06463 AST_SCHED_DEL(sched, iaxs[callno]->autoid); 06464 iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno); 06465 memset(&ied, 0, sizeof(ied)); 06466 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten); 06467 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1); 06468 dp->flags |= CACHE_FLAG_TRANSMITTED; 06469 }
| 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 10576 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), CACHE_FLAG_EXISTS, find_cache(), iax2_dpcache::flags, LOG_NOTICE, LOG_WARNING, option_verbose, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), and VERBOSE_PREFIX_3.
10577 { 10578 char odata[256]; 10579 char req[256]; 10580 char *ncontext; 10581 struct iax2_dpcache *dp; 10582 struct ast_app *dial; 10583 #if 0 10584 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); 10585 #endif 10586 if (priority == 2) { 10587 /* Indicate status, can be overridden in dialplan */ 10588 const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS"); 10589 if (dialstatus) { 10590 dial = pbx_findapp(dialstatus); 10591 if (dial) 10592 pbx_exec(chan, dial, ""); 10593 } 10594 return -1; 10595 } else if (priority != 1) 10596 return -1; 10597 ast_mutex_lock(&dpcache_lock); 10598 dp = find_cache(chan, data, context, exten, priority); 10599 if (dp) { 10600 if (dp->flags & CACHE_FLAG_EXISTS) { 10601 ast_copy_string(odata, data, sizeof(odata)); 10602 ncontext = strchr(odata, '/'); 10603 if (ncontext) { 10604 *ncontext = '\0'; 10605 ncontext++; 10606 snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext); 10607 } else { 10608 snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten); 10609 } 10610 if (option_verbose > 2) 10611 ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req); 10612 } else { 10613 ast_mutex_unlock(&dpcache_lock); 10614 ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data); 10615 return -1; 10616 } 10617 } 10618 ast_mutex_unlock(&dpcache_lock); 10619 dial = pbx_findapp("Dial"); 10620 if (dial) { 10621 return pbx_exec(chan, dial, req); 10622 } else { 10623 ast_log(LOG_WARNING, "No dial application registered\n"); 10624 } 10625 return -1; 10626 }
| 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 10507 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_EXISTS, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
10508 { 10509 struct iax2_dpcache *dp; 10510 int res = 0; 10511 #if 0 10512 ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 10513 #endif 10514 if ((priority != 1) && (priority != 2)) 10515 return 0; 10516 ast_mutex_lock(&dpcache_lock); 10517 dp = find_cache(chan, data, context, exten, priority); 10518 if (dp) { 10519 if (dp->flags & CACHE_FLAG_EXISTS) 10520 res= 1; 10521 } 10522 ast_mutex_unlock(&dpcache_lock); 10523 if (!dp) { 10524 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 10525 } 10526 return res; 10527 }
| static int iax2_fixup | ( | struct ast_channel * | oldchannel, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 2786 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iaxs, iaxsl, LOG_WARNING, chan_iax2_pvt::owner, PTR_TO_CALLNO, and ast_channel::tech_pvt.
02787 { 02788 unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt); 02789 ast_mutex_lock(&iaxsl[callno]); 02790 if (iaxs[callno]) 02791 iaxs[callno]->owner = newchan; 02792 else 02793 ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n"); 02794 ast_mutex_unlock(&iaxsl[callno]); 02795 return 0; 02796 }
| static void iax2_frame_free | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 1282 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(), and schedule_delivery().
01283 { 01284 AST_SCHED_DEL(sched, fr->retrans); 01285 iax_frame_free(fr); 01286 }
| static int iax2_getpeername | ( | struct sockaddr_in | sin, | |
| char * | host, | |||
| int | len | |||
| ) | [static] |
Definition at line 1188 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), peer_unref(), peers, and realtime_peer().
Referenced by __find_callno().
01189 { 01190 struct iax2_peer *peer = NULL; 01191 int res = 0; 01192 struct ao2_iterator i; 01193 01194 i = ao2_iterator_init(peers, 0); 01195 while ((peer = ao2_iterator_next(&i))) { 01196 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 01197 (peer->addr.sin_port == sin.sin_port)) { 01198 ast_copy_string(host, peer->name, len); 01199 peer_unref(peer); 01200 res = 1; 01201 break; 01202 } 01203 peer_unref(peer); 01204 } 01205 01206 if (!peer) { 01207 peer = realtime_peer(NULL, &sin); 01208 if (peer) { 01209 ast_copy_string(host, peer->name, len); 01210 peer_unref(peer); 01211 res = 1; 01212 } 01213 } 01214 01215 return res; 01216 }
| static int iax2_getpeertrunk | ( | struct sockaddr_in | sin | ) | [static] |
Definition at line 3721 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_test_flag, IAX_TRUNK, peer_unref(), and peers.
Referenced by check_access().
03722 { 03723 struct iax2_peer *peer; 03724 int res = 0; 03725 struct ao2_iterator i; 03726 03727 i = ao2_iterator_init(peers, 0); 03728 while ((peer = ao2_iterator_next(&i))) { 03729 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 03730 (peer->addr.sin_port == sin.sin_port)) { 03731 res = ast_test_flag(peer, IAX_TRUNK); 03732 peer_unref(peer); 03733 break; 03734 } 03735 peer_unref(peer); 03736 } 03737 03738 return res; 03739 }
| static int iax2_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3387 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_verbose(), iax_ie_data::buf, iax2_registry::callno, error(), ast_channel::hangupcause, iax2_destroy(), iax2_predestroy(), IAX_ALREADYGONE, IAX_COMMAND_HANGUP, iax_ie_append_byte(), IAX_IE_CAUSECODE, iaxs, iaxsl, LOG_DEBUG, option_debug, option_verbose, iax_ie_data::pos, PTR_TO_CALLNO, send_command_final(), ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
03388 { 03389 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03390 int alreadygone; 03391 struct iax_ie_data ied; 03392 memset(&ied, 0, sizeof(ied)); 03393 ast_mutex_lock(&iaxsl[callno]); 03394 if (callno && iaxs[callno]) { 03395 if (option_debug) 03396 ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause); 03397 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE); 03398 /* Send the hangup unless we have had a transmission error or are already gone */ 03399 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause); 03400 if (!iaxs[callno]->error && !alreadygone) { 03401 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 03402 if (!iaxs[callno]) { 03403 ast_mutex_unlock(&iaxsl[callno]); 03404 return 0; 03405 } 03406 } 03407 /* Explicitly predestroy it */ 03408 iax2_predestroy(callno); 03409 /* If we were already gone to begin with, destroy us now */ 03410 if (alreadygone && iaxs[callno]) { 03411 if (option_debug) 03412 ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name); 03413 iax2_destroy(callno); 03414 } 03415 } 03416 ast_mutex_unlock(&iaxsl[callno]); 03417 if (option_verbose > 2) 03418 ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name); 03419 return 0; 03420 }
| static int iax2_indicate | ( | struct ast_channel * | c, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 3654 of file chan_iax2.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, DEADLOCK_AVOIDANCE, iaxs, iaxsl, LOG_DEBUG, option_debug, chan_iax2_pvt::peercallno, PTR_TO_CALLNO, send_command(), and ast_channel::tech_pvt.
03655 { 03656 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03657 struct chan_iax2_pvt *pvt; 03658 int res = 0; 03659 03660 if (option_debug && iaxdebug) 03661 ast_log(LOG_DEBUG, "Indicating condition %d\n", condition); 03662 03663 ast_mutex_lock(&iaxsl[callno]); 03664 pvt = iaxs[callno]; 03665 03666 if (!pvt->peercallno) { 03667 /* We don't know the remote side's call number, yet. :( */ 03668 int count = 10; 03669 while (count-- && pvt && !pvt->peercallno) { 03670 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 03671 pvt = iaxs[callno]; 03672 } 03673 if (!pvt->peercallno) { 03674 res = -1; 03675 goto done; 03676 } 03677 } 03678 03679 switch (condition) { 03680 case AST_CONTROL_HOLD: 03681 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 03682 ast_moh_start(c, data, pvt->mohinterpret); 03683 goto done; 03684 } 03685 break; 03686 case AST_CONTROL_UNHOLD: 03687 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 03688 ast_moh_stop(c); 03689 goto done; 03690 } 03691 } 03692 03693 res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1); 03694 03695 done: 03696 ast_mutex_unlock(&iaxsl[callno]); 03697 03698 return res; 03699 }
| 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 10553 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_MATCHMORE, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
10554 { 10555 int res = 0; 10556 struct iax2_dpcache *dp; 10557 #if 0 10558 ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 10559 #endif 10560 if ((priority != 1) && (priority != 2)) 10561 return 0; 10562 ast_mutex_lock(&dpcache_lock); 10563 dp = find_cache(chan, data, context, exten, priority); 10564 if (dp) { 10565 if (dp->flags & CACHE_FLAG_MATCHMORE) 10566 res= 1; 10567 } 10568 ast_mutex_unlock(&dpcache_lock); 10569 if (!dp) { 10570 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 10571 } 10572 return res; 10573 }
| static int iax2_no_debug | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4993 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04994 { 04995 if (argc < 3 || argc > 4) 04996 return RESULT_SHOWUSAGE; 04997 iaxdebug = 0; 04998 ast_cli(fd, "IAX2 Debugging Disabled\n"); 04999 return RESULT_SUCCESS; 05000 }
| static int iax2_no_jb_debug | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 5011 of file chan_iax2.c.
References ast_cli(), jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
05012 { 05013 if (argc < 4 || argc > 5) 05014 return RESULT_SHOWUSAGE; 05015 jb_setoutput(jb_error_output, jb_warning_output, NULL); 05016 jb_debug_output("\n"); 05017 ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n"); 05018 return RESULT_SUCCESS; 05019 }
| static int iax2_no_trunk_debug | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 5002 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
05003 { 05004 if (argc < 4 || argc > 5) 05005 return RESULT_SHOWUSAGE; 05006 iaxtrunkdebug = 0; 05007 ast_cli(fd, "IAX2 Trunk Debugging Disabled\n"); 05008 return RESULT_SUCCESS; 05009 }
| static int iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 8885 of file chan_iax2.c.
References __iax2_poke_noanswer(), peer_unref(), iax2_peer::pokeexpire, and schedule_action.
Referenced by iax2_poke_peer().
08886 { 08887 struct iax2_peer *peer = (struct iax2_peer *)data; 08888 peer->pokeexpire = -1; 08889 #ifdef SCHED_MULTITHREADED 08890 if (schedule_action(__iax2_poke_noanswer, data)) 08891 #endif 08892 __iax2_poke_noanswer(data); 08893 peer_unref(peer); 08894 return 0; 08895 }
| static int iax2_poke_peer | ( | struct iax2_peer * | peer, | |
| int | heldcall | |||
| ) | [static] |
Definition at line 8906 of file chan_iax2.c.
References iax2_peer::addr, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), iax2_peer::callno, iax2_registry::callno, DEFAULT_MAXMS, iax2_peer::dnsmgr, find_callno(), iax2_peer::historicms, iax2_destroy(), iax2_poke_noanswer(), iax2_sched_add(), IAX_COMMAND_POKE, iaxs, iaxsl, iax2_peer::lastms, LOG_NOTICE, LOG_WARNING, iax2_peer::maxms, NEW_FORCE, peer_ref(), peer_unref(), chan_iax2_pvt::peerpoke, chan_iax2_pvt::pingtime, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, 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().
08907 { 08908 int callno; 08909 if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) { 08910 /* IF we have no IP without dnsmgr, or this isn't to be monitored, return 08911 immediately after clearing things out */ 08912 peer->lastms = 0; 08913 peer->historicms = 0; 08914 peer->pokeexpire = -1; 08915 peer->callno = 0; 08916 return 0; 08917 } 08918 08919 /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */ 08920 if ((callno = peer->callno) > 0) { 08921 ast_log(LOG_NOTICE, "Still have a callno...\n"); 08922 ast_mutex_lock(&iaxsl[callno]); 08923 iax2_destroy(callno); 08924 ast_mutex_unlock(&iaxsl[callno]); 08925 } 08926 if (heldcall) 08927 ast_mutex_unlock(&iaxsl[heldcall]); 08928 callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0); 08929 if (heldcall) 08930 ast_mutex_lock(&iaxsl[heldcall]); 08931 if (peer->callno < 1) { 08932 ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name); 08933 return -1; 08934 } 08935 08936 /* Speed up retransmission times for this qualify call */ 08937 iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1; 08938 iaxs[peer->callno]->peerpoke = peer; 08939 08940 /* Remove any pending pokeexpire task */ 08941 if (peer->pokeexpire > -1) { 08942 if (!ast_sched_del(sched, peer->pokeexpire)) { 08943 peer->pokeexpire = -1; 08944 peer_unref(peer); 08945 } 08946 } 08947 08948 /* Queue up a new task to handle no reply */ 08949 /* If the host is already unreachable then use the unreachable interval instead */ 08950 if (peer->lastms < 0) { 08951 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer)); 08952 } else 08953 peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer)); 08954 08955 if (peer->pokeexpire == -1) 08956 peer_unref(peer); 08957 08958 /* And send the poke */ 08959 ast_mutex_lock(&iaxsl[callno]); 08960 if (iaxs[callno]) { 08961 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1); 08962 } 08963 ast_mutex_unlock(&iaxsl[callno]); 08964 08965 return 0; 08966 }
| static int iax2_poke_peer_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 8897 of file chan_iax2.c.
References iax2_poke_peer().
Referenced by load_module().
08898 { 08899 struct iax2_peer *peer = obj; 08900 08901 iax2_poke_peer(peer, 0); 08902 08903 return 0; 08904 }
| static int iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 6499 of file chan_iax2.c.
References __iax2_poke_peer_s(), iax2_peer::pokeexpire, and schedule_action.
Referenced by __iax2_poke_noanswer(), and socket_process().
06500 { 06501 struct iax2_peer *peer = (struct iax2_peer *)data; 06502 peer->pokeexpire = -1; 06503 #ifdef SCHED_MULTITHREADED 06504 if (schedule_action(__iax2_poke_peer_s, data)) 06505 #endif 06506 __iax2_poke_peer_s(data); 06507 return 0; 06508 }
| static int iax2_predestroy | ( | int | callno | ) | [static] |
Definition at line 2121 of file chan_iax2.c.
References ast_module_unref(), ast_set_flag, ast_test_flag, iax2_destroy_helper(), iax2_queue_hangup(), IAX_ALREADYGONE, iaxs, chan_iax2_pvt::owner, and ast_channel::tech_pvt.
Referenced by iax2_hangup(), and send_command_final().
02122 { 02123 struct ast_channel *c; 02124 struct chan_iax2_pvt *pvt = iaxs[callno]; 02125 02126 if (!pvt) 02127 return -1; 02128 if (!ast_test_flag(pvt, IAX_ALREADYGONE)) { 02129 iax2_destroy_helper(pvt); 02130 ast_set_flag(pvt, IAX_ALREADYGONE); 02131 } 02132 c = pvt->owner; 02133 if (c) { 02134 c->tech_pvt = NULL; 02135 iax2_queue_hangup(callno); 02136 pvt->owner = NULL; 02137 ast_module_unref(ast_module_info->self); 02138 } 02139 return 0; 02140 }
| static void * iax2_process_thread | ( | void * | data | ) | [static] |
Definition at line 8562 of file chan_iax2.c.
References 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_tvadd(), handle_deferred_full_frames(), iax2_process_thread_cleanup(), IAX_IOSTATE_IDLE, IAX_IOSTATE_PROCESSING, IAX_IOSTATE_READY, IAX_IOSTATE_SCHEDREADY, IAX_TYPE_DYNAMIC, iaxactivethreadcount, iaxdynamicthreadcount, insert_idle_thread(), socket_process(), t, and thread.
Referenced by find_idle_thread(), and start_network_thread().
08563 { 08564 struct iax2_thread *thread = data; 08565 struct timeval tv; 08566 struct timespec ts; 08567 int put_into_idle = 0; 08568 08569 ast_atomic_fetchadd_int(&iaxactivethreadcount,1); 08570 pthread_cleanup_push(iax2_process_thread_cleanup, data); 08571 for(;;) { 08572 /* Wait for something to signal us to be awake */ 08573 ast_mutex_lock(&thread->lock); 08574 08575 /* Flag that we're ready to accept signals */ 08576 thread->ready_for_signal = 1; 08577 08578 /* Put into idle list if applicable */ 08579 if (put_into_idle) 08580 insert_idle_thread(thread); 08581 08582 if (thread->type == IAX_TYPE_DYNAMIC) { 08583 struct iax2_thread *t = NULL; 08584 /* Wait to be signalled or time out */ 08585 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 08586 ts.tv_sec = tv.tv_sec; 08587 ts.tv_nsec = tv.tv_usec * 1000; 08588 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) { 08589 /* This thread was never put back into the available dynamic 08590 * thread list, so just go away. */ 08591 if (!put_into_idle) { 08592 ast_mutex_unlock(&thread->lock); 08593 break; 08594 } 08595 AST_LIST_LOCK(&dynamic_list); 08596 /* Account for the case where this thread is acquired *right* after a timeout */ 08597 if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list))) 08598 iaxdynamicthreadcount--; 08599 AST_LIST_UNLOCK(&dynamic_list); 08600 if (t) { 08601 /* This dynamic thread timed out waiting for a task and was 08602 * not acquired immediately after the timeout, 08603 * so it's time to go away. */ 08604 ast_mutex_unlock(&thread->lock); 08605 break; 08606 } 08607 /* Someone grabbed our thread *right* after we timed out. 08608 * Wait for them to set us up with something to do and signal 08609 * us to continue. */ 08610 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 08611 ts.tv_sec = tv.tv_sec; 08612 ts.tv_nsec = tv.tv_usec * 1000; 08613 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) 08614 { 08615 ast_mutex_unlock(&thread->lock); 08616 break; 08617 } 08618 } 08619 } else { 08620 ast_cond_wait(&thread->cond, &thread->lock); 08621 } 08622 08623 /* Go back into our respective list */ 08624 put_into_idle = 1; 08625 08626 ast_mutex_unlock(&thread->lock); 08627 08628 if (thread->iostate == IAX_IOSTATE_IDLE) 08629 continue; 08630 08631 /* Add ourselves to the active list now */ 08632 AST_LIST_LOCK(&active_list); 08633 AST_LIST_INSERT_HEAD(&active_list, thread, list); 08634 AST_LIST_UNLOCK(&active_list); 08635 08636 /* See what we need to do */ 08637 switch(thread->iostate) { 08638 case IAX_IOSTATE_READY: 08639 thread->actions++; 08640 thread->iostate = IAX_IOSTATE_PROCESSING; 08641 socket_process(thread); 08642 handle_deferred_full_frames(thread); 08643 break; 08644 case IAX_IOSTATE_SCHEDREADY: 08645 thread->actions++; 08646 thread->iostate = IAX_IOSTATE_PROCESSING; 08647 #ifdef SCHED_MULTITHREADED 08648 thread->schedfunc(thread->scheddata); 08649 #endif 08650 break; 08651 } 08652 time(&thread->checktime); 08653 thread->iostate = IAX_IOSTATE_IDLE; 08654 #ifdef DEBUG_SCHED_MULTITHREAD 08655 thread->curfunc[0]='\0'; 08656 #endif 08657 08658 /* Now... remove ourselves from the active list, and return to the idle list */ 08659 AST_LIST_LOCK(&active_list); 08660 AST_LIST_REMOVE(&active_list, thread, list); 08661 AST_LIST_UNLOCK(&active_list); 08662 08663 /* Make sure another frame didn't sneak in there after we thought we were done. */ 08664 handle_deferred_full_frames(thread); 08665 } 08666 08667 /*!\note For some reason, idle threads are exiting without being removed 08668 * from an idle list, which is causing memory corruption. Forcibly remove 08669 * it from the list, if it's there. 08670 */ 08671 AST_LIST_LOCK(&idle_list); 08672 AST_LIST_REMOVE(&idle_list, thread, list); 08673 AST_LIST_UNLOCK(&idle_list); 08674 08675 AST_LIST_LOCK(&dynamic_list); 08676 AST_LIST_REMOVE(&dynamic_list, thread, list); 08677 AST_LIST_UNLOCK(&dynamic_list); 08678 08679 /* I am exiting here on my own volition, I need to clean up my own data structures 08680 * Assume that I am no longer in any of the lists (idle, active, or dynamic) 08681 */ 08682 pthread_cleanup_pop(1); 08683 08684 return NULL; 08685 }
| static void iax2_process_thread_cleanup | ( | void * | data | ) | [static] |
Definition at line 8553 of file chan_iax2.c.
References ast_cond_destroy(), ast_mutex_destroy(), free, iaxactivethreadcount, and thread.
Referenced by iax2_process_thread().
08554 { 08555 struct iax2_thread *thread = data; 08556 ast_mutex_destroy(&thread->lock); 08557 ast_cond_destroy(&thread->cond); 08558 free(thread); 08559 ast_atomic_dec_and_test(&iaxactivethreadcount); 08560 }
| static int iax2_prov_cmd | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 8840 of file chan_iax2.c.
References ast_cli(), iax2_provision(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
08841 { 08842 int force = 0; 08843 int res; 08844 if (argc < 4) 08845 return RESULT_SHOWUSAGE; 08846 if ((argc > 4)) { 08847 if (!strcasecmp(argv[4], "forced")) 08848 force = 1; 08849 else 08850 return RESULT_SHOWUSAGE; 08851 } 08852 res = iax2_provision(NULL, -1, argv[2], argv[3], force); 08853 if (res < 0) 08854 ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]); 08855 else if (res < 1) 08856 ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]); 08857 else 08858 ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : ""); 08859 return RESULT_SUCCESS; 08860 }
| static char* iax2_prov_complete_template_3rd | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 8743 of file chan_iax2.c.
References iax_prov_complete_template().
08744 { 08745 if (pos != 3) 08746 return NULL; 08747 return iax_prov_complete_template(line, word, pos, state); 08748 }
| static int iax2_provision | ( | struct sockaddr_in * | end, | |
| int | sockfd, | |||
| char * | dest, | |||
| const char * | template, | |||
| int | force | |||
| ) | [static] |
Definition at line 8750 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_unlock(), AST_SCHED_DEL, ast_set_flag, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, iax2_registry::callno, create_addr(), find_callno_locked(), iax2_sched_add(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), iaxs, iaxsl, LOG_DEBUG, NEW_FORCE, option_debug, iax_ie_data::pos, send_command(), and create_addr_info::sockfd.
Referenced by check_provisioning(), iax2_prov_app(), and iax2_prov_cmd().
08751 { 08752 /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning 08753 is found for template */ 08754 struct iax_ie_data provdata; 08755 struct iax_ie_data ied; 08756 unsigned int sig; 08757 struct sockaddr_in sin; 08758 int callno; 08759 struct create_addr_info cai; 08760 08761 memset(&cai, 0, sizeof(cai)); 08762 08763 if (option_debug) 08764 ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template); 08765 08766 if (iax_provision_build(&provdata, &sig, template, force)) { 08767 if (option_debug) 08768 ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template); 08769 return 0; 08770 } 08771 08772 if (end) { 08773 memcpy(&sin, end, sizeof(sin)); 08774 cai.sockfd = sockfd; 08775 } else if (create_addr(dest, NULL, &sin, &cai)) 08776 return -1; 08777 08778 /* Build the rest of the message */ 08779 memset(&ied, 0, sizeof(ied)); 08780 iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos); 08781 08782 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 08783 if (!callno) 08784 return -1; 08785 08786 if (iaxs[callno]) { 08787 /* Schedule autodestruct in case they don't ever give us anything back */ 08788 AST_SCHED_DEL(sched, iaxs[callno]->autoid); 08789 iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno); 08790 ast_set_flag(iaxs[callno], IAX_PROVISION); 08791 /* Got a call number now, so go ahead and send the provisioning information */ 08792 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1); 08793 } 08794 ast_mutex_unlock(&iaxsl[callno]); 08795 08796 return 1; 08797 }
| static int iax2_prune_realtime | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 2256 of file chan_iax2.c.
References ast_cli(), ast_set_flag, ast_test_flag, expire_registry(), find_peer(), IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, peer_ref(), peer_unref(), reload_config(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02257 { 02258 struct iax2_peer *peer; 02259 02260 if (argc != 4) 02261 return RESULT_SHOWUSAGE; 02262 if (!strcmp(argv[3],"all")) { 02263 reload_config(); 02264 ast_cli(fd, "OK cache is flushed.\n"); 02265 } else if ((peer = find_peer(argv[3], 0))) { 02266 if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) { 02267 ast_set_flag(peer, IAX_RTAUTOCLEAR); 02268 expire_registry(peer_ref(peer)); 02269 ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]); 02270 } else { 02271 ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]); 02272 } 02273 peer_unref(peer); 02274 } else { 02275 ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]); 02276 } 02277 02278 return RESULT_SUCCESS; 02279 }
| 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 1731 of file chan_iax2.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_control_data(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.
Referenced by socket_process().
01733 { 01734 for (;;) { 01735 if (iaxs[callno] && iaxs[callno]->owner) { 01736 if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) { 01737 /* Avoid deadlock by pausing and trying again */ 01738 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01739 } else { 01740 ast_queue_control_data(iaxs[callno]->owner, control, data, datalen); 01741 ast_mutex_unlock(&iaxs[callno]->owner->lock); 01742 break; 01743 } 01744 } else 01745 break; 01746 } 01747 return 0; 01748 }
| 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 1669 of file chan_iax2.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.
Referenced by __attempt_transmit(), __auto_congest(), __do_deliver(), __get_from_jb(), and socket_process().
01670 { 01671 for (;;) { 01672 if (iaxs[callno] && iaxs[callno]->owner) { 01673 if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) { 01674 /* Avoid deadlock by pausing and trying again */ 01675 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01676 } else { 01677 ast_queue_frame(iaxs[callno]->owner, f); 01678 ast_mutex_unlock(&iaxs[callno]->owner->lock); 01679 break; 01680 } 01681 } else 01682 break; 01683 } 01684 return 0; 01685 }
| 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 1700 of file chan_iax2.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.
Referenced by iax2_predestroy().
01701 { 01702 for (;;) { 01703 if (iaxs[callno] && iaxs[callno]->owner) { 01704 if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) { 01705 /* Avoid deadlock by pausing and trying again */ 01706 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01707 } else { 01708 ast_queue_hangup(iaxs[callno]->owner); 01709 ast_mutex_unlock(&iaxs[callno]->owner->lock); 01710 break; 01711 } 01712 } else 01713 break; 01714 } 01715 return 0; 01716 }
| static struct ast_frame * iax2_read | ( | struct ast_channel * | c | ) | [static, read] |
Definition at line 3448 of file chan_iax2.c.
References ast_log(), ast_null_frame, LOG_NOTICE, and option_verbose.
03449 { 03450 if (option_verbose > 3) 03451 ast_log(LOG_NOTICE, "I should never be called!\n"); 03452 return &ast_null_frame; 03453 }
| static int iax2_register | ( | char * | value, | |
| int | lineno | |||
| ) | [static] |
Definition at line 5981 of file chan_iax2.c.
References iax2_registry::addr, ast_calloc, ast_dnsmgr_lookup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), copy(), iax2_registry::dnsmgr, iax2_registry::expire, free, hostname, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, LOG_WARNING, iax2_registry::refresh, iax2_registry::secret, strsep(), and iax2_registry::username.
Referenced by set_config().
05982 { 05983 struct iax2_registry *reg; 05984 char copy[256]; 05985 char *username, *hostname, *secret; 05986 char *porta; 05987 char *stringp=NULL; 05988 05989 if (!value) 05990 return -1; 05991 ast_copy_string(copy, value, sizeof(copy)); 05992 stringp=copy; 05993 username = strsep(&stringp, "@"); 05994 hostname = strsep(&stringp, "@"); 05995 if (!hostname) { 05996 ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno); 05997 return -1; 05998 } 05999 stringp=username; 06000 username = strsep(&stringp, ":"); 06001 secret = strsep(&stringp, ":"); 06002 stringp=hostname; 06003 hostname = strsep(&stringp, ":"); 06004 porta = strsep(&stringp, ":"); 06005 06006 if (porta && !atoi(porta)) { 06007 ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno); 06008 return -1; 06009 } 06010 if (!(reg = ast_calloc(1, sizeof(*reg)))) 06011 return -1; 06012 if (ast_dnsmgr_lookup(hostname, ®->addr.sin_addr, ®->dnsmgr) < 0) { 06013 free(reg); 06014 return -1; 06015 } 06016 ast_copy_string(reg->username, username, sizeof(reg->username)); 06017 if (secret) 06018 ast_copy_string(reg->secret, secret, sizeof(reg->secret)); 06019 reg->expire = -1; 06020 reg->refresh = IAX_DEFAULT_REG_EXPIRE; 06021 reg->addr.sin_family = AF_INET; 06022 reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO); 06023 AST_LIST_LOCK(®istrations); 06024 AST_LIST_INSERT_HEAD(®istrations, reg, entry); 06025 AST_LIST_UNLOCK(®istrations); 06026 06027 return 0; 06028 }
| static int iax2_reload | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 10276 of file chan_iax2.c.
References reload_config().
10277 { 10278 return reload_config(); 10279 }
| static struct ast_channel * iax2_request | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 8978 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(), iax2_registry::callno, create_addr_info::capability, create_addr(), find_callno_locked(), fmt, create_addr_info::found, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iaxsl, 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.
08979 { 08980 int callno; 08981 int res; 08982 int fmt, native; 08983 struct sockaddr_in sin; 08984 struct ast_channel *c; 08985 struct parsed_dial_string pds; 08986 struct create_addr_info cai; 08987 char *tmpstr; 08988 08989 memset(&pds, 0, sizeof(pds)); 08990 tmpstr = ast_strdupa(data); 08991 parse_dial_string(tmpstr, &pds); 08992 08993 if (ast_strlen_zero(pds.peer)) { 08994 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 08995 return NULL; 08996 } 08997 08998 memset(&cai, 0, sizeof(cai)); 08999 cai.capability = iax2_capability; 09000 09001 ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 09002 09003 /* Populate our address from the given */ 09004 if (create_addr(pds.peer, NULL, &sin, &cai)) { 09005 *cause = AST_CAUSE_UNREGISTERED; 09006 return NULL; 09007 } 09008 09009 if (pds.port) 09010 sin.sin_port = htons(atoi(pds.port)); 09011 09012 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 09013 if (callno < 1) { 09014 ast_log(LOG_WARNING, "Unable to create call\n"); 09015 *cause = AST_CAUSE_CONGESTION; 09016 return NULL; 09017 } 09018 09019 /* If this is a trunk, update it now */ 09020 ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 09021 if (ast_test_flag(&cai, IAX_TRUNK)) { 09022 int new_callno; 09023 if ((new_callno = make_trunk(callno, 1)) != -1) 09024 callno = new_callno; 09025 } 09026 iaxs[callno]->maxtime = cai.maxtime; 09027 if (cai.found) 09028 ast_string_field_set(iaxs[callno], host, pds.peer); 09029 09030 c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability); 09031 09032 ast_mutex_unlock(&iaxsl[callno]); 09033 09034 if (c) { 09035 /* Choose a format we can live with */ 09036 if (c->nativeformats & format) 09037 c->nativeformats &= format; 09038 else { 09039 native = c->nativeformats; 09040 fmt = format; 09041 res = ast_translator_best_choice(&fmt, &native); 09042 if (res < 0) { 09043 ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", 09044 ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name); 09045 ast_hangup(c); 09046 return NULL; 09047 } 09048 c->nativeformats = native; 09049 } 09050 c->readformat = ast_best_codec(c->nativeformats); 09051 c->writeformat = c->readformat; 09052 } 09053 09054 return c; 09055 }
| static int iax2_sched_add | ( | struct sched_context * | con, | |
| int | when, | |||
| ast_sched_cb | callback, | |||
| const void * | data | |||
| ) | [static] |
Definition at line 992 of file chan_iax2.c.
References ast_sched_add(), and signal_condition().
Referenced by __attempt_transmit(), __find_callno(), __iax2_poke_noanswer(), __send_lagrq(), __send_ping(), auth_fail(), iax2_ack_registry(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_poke_peer(), iax2_provision(), make_trunk(), network_thread(), realtime_peer(), reg_source_db(), socket_process(), update_jbsched(), and update_registry().
00993 { 00994 int res; 00995 00996 res = ast_sched_add(con, when, callback, data); 00997 signal_condition(&sched_lock, &sched_cond); 00998 00999 return res; 01000 }
| 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 4299 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, 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, ast_frame::frametype, iax2_transmit(), iax2_trunk_queue(), IAX_COMMAND_ACK, IAX_ENCRYPTED, IAX_FLAG_FULL, iax_frame_new(), iax_frame_wrap(), IAX_KEYPOPULATED, iax_showframe(), IAX_TRUNK, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, chan_iax2_pvt::lastsent, chan_iax2_pvt::lastvsent, LOG_WARNING, 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, 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().
04300 { 04301 /* Queue a packet for delivery on a given private structure. Use "ts" for 04302 timestamp, or calculate if ts is 0. Send immediately without retransmission 04303 or delayed, with retransmission */ 04304 struct ast_iax2_full_hdr *fh; 04305 struct ast_iax2_mini_hdr *mh; 04306 struct ast_iax2_video_hdr *vh; 04307 struct { 04308 struct iax_frame fr2; 04309 unsigned char buffer[4096]; 04310 } frb; 04311 struct iax_frame *fr; 04312 int res; 04313 int sendmini=0; 04314 unsigned int lastsent; 04315 unsigned int fts; 04316 04317 frb.fr2.afdatalen = sizeof(frb.buffer); 04318 04319 if (!pvt) { 04320 ast_log(LOG_WARNING, "No private structure for packet?\n"); 04321 return -1; 04322 } 04323 04324 lastsent = pvt->lastsent; 04325 04326 /* Calculate actual timestamp */ 04327 fts = calc_timestamp(pvt, ts, f); 04328 04329 /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out 04330 * (the endpoint should detect the lost packet itself). But, we want to do this here, so that we 04331 * increment the "predicted timestamps" for voice, if we're predecting */ 04332 if(f->frametype == AST_FRAME_VOICE && f->datalen == 0) 04333 return 0; 04334 04335 04336 if ((ast_test_flag(pvt, IAX_TRUNK) || 04337 (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) || 04338 ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L)))) 04339 /* High two bytes are the same on timestamp, or sending on a trunk */ && 04340 (f->frametype == AST_FRAME_VOICE) 04341 /* is a voice frame */ && 04342 (f->subclass == pvt->svoiceformat) 04343 /* is the same type */ ) { 04344 /* Force immediate rather than delayed transmission */ 04345 now = 1; 04346 /* Mark that mini-style frame is appropriate */ 04347 sendmini = 1; 04348 } 04349 if ( f->frametype == AST_FRAME_VIDEO ) { 04350 /* 04351 * If the lower 15 bits of the timestamp roll over, or if 04352 * the video format changed then send a full frame. 04353 * Otherwise send a mini video frame 04354 */ 04355 if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) && 04356 ((f->subclass & ~0x1) == pvt->svideoformat) 04357 ) { 04358 now = 1; 04359 sendmini = 1; 04360 } else { 04361 now = 0; 04362 sendmini = 0; 04363 } 04364 pvt->lastvsent = fts; 04365 } 04366 /* Allocate an iax_frame */ 04367 if (now) { 04368 fr = &frb.fr2; 04369 } else 04370 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)); 04371 if (!fr) { 04372 ast_log(LOG_WARNING, "Out of memory\n"); 04373 return -1; 04374 } 04375 /* Copy our prospective frame into our immediate or retransmitted wrapper */ 04376 iax_frame_wrap(fr, f); 04377 04378 fr->ts = fts; 04379 fr->callno = pvt->callno; 04380 fr->transfer = transfer; 04381 fr->final = final; 04382 fr->encmethods = 0; 04383 if (!sendmini) { 04384 /* We need a full frame */ 04385 if (seqno > -1) 04386 fr->oseqno = seqno; 04387 else 04388 fr->oseqno = pvt->oseqno++; 04389 fr->iseqno = pvt->iseqno; 04390 fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr)); 04391 fh->scallno = htons(fr->callno | IAX_FLAG_FULL); 04392 fh->ts = htonl(fr->ts); 04393 fh->oseqno = fr->oseqno; 04394 if (transfer) { 04395 fh->iseqno = 0; 04396 } else 04397 fh->iseqno = fr->iseqno; 04398 /* Keep track of the last thing we've acknowledged */ 04399 if (!transfer) 04400 pvt->aseqno = fr->iseqno; 04401 fh->type = fr->af.frametype & 0xFF; 04402 if (fr->af.frametype == AST_FRAME_VIDEO) 04403 fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6); 04404 else 04405 fh->csub = compress_subclass(fr->af.subclass); 04406 if (transfer) { 04407 fr->dcallno = pvt->transfercallno; 04408 } else 04409 fr->dcallno = pvt->peercallno; 04410 fh->dcallno = htons(fr->dcallno); 04411 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr); 04412 fr->data = fh; 04413 fr->retries = 0; 04414 /* Retry after 2x the ping time has passed */ 04415 fr->retrytime = pvt->pingtime * 2; 04416 if (fr->retrytime < MIN_RETRY_TIME) 04417 fr->retrytime = MIN_RETRY_TIME; 04418 if (fr->retrytime > MAX_RETRY_TIME) 04419 fr->retrytime = MAX_RETRY_TIME; 04420 /* Acks' don't get retried */ 04421 if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK)) 04422 fr->retries = -1; 04423 else if (f->frametype == AST_FRAME_VOICE) 04424 pvt->svoiceformat = f->subclass; 04425 else if (f->frametype == AST_FRAME_VIDEO) 04426 pvt->svideoformat = f->subclass & ~0x1; 04427 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 04428 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 04429 if (iaxdebug) { 04430 if (fr->transfer) 04431 iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 04432 else 04433 iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 04434 } 04435 encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen); 04436 fr->encmethods = pvt->encmethods; 04437 fr->ecx = pvt->ecx; 04438 fr->mydcx = pvt->mydcx; 04439 memcpy(fr->semirand, pvt->semirand, sizeof(fr->semirand)); 04440 } else 04441 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 04442 } 04443 04444 if (now) { 04445 res = send_packet(fr); 04446 } else 04447 res = iax2_transmit(fr); 04448 } else { 04449 if (ast_test_flag(pvt, IAX_TRUNK)) { 04450 iax2_trunk_queue(pvt, fr); 04451 res = 0; 04452 } else if (fr->af.frametype == AST_FRAME_VIDEO) { 04453 /* Video frame have no sequence number */ 04454 fr->oseqno = -1; 04455 fr->iseqno = -1; 04456 vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr)); 04457 vh->zeros = 0; 04458 vh->callno = htons(0x8000 | fr->callno); 04459 vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0)); 04460 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr); 04461 fr->data = vh; 04462 fr->retries = -1; 04463 res = send_packet(fr); 04464 } else { 04465 /* Mini-frames have no sequence number */ 04466 fr->oseqno = -1; 04467 fr->iseqno = -1; 04468 /* Mini frame will do */ 04469 mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr)); 04470 mh->callno = htons(fr->callno); 04471 mh->ts = htons(fr->ts & 0xFFFF); 04472 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr); 04473 fr->data = mh; 04474 fr->retries = -1; 04475 if (pvt->transferring == TRANSFER_MEDIAPASS) 04476 fr->transfer = 1; 04477 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 04478 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 04479 encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen); 04480 } else 04481 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 04482 } 04483 res = send_packet(fr); 04484 } 04485 } 04486 return res; 04487 }
| static int iax2_sendhtml | ( | struct ast_channel * | c, | |
| int | subclass, | |||
| const char * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 2781 of file chan_iax2.c.
References AST_FRAME_HTML, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02782 { 02783 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1); 02784 }
| static int iax2_sendimage | ( | struct ast_channel * | c, | |
| struct ast_frame * | img | |||
| ) | [static] |
Definition at line 2776 of file chan_iax2.c.
References AST_FRAME_IMAGE, ast_frame::data, ast_frame::datalen, PTR_TO_CALLNO, send_command_locked(), ast_frame::subclass, and ast_channel::tech_pvt.
02777 { 02778 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1); 02779 }
| static int iax2_sendtext | ( | struct ast_channel * | c, | |
| const char * | text | |||
| ) | [static] |
Definition at line 2769 of file chan_iax2.c.
References AST_FRAME_TEXT, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02770 { 02771 02772 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT, 02773 0, 0, (unsigned char *)text, strlen(text) + 1, -1); 02774 }
| static int iax2_setoption | ( | struct ast_channel * | c, | |
| int | option, | |||
| void * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 3422 of file chan_iax2.c.
References AST_CONTROL_OPTION, AST_FRAME_CONTROL, ast_malloc, AST_OPTION_FLAG_REQUEST, AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, ast_option_header::data, errno, ast_option_header::flag, free, ast_option_header::option, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03423 { 03424 struct ast_option_header *h; 03425 int res; 03426 03427 switch (option) { 03428 case AST_OPTION_TXGAIN: 03429 case AST_OPTION_RXGAIN: 03430 /* these two cannot be sent, because they require a result */ 03431 errno = ENOSYS; 03432 return -1; 03433 default: 03434 if (!(h = ast_malloc(datalen + sizeof(*h)))) 03435 return -1; 03436 03437 h->flag = AST_OPTION_FLAG_REQUEST; 03438 h->option = htons(option); 03439 memcpy(h->data, data, datalen); 03440 res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL, 03441 AST_CONTROL_OPTION, 0, (unsigned char *) h, 03442 datalen + sizeof(*h), -1); 03443 free(h); 03444 return res; 03445 } 03446 }
| static int iax2_show_cache | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 2460 of file chan_iax2.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, CACHE_FLAG_TRANSMITTED, CACHE_FLAG_UNKNOWN, dpcache, iax2_dpcache::expiry, iax2_dpcache::exten, iax2_dpcache::flags, iax2_dpcache::next, iax2_dpcache::peercontext, RESULT_SUCCESS, s, and iax2_dpcache::waiters.
02461 { 02462 struct iax2_dpcache *dp; 02463 char tmp[1024], *pc; 02464 int s; 02465 int x,y; 02466 struct timeval tv; 02467 gettimeofday(&tv, NULL); 02468 ast_mutex_lock(&dpcache_lock); 02469 dp = dpcache; 02470 ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags"); 02471 while(dp) { 02472 s = dp->expiry.tv_sec - tv.tv_sec; 02473 tmp[0] = '\0'; 02474 if (dp->flags & CACHE_FLAG_EXISTS) 02475 strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1); 02476 if (dp->flags & CACHE_FLAG_NONEXISTENT) 02477 strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1); 02478 if (dp->flags & CACHE_FLAG_CANEXIST) 02479 strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1); 02480 if (dp->flags & CACHE_FLAG_PENDING) 02481 strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1); 02482 if (dp->flags & CACHE_FLAG_TIMEOUT) 02483 strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1); 02484 if (dp->flags & CACHE_FLAG_TRANSMITTED) 02485 strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1); 02486 if (dp->flags & CACHE_FLAG_MATCHMORE) 02487 strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1); 02488 if (dp->flags & CACHE_FLAG_UNKNOWN) 02489 strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1); 02490 /* Trim trailing pipe */ 02491 if (!ast_strlen_zero(tmp)) 02492 tmp[strlen(tmp) - 1] = '\0'; 02493 else 02494 ast_copy_string(tmp, "(none)", sizeof(tmp)); 02495 y=0; 02496 pc = strchr(dp->peercontext, '@'); 02497 if (!pc) 02498 pc = dp->peercontext; 02499 else 02500 pc++; 02501 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 02502 if (dp->waiters[x] > -1) 02503 y++; 02504 if (s > 0) 02505 ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp); 02506 else 02507 ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp); 02508 dp = dp->next; 02509 } 02510 ast_mutex_unlock(&dpcache_lock); 02511 return RESULT_SUCCESS; 02512 }
| static int iax2_show_channels | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4831 of file chan_iax2.c.
References iax2_registry::addr, ARRAY_LEN, ast_cli(), ast_getformatname(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, jb_info::current, iax_rr::delay, FORMAT, FORMAT2, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), jb_info::jitter, jb_info::min, chan_iax2_pvt::remote_rr, RESULT_SHOWUSAGE, RESULT_SUCCESS, and S_OR.
04832 { 04833 #define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n" 04834 #define FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n" 04835 #define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" 04836 int x; 04837 int numchans = 0; 04838 04839 if (argc != 3) 04840 return RESULT_SHOWUSAGE; 04841 ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format"); 04842 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 04843 ast_mutex_lock(&iaxsl[x]); 04844 if (iaxs[x]) { 04845 int lag, jitter, localdelay; 04846 jb_info jbinfo; 04847 04848 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 04849 jb_getinfo(iaxs[x]->jb, &jbinfo); 04850 jitter = jbinfo.jitter; 04851 localdelay = jbinfo.current - jbinfo.min; 04852 } else { 04853 jitter = -1; 04854 localdelay = 0; 04855 } 04856 lag = iaxs[x]->remote_rr.delay; 04857 ast_cli(fd, FORMAT, 04858 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04859 ast_inet_ntoa(iaxs[x]->addr.sin_addr), 04860 S_OR(iaxs[x]->username, "(None)"), 04861 iaxs[x]->callno, iaxs[x]->peercallno, 04862 iaxs[x]->oseqno, iaxs[x]->iseqno, 04863 lag, 04864 jitter, 04865 localdelay, 04866 ast_getformatname(iaxs[x]->voiceformat) ); 04867 numchans++; 04868 } 04869 ast_mutex_unlock(&iaxsl[x]); 04870 } 04871 ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 04872 return RESULT_SUCCESS; 04873 #undef FORMAT 04874 #undef FORMAT2 04875 #undef FORMATB 04876 }
| static int iax2_show_firmware | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4742 of file chan_iax2.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, FORMAT, FORMAT2, iax_firmware::fwh, ast_firmware_list::lock, iax_firmware::next, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.
04743 { 04744 #define FORMAT2 "%-15.15s %-15.15s %-15.15s\n" 04745 #if !defined(__FreeBSD__) 04746 #define FORMAT "%-15.15s %-15d %-15d\n" 04747 #else /* __FreeBSD__ */ 04748 #define FORMAT "%-15.15s %-15d %-15d\n" /* XXX 2.95 ? */ 04749 #endif /* __FreeBSD__ */ 04750 struct iax_firmware *cur; 04751 if ((argc != 3) && (argc != 4)) 04752 return RESULT_SHOWUSAGE; 04753 ast_mutex_lock(&waresl.lock); 04754 04755 ast_cli(fd, FORMAT2, "Device", "Version", "Size"); 04756 for (cur = waresl.wares;cur;cur = cur->next) { 04757 if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 04758 ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version), 04759 (int)ntohl(cur->fwh->datalen)); 04760 } 04761 ast_mutex_unlock(&waresl.lock); 04762 return RESULT_SUCCESS; 04763 #undef FORMAT 04764 #undef FORMAT2 04765 }
| static int iax2_show_netstats | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4954 of file chan_iax2.c.
References ast_cli(), ast_cli_netstats(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04955 { 04956 int numchans = 0; 04957 if (argc != 3) 04958 return RESULT_SHOWUSAGE; 04959 ast_cli(fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n"); 04960 ast_cli(fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts\n"); 04961 numchans = ast_cli_netstats(NULL, fd, 1); 04962 ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 04963 return RESULT_SUCCESS; 04964 }
| static int iax2_show_peer | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Show one peer in detail.
Definition at line 2350 of file chan_iax2.c.
References iax2_peer::addr, ast_callerid_merge(), ast_cli(), ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, iax2_peer::capability, iax2_peer::defaddr, iax2_peer::expire, find_peer(), iax2_peer::ha, IAX_DYNAMIC, peer_status(), peer_unref(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax2_peer::prefs, RESULT_SHOWUSAGE, RESULT_SUCCESS, and iax2_peer::smoothing.
02351 { 02352 char status[30]; 02353 char cbuf[256]; 02354 struct iax2_peer *peer; 02355 char codec_buf[512]; 02356 int x = 0, codec = 0, load_realtime = 0; 02357 02358 if (argc < 4) 02359 return RESULT_SHOWUSAGE; 02360 02361 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0; 02362 02363 peer = find_peer(argv[3], load_realtime); 02364 if (peer) { 02365 ast_cli(fd,"\n\n"); 02366 ast_cli(fd, " * Name : %s\n", peer->name); 02367 ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>"); 02368 ast_cli(fd, " Context : %s\n", peer->context); 02369 ast_cli(fd, " Mailbox : %s\n", peer->mailbox); 02370 ast_cli(fd, " Dynamic : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No"); 02371 ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 02372 ast_cli(fd, " Expire : %d\n", peer->expire); 02373 ast_cli(fd, " ACL : %s\n", (peer->ha?"Yes":"No")); 02374 ast_cli(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)); 02375 ast_cli(fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 02376 ast_cli(fd, " Username : %s\n", peer->username); 02377 ast_cli(fd, " Codecs : "); 02378 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 02379 ast_cli(fd, "%s\n", codec_buf); 02380 02381 ast_cli(fd, " Codec Order : ("); 02382 for(x = 0; x < 32 ; x++) { 02383 codec = ast_codec_pref_index(&peer->prefs,x); 02384 if(!codec) 02385 break; 02386 ast_cli(fd, "%s", ast_getformatname(codec)); 02387 if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1)) 02388 ast_cli(fd, "|"); 02389 } 02390 02391 if (!x) 02392 ast_cli(fd, "none"); 02393 ast_cli(fd, ")\n"); 02394 02395 ast_cli(fd, " Status : "); 02396 peer_status(peer, status, sizeof(status)); 02397 ast_cli(fd, "%s\n",status); 02398 ast_cli(fd, " Qualify : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off"); 02399 ast_cli(fd,"\n"); 02400 peer_unref(peer); 02401 } else { 02402 ast_cli(fd,"Peer %s not found.\n", argv[3]); 02403 ast_cli(fd,"\n"); 02404 } 02405 02406 return RESULT_SUCCESS; 02407 }
| static int iax2_show_peers | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4731 of file chan_iax2.c.
References __iax2_show_peers().
04732 { 04733 return __iax2_show_peers(0, fd, NULL, argc, argv); 04734 }
| static int iax2_show_registry | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4803 of file chan_iax2.c.
References iax2_registry::addr, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax2_registry::dnsmgr, FORMAT, FORMAT2, iax2_registry::refresh, iax2_registry::regstate, regstate2str(), RESULT_SHOWUSAGE, RESULT_SUCCESS, iax2_registry::us, and iax2_registry::username.
04804 { 04805 #define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" 04806 #define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" 04807 struct iax2_registry *reg = NULL; 04808 04809 char host[80]; 04810 char perceived[80]; 04811 if (argc != 3) 04812 return RESULT_SHOWUSAGE; 04813 ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State"); 04814 AST_LIST_LOCK(®istrations); 04815 AST_LIST_TRAVERSE(®istrations, reg, entry) { 04816 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port)); 04817 if (reg->us.sin_addr.s_addr) 04818 snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 04819 else 04820 ast_copy_string(perceived, "<Unregistered>", sizeof(perceived)); 04821 ast_cli(fd, FORMAT, host, 04822 (reg->dnsmgr) ? "Y" : "N", 04823 reg->username, perceived, reg->refresh, regstate2str(reg->regstate)); 04824 } 04825 AST_LIST_UNLOCK(®istrations); 04826 return RESULT_SUCCESS; 04827 #undef FORMAT 04828 #undef FORMAT2 04829 }
| static int iax2_show_stats | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 2434 of file chan_iax2.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax_frame::final, iax_get_frames(), iax_get_iframes(), iax_get_oframes(), iaxq, RESULT_SHOWUSAGE, RESULT_SUCCESS, and iax_frame::retries.
02435 { 02436 struct iax_frame *cur; 02437 int cnt = 0, dead=0, final=0; 02438 02439 if (argc != 3) 02440 return RESULT_SHOWUSAGE; 02441 02442 AST_LIST_LOCK(&iaxq.queue); 02443 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 02444 if (cur->retries < 0) 02445 dead++; 02446 if (cur->final) 02447 final++; 02448 cnt++; 02449 } 02450 AST_LIST_UNLOCK(&iaxq.queue); 02451 02452 ast_cli(fd, " IAX Statistics\n"); 02453 ast_cli(fd, "---------------------\n"); 02454 ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes()); 02455 ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt); 02456 02457 return RESULT_SUCCESS; 02458 }
| static int iax2_show_threads | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4672 of file chan_iax2.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, IAX_TYPE_DYNAMIC, iaxthreadcount, RESULT_SHOWUSAGE, RESULT_SUCCESS, t, and thread.
04673 { 04674 struct iax2_thread *thread = NULL; 04675 time_t t; 04676 int threadcount = 0, dynamiccount = 0; 04677 char type; 04678 04679 if (argc != 3) 04680 return RESULT_SHOWUSAGE; 04681 04682 ast_cli(fd, "IAX2 Thread Information\n"); 04683 time(&t); 04684 ast_cli(fd, "Idle Threads:\n"); 04685 AST_LIST_LOCK(&idle_list); 04686 AST_LIST_TRAVERSE(&idle_list, thread, list) { 04687 #ifdef DEBUG_SCHED_MULTITHREAD 04688 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 04689 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04690 #else 04691 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 04692 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04693 #endif 04694 threadcount++; 04695 } 04696 AST_LIST_UNLOCK(&idle_list); 04697 ast_cli(fd, "Active Threads:\n"); 04698 AST_LIST_LOCK(&active_list); 04699 AST_LIST_TRAVERSE(&active_list, thread, list) { 04700 if (thread->type == IAX_TYPE_DYNAMIC) 04701 type = 'D'; 04702 else 04703 type = 'P'; 04704 #ifdef DEBUG_SCHED_MULTITHREAD 04705 ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 04706 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04707 #else 04708 ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 04709 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04710 #endif 04711 threadcount++; 04712 } 04713 AST_LIST_UNLOCK(&active_list); 04714 ast_cli(fd, "Dynamic Threads:\n"); 04715 AST_LIST_LOCK(&dynamic_list); 04716 AST_LIST_TRAVERSE(&dynamic_list, thread, list) { 04717 #ifdef DEBUG_SCHED_MULTITHREAD 04718 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 04719 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04720 #else 04721 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 04722 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04723 #endif 04724 dynamiccount++; 04725 } 04726 AST_LIST_UNLOCK(&dynamic_list); 04727 ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount); 04728 return RESULT_SUCCESS; 04729 }
| static int iax2_show_users | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 4489 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_cli(), ast_strlen_zero(), ast_test_flag, iax2_user::authmethods, iax2_context::context, iax2_user::contexts, FORMAT, FORMAT2, iax2_user::ha, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, RESULT_SHOWUSAGE, RESULT_SUCCESS, user_unref(), and users.
04490 { 04491 regex_t regexbuf; 04492 int havepattern = 0; 04493 04494 #define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" 04495 #define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" 04496 04497 struct iax2_user *user = NULL; 04498 char auth[90]; 04499 char *pstr = ""; 04500 struct ao2_iterator i; 04501 04502 switch (argc) { 04503 case 5: 04504 if (!strcasecmp(argv[3], "like")) { 04505 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 04506 return RESULT_SHOWUSAGE; 04507 havepattern = 1; 04508 } else 04509 return RESULT_SHOWUSAGE; 04510 case 3: 04511 break; 04512 default: 04513 return RESULT_SHOWUSAGE; 04514 } 04515 04516 ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref"); 04517 i = ao2_iterator_init(users, 0); 04518 for (user = ao2_iterator_next(&i); user; 04519 user_unref(user), user = ao2_iterator_next(&i)) { 04520 if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) 04521 continue; 04522 04523 if (!ast_strlen_zero(user->secret)) { 04524 ast_copy_string(auth,user->secret,sizeof(auth)); 04525 } else if (!ast_strlen_zero(user->inkeys)) { 04526 snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys); 04527 } else 04528 ast_copy_string(auth, "-no secret-", sizeof(auth)); 04529 04530 if(ast_test_flag(user,IAX_CODEC_NOCAP)) 04531 pstr = "REQ Only"; 04532 else if(ast_test_flag(user,IAX_CODEC_NOPREFS)) 04533 pstr = "Disabled"; 04534 else 04535 pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host"; 04536 04537 ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 04538 user->contexts ? user->contexts->context : context, 04539 user->ha ? "Yes" : "No", pstr); 04540 } 04541 04542 if (havepattern) 04543 regfree(®exbuf); 04544 04545 return RESULT_SUCCESS; 04546 #undef FORMAT 04547 #undef FORMAT2 04548 }
| static int iax2_start_transfer | ( | unsigned short | callno0, | |
| unsigned short | callno1, | |||
| int | mediaonly | |||
| ) | [static] |
Definition at line 3455 of file chan_iax2.c.
References iax2_registry::addr, AST_FRAME_IAX, ast_random(), iax_ie_data::buf, 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, iaxs, iax_ie_data::pos, send_command(), TRANSFER_BEGIN, TRANSFER_MBEGIN, and chan_iax2_pvt::transferring.
Referenced by iax2_bridge().
03456 { 03457 int res; 03458 struct iax_ie_data ied0; 03459 struct iax_ie_data ied1; 03460 unsigned int transferid = (unsigned int)ast_random(); 03461 memset(&ied0, 0, sizeof(ied0)); 03462 iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr); 03463 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno); 03464 iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid); 03465 03466 memset(&ied1, 0, sizeof(ied1)); 03467 iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr); 03468 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno); 03469 iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid); 03470 03471 res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1); 03472 if (res) 03473 return -1; 03474 res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1); 03475 if (res) 03476 return -1; 03477 iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 03478 iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 03479 return 0; 03480 }
| static int iax2_test_losspct | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 2281 of file chan_iax2.c.
References RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02282 { 02283 if (argc != 4) 02284 return RESULT_SHOWUSAGE; 02285 02286 test_losspct = atoi(argv[3]); 02287 02288 return RESULT_SUCCESS; 02289 }
| static int iax2_transfer | ( | struct ast_channel * | c, | |
| const char * | dest | |||
| ) | [static] |
Definition at line 3701 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), iax_ie_data::buf, iax2_registry::callno, IAX_COMMAND_TRANSFER, iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, LOG_DEBUG, option_debug, iax_ie_data::pos, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03702 { 03703 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03704 struct iax_ie_data ied; 03705 char tmp[256], *context; 03706 ast_copy_string(tmp, dest, sizeof(tmp)); 03707 context = strchr(tmp, '@'); 03708 if (context) { 03709 *context = '\0'; 03710 context++; 03711 } 03712 memset(&ied, 0, sizeof(ied)); 03713 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp); 03714 if (context) 03715 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context); 03716 if (option_debug) 03717 ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest); 03718 return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1); 03719 }
| static int iax2_transmit | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 2740 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, iaxq, iax_frame::sentyet, and signal_condition().
Referenced by iax2_send().
02741 { 02742 /* Lock the queue and place this packet at the end */ 02743 /* By setting this to 0, the network thread will send it for us, and 02744 queue retransmission if necessary */ 02745 fr->sentyet = 0; 02746 AST_LIST_LOCK(&iaxq.queue); 02747 AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list); 02748 iaxq.count++; 02749 AST_LIST_UNLOCK(&iaxq.queue); 02750 /* Wake up the network and scheduler thread */ 02751 if (netthreadid != AST_PTHREADT_NULL) 02752 pthread_kill(netthreadid, SIGURG); 02753 signal_condition(&sched_lock, &sched_cond); 02754 return 0; 02755 }
| static int iax2_trunk_expired | ( | struct iax2_trunk_peer * | tpeer, | |
| struct timeval * | now | |||
| ) | [inline, static] |
Definition at line 6554 of file chan_iax2.c.
References iax2_trunk_peer::trunkact.
Referenced by timing_read().
06555 { 06556 /* Drop when trunk is about 5 seconds idle */ 06557 if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 06558 return 1; 06559 return 0; 06560 }
| static int iax2_trunk_queue | ( | struct chan_iax2_pvt * | pvt, | |
| struct iax_frame * | fr | |||
| ) | [static] |
Definition at line 4064 of file chan_iax2.c.
References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, 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_DEBUG, LOG_WARNING, MAX_TRUNKDATA, ast_iax2_meta_trunk_mini::mini, option_debug, 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().
04065 { 04066 struct ast_frame *f; 04067 struct iax2_trunk_peer *tpeer; 04068 void *tmp, *ptr; 04069 struct ast_iax2_meta_trunk_entry *met; 04070 struct ast_iax2_meta_trunk_mini *mtm; 04071 04072 f = &fr->af; 04073 tpeer = find_tpeer(&pvt->addr, pvt->sockfd); 04074 if (tpeer) { 04075 if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) { 04076 /* Need to reallocate space */ 04077 if (tpeer->trunkdataalloc < MAX_TRUNKDATA) { 04078 if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) { 04079 ast_mutex_unlock(&tpeer->lock); 04080 return -1; 04081 } 04082 04083 tpeer->trunkdataalloc += DEFAULT_TRUNKDATA; 04084 tpeer->trunkdata = tmp; 04085 if (option_debug) 04086 ast_log(LOG_DEBUG, "Expanded trunk '%s:%d' to %d bytes\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), tpeer->trunkdataalloc); 04087 } else { 04088 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)); 04089 ast_mutex_unlock(&tpeer->lock); 04090 return -1; 04091 } 04092 } 04093 04094 /* Append to meta frame */ 04095 ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen; 04096 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) { 04097 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 04098 mtm->len = htons(f->datalen); 04099 mtm->mini.callno = htons(pvt->callno); 04100 mtm->mini.ts = htons(0xffff & fr->ts); 04101 ptr += sizeof(struct ast_iax2_meta_trunk_mini); 04102 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini); 04103 } else { 04104 met = (struct ast_iax2_meta_trunk_entry *)ptr; 04105 /* Store call number and length in meta header */ 04106 met->callno = htons(pvt->callno); 04107 met->len = htons(f->datalen); 04108 /* Advance pointers/decrease length past trunk entry header */ 04109 ptr += sizeof(struct ast_iax2_meta_trunk_entry); 04110 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry); 04111 } 04112 /* Copy actual trunk data */ 04113 memcpy(ptr, f->data, f->datalen); 04114 tpeer->trunkdatalen += f->datalen; 04115 04116 tpeer->calls++; 04117 ast_mutex_unlock(&tpeer->lock); 04118 } 04119 return 0; 04120 }
| static int iax2_vnak | ( | int | callno | ) | [static] |
Definition at line 6471 of file chan_iax2.c.
References AST_FRAME_IAX, IAX_COMMAND_VNAK, iaxs, and send_command_immediate().
Referenced by socket_process().
06472 { 06473 return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno); 06474 }
| static int iax2_write | ( | struct ast_channel * | c, | |
| struct ast_frame * | f | |||
| ) | [static] |
Definition at line 5021 of file chan_iax2.c.
References AST_FRAME_NULL, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, errno, error(), ast_frame::frametype, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, iaxs, iaxsl, LOG_DEBUG, option_debug, PTR_TO_CALLNO, and ast_channel::tech_pvt.
05022 { 05023 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 05024 int res = -1; 05025 ast_mutex_lock(&iaxsl[callno]); 05026 if (iaxs[callno]) { 05027 /* If there's an outstanding error, return failure now */ 05028 if (!iaxs[callno]->error) { 05029 if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) 05030 res = 0; 05031 /* Don't waste bandwidth sending null frames */ 05032 else if (f->frametype == AST_FRAME_NULL) 05033 res = 0; 05034 else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH)) 05035 res = 0; 05036 else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 05037 res = 0; 05038 else 05039 /* Simple, just queue for transmission */ 05040 res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0); 05041 } else { 05042 if (option_debug) 05043 ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno)); 05044 } 05045 } 05046 /* If it's already gone, just return */ 05047 ast_mutex_unlock(&iaxsl[callno]); 05048 return res; 05049 }
| static int iax_check_version | ( | char * | dev | ) | [static] |
Definition at line 1904 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_iax2_firmware_header::devname, iax_firmware::fwh, ast_firmware_list::lock, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.
Referenced by update_registry().
01905 { 01906 int res = 0; 01907 struct iax_firmware *cur; 01908 if (!ast_strlen_zero(dev)) { 01909 ast_mutex_lock(&waresl.lock); 01910 cur = waresl.wares; 01911 while(cur) { 01912 if (!strcmp(dev, (char *)cur->fwh->devname)) { 01913 res = ntohs(cur->fwh->version); 01914 break; 01915 } 01916 cur = cur->next; 01917 } 01918 ast_mutex_unlock(&waresl.lock); 01919 } 01920 return res; 01921 }
| static void iax_debug_output | ( | const char * | data | ) | [static] |
Definition at line 766 of file chan_iax2.c.
References ast_verbose().
Referenced by load_module().
00767 { 00768 if (iaxdebug) 00769 ast_verbose("%s", data); 00770 }
| static void iax_error_output | ( | const char * | data | ) | [static] |
Definition at line 772 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by load_module().
00773 { 00774 ast_log(LOG_WARNING, "%s", data); 00775 }
| static int iax_firmware_append | ( | struct iax_ie_data * | ied, | |
| const unsigned char * | dev, | |||
| unsigned int | desc | |||
| ) | [static] |
Definition at line 1923 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_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, IAX_IE_FWBLOCKDESC, ast_firmware_list::lock, iax_firmware::next, ast_firmware_list::wares, and waresl.
Referenced by socket_process().
01924 { 01925 int res = -1; 01926 unsigned int bs = desc & 0xff; 01927 unsigned int start = (desc >> 8) & 0xffffff; 01928 unsigned int bytes; 01929 struct iax_firmware *cur; 01930 if (!ast_strlen_zero((char *)dev) && bs) { 01931 start *= bs; 01932 ast_mutex_lock(&waresl.lock); 01933 cur = waresl.wares; 01934 while(cur) { 01935 if (!strcmp((char *)dev, (char *)cur->fwh->devname)) { 01936 iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc); 01937 if (start < ntohl(cur->fwh->datalen)) { 01938 bytes = ntohl(cur->fwh->datalen) - start; 01939 if (bytes > bs) 01940 bytes = bs; 01941 iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes); 01942 } else { 01943 bytes = 0; 01944 iax_ie_append(ied, IAX_IE_FWBLOCKDATA); 01945 } 01946 if (bytes == bs) 01947 res = 0; 01948 else 01949 res = 1; 01950 break; 01951 } 01952 cur = cur->next; 01953 } 01954 ast_mutex_unlock(&waresl.lock); 01955 } 01956 return res; 01957 }
| static int iax_park | ( | struct ast_channel * | chan1, | |
| struct ast_channel * | chan2 | |||
| ) | [static] |
Definition at line 6742 of file chan_iax2.c.
References ast_channel::amaflags, ast_calloc, ast_channel_alloc(), ast_channel_masquerade(), ast_do_masquerade(), ast_hangup(), ast_log(), ast_pthread_create_background, AST_STATE_DOWN, iax_dual::chan1, iax_dual::chan2, ast_channel::context, ast_channel::exten, free, iax_park_thread(), LOG_WARNING, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.
Referenced by socket_process().
06743 { 06744 struct iax_dual *d; 06745 struct ast_channel *chan1m, *chan2m; 06746 pthread_t th; 06747 chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name); 06748 chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name); 06749 if (chan2m && chan1m) { 06750 /* Make formats okay */ 06751 chan1m->readformat = chan1->readformat; 06752 chan1m->writeformat = chan1->writeformat; 06753 ast_channel_masquerade(chan1m, chan1); 06754 /* Setup the extensions and such */ 06755 ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context)); 06756 ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten)); 06757 chan1m->priority = chan1->priority; 06758 06759 /* We make a clone of the peer channel too, so we can play 06760 back the announcement */ 06761 /* Make formats okay */ 06762 chan2m->readformat = chan2->readformat; 06763 chan2m->writeformat = chan2->writeformat; 06764 ast_channel_masquerade(chan2m, chan2); 06765 /* Setup the extensions and such */ 06766 ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context)); 06767 ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten)); 06768 chan2m->priority = chan2->priority; 06769 if (ast_do_masquerade(chan2m)) { 06770 ast_log(LOG_WARNING, "Masquerade failed :(\n"); 06771 ast_hangup(chan2m); 06772 return -1; 06773 } 06774 } else { 06775 if (chan1m) 06776 ast_hangup(chan1m); 06777 if (chan2m) 06778 ast_hangup(chan2m); 06779 return -1; 06780 } 06781 if ((d = ast_calloc(1, sizeof(*d)))) { 06782 pthread_attr_t attr; 06783 06784 pthread_attr_init(&attr); 06785 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 06786 06787 d->chan1 = chan1m; 06788 d->chan2 = chan2m; 06789 if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) { 06790 pthread_attr_destroy(&attr); 06791 return 0; 06792 } 06793 pthread_attr_destroy(&attr); 06794 free(d); 06795 } 06796 return -1; 06797 }
| static void* iax_park_thread | ( | void * | stuff | ) | [static] |
Definition at line 6722 of file chan_iax2.c.
References ast_frfree, ast_hangup(), ast_log(), ast_park_call(), ast_read(), iax_dual::chan1, iax_dual::chan2, ext, f, free, and LOG_NOTICE.
Referenced by iax_park().
06723 { 06724 struct ast_channel *chan1, *chan2; 06725 struct iax_dual *d; 06726 struct ast_frame *f; 06727 int ext; 06728 int res; 06729 d = stuff; 06730 chan1 = d->chan1; 06731 chan2 = d->chan2; 06732 free(d); 06733 f = ast_read(chan1); 06734 if (f) 06735 ast_frfree(f); 06736 res = ast_park_call(chan1, chan2, 0, &ext); 06737 ast_hangup(chan2); 06738 ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext); 06739 return NULL; 06740 }
Definition at line 1418 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().
01419 { 01420 struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable); 01421 if (new) { 01422 size_t afdatalen = new->afdatalen; 01423 memcpy(new, fr, sizeof(*new)); 01424 iax_frame_wrap(new, &fr->af); 01425 new->afdatalen = afdatalen; 01426 new->data = NULL; 01427 new->datalen = 0; 01428 new->direction = DIRECTION_INGRESS; 01429 new->retrans = -1; 01430 } 01431 return new; 01432 }
| static void insert_idle_thread | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 900 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, and IAX_TYPE_DYNAMIC.
Referenced by iax2_process_thread().
00901 { 00902 if (thread->type == IAX_TYPE_DYNAMIC) { 00903 AST_LIST_LOCK(&dynamic_list); 00904 AST_LIST_INSERT_TAIL(&dynamic_list, thread, list); 00905 AST_LIST_UNLOCK(&dynamic_list); 00906 } else { 00907 AST_LIST_LOCK(&idle_list); 00908 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 00909 AST_LIST_UNLOCK(&idle_list); 00910 } 00911 00912 return; 00913 }
| static void jb_debug_output | ( | const char * | fmt, | |
| ... | ||||
| ) | [static] |
Definition at line 801 of file chan_iax2.c.
References ast_verbose().
Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().
00802 { 00803 va_list args; 00804 char buf[1024]; 00805 00806 va_start(args, fmt); 00807 vsnprintf(buf, 1024, fmt, args); 00808 va_end(args); 00809 00810 ast_verbose(buf); 00811 }
| static void jb_error_output | ( | const char * | fmt, | |
| ... | ||||
| ) | [static] |
Definition at line 777 of file chan_iax2.c.
References ast_log(), and LOG_ERROR.
Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().
00778 { 00779 va_list args; 00780 char buf[1024]; 00781 00782 va_start(args, fmt); 00783 vsnprintf(buf, 1024, fmt, args); 00784 va_end(args); 00785 00786 ast_log(LOG_ERROR, buf); 00787 }
| static void jb_warning_output | ( | const char * | fmt, | |
| ... | ||||
| ) | [static] |
Definition at line 789 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().
00790 { 00791 va_list args; 00792 char buf[1024]; 00793 00794 va_start(args, fmt); 00795 vsnprintf(buf, 1024, fmt, args); 00796 va_end(args); 00797 00798 ast_log(LOG_WARNING, buf); 00799 }
| static int load_module | ( | void | ) | [static] |
Load IAX2 module, load configuraiton ---.
Definition at line 11112 of file chan_iax2.c.
References __unload_module(), ao2_callback(), ao2_container_alloc(), ao2_ref(), ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_custom_function_register(), AST_LIST_HEAD_INIT, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, ast_mutex_init(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_register_application(), ast_register_switch(), ast_verbose(), cli_iax2, config, errno, iax2_do_register(), iax2_poke_peer_cb(), iax2_prov_app(), iax2_switch, iax2_tech, iax_debug_output(), iax_error_output(), IAX_MAX_CALLS, iax_peercallno_pvts, iax_provision_reload(), iax_set_error(), iax_set_output(), iaxpeer_function, iaxq, iaxs, iaxsl, io_context_create(), jb_error_output(), jb_setoutput(), jb_warning_output(), ast_firmware_list::lock, LOG_ERROR, LOG_WARNING, manager_iax2_show_netstats(), manager_iax2_show_peers(), MAX_PEER_BUCKETS, MAX_USER_BUCKETS, option_verbose, papp, pdescrip, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), peers, psyn, pvt_cmp_cb(), pvt_hash_cb(), reload_firmware(), sched_context_create(), set_config(), start_network_thread(), user_cmp_cb(), user_hash_cb(), users, VERBOSE_PREFIX_2, and waresl.
11113 { 11114 char *config = "iax.conf"; 11115 int res = 0; 11116 int x; 11117 struct iax2_registry *reg = NULL; 11118 11119 peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb); 11120 if (!peers) 11121 return AST_MODULE_LOAD_FAILURE; 11122 users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb); 11123 if (!users) { 11124 ao2_ref(peers, -1); 11125 return AST_MODULE_LOAD_FAILURE; 11126 } 11127 iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb); 11128 if (!iax_peercallno_pvts) { 11129 ao2_ref(peers, -1); 11130 ao2_ref(users, -1); 11131 return AST_MODULE_LOAD_FAILURE; 11132 } 11133 11134 ast_custom_function_register(&iaxpeer_function); 11135 11136 iax_set_output(iax_debug_output); 11137 iax_set_error(iax_error_output); 11138 jb_setoutput(jb_error_output, jb_warning_output, NULL); 11139 11140 #ifdef HAVE_ZAPTEL 11141 #ifdef ZT_TIMERACK 11142 timingfd = open("/dev/zap/timer", O_RDWR); 11143 if (timingfd < 0) 11144 #endif 11145 timingfd = open("/dev/zap/pseudo", O_RDWR); 11146 if (timingfd < 0) 11147 ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno)); 11148 #endif 11149 11150 memset(iaxs, 0, sizeof(iaxs)); 11151 11152 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 11153 ast_mutex_init(&iaxsl[x]); 11154 } 11155 11156 ast_cond_init(&sched_cond, NULL); 11157 11158 io = io_context_create(); 11159 sched = sched_context_create(); 11160 11161 if (!io || !sched) { 11162 ast_log(LOG_ERROR, "Out of memory\n"); 11163 return -1; 11164 } 11165 11166 netsock = ast_netsock_list_alloc(); 11167 if (!netsock) { 11168 ast_log(LOG_ERROR, "Could not allocate netsock list.\n"); 11169 return -1; 11170 } 11171 ast_netsock_init(netsock); 11172 11173 outsock = ast_netsock_list_alloc(); 11174 if (!outsock) { 11175 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 11176 return -1; 11177 } 11178 ast_netsock_init(outsock); 11179 11180 ast_mutex_init(&waresl.lock); 11181 11182 AST_LIST_HEAD_INIT(&iaxq.queue); 11183 11184 ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 11185 11186 ast_register_application(papp, iax2_prov_app, psyn, pdescrip); 11187 11188 ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" ); 11189 ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" ); 11190 11191 if(set_config(config, 0) == -1) 11192 return AST_MODULE_LOAD_DECLINE; 11193 11194 if (ast_channel_register(&iax2_tech)) { 11195 ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2"); 11196 __unload_module(); 11197 return -1; 11198 } 11199 11200 if (ast_register_switch(&iax2_switch)) 11201 ast_log(LOG_ERROR, "Unable to register IAX switch\n"); 11202 11203 res = start_network_thread(); 11204 if (!res) { 11205 if (option_verbose > 1) 11206 ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n"); 11207 } else { 11208 ast_log(LOG_ERROR, "Unable to start network thread\n"); 11209 ast_netsock_release(netsock); 11210 ast_netsock_release(outsock); 11211 } 11212 11213 AST_LIST_LOCK(®istrations); 11214 AST_LIST_TRAVERSE(®istrations, reg, entry) 11215 iax2_do_register(reg); 11216 AST_LIST_UNLOCK(®istrations); 11217 11218 ao2_callback(peers, 0, peer_set_sock_cb, NULL); 11219 ao2_callback(peers, 0, iax2_poke_peer_cb, NULL); 11220 11221 reload_firmware(0); 11222 iax_provision_reload(); 11223 return res; 11224 }
| static void lock_both | ( | unsigned short | callno0, | |
| unsigned short | callno1 | |||
| ) | [static] |
Definition at line 3482 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_trylock(), DEADLOCK_AVOIDANCE, and iaxsl.
Referenced by iax2_bridge().
03483 { 03484 ast_mutex_lock(&iaxsl[callno0]); 03485 while (ast_mutex_trylock(&iaxsl[callno1])) { 03486 DEADLOCK_AVOIDANCE(&iaxsl[callno0]); 03487 } 03488 }
| static int make_trunk | ( | unsigned short | callno, | |
| int | locked | |||
| ) | [static] |
Definition at line 1472 of file chan_iax2.c.
References ARRAY_LEN, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, chan_iax2_pvt::callno, iax2_sched_add(), iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, MIN_REUSE_TIME, option_debug, chan_iax2_pvt::pingid, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().
Referenced by iax2_request(), and socket_process().
01473 { 01474 int x; 01475 int res= 0; 01476 struct timeval now; 01477 if (iaxs[callno]->oseqno) { 01478 ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n"); 01479 return -1; 01480 } 01481 if (callno & TRUNK_CALL_START) { 01482 ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno); 01483 return -1; 01484 } 01485 gettimeofday(&now, NULL); 01486 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01487 ast_mutex_lock(&iaxsl[x]); 01488 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01489 iaxs[x] = iaxs[callno]; 01490 iaxs[x]->callno = x; 01491 iaxs[callno] = NULL; 01492 /* Update the two timers that should have been started */ 01493 AST_SCHED_DEL(sched, iaxs[x]->pingid); 01494 AST_SCHED_DEL(sched, iaxs[x]->lagid); 01495 iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 01496 iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 01497 if (locked) 01498 ast_mutex_unlock(&iaxsl[callno]); 01499 res = x; 01500 if (!locked) 01501 ast_mutex_unlock(&iaxsl[x]); 01502 break; 01503 } 01504 ast_mutex_unlock(&iaxsl[x]); 01505 } 01506 if (x >= ARRAY_LEN(iaxs) - 1) { 01507 ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n"); 01508 return -1; 01509 } 01510 if (option_debug) 01511 ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x); 01512 /* We move this call from a non-trunked to a trunked call */ 01513 update_max_trunk(); 01514 update_max_nontrunk(); 01515 return res; 01516 }
| static int manager_iax2_show_netstats | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4735 of file chan_iax2.c.
References ast_cli_netstats(), astman_append(), and RESULT_SUCCESS.
Referenced by load_module().
04736 { 04737 ast_cli_netstats(s, -1, 0); 04738 astman_append(s, "\r\n"); 04739 return RESULT_SUCCESS; 04740 }
| static int manager_iax2_show_peers | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4768 of file chan_iax2.c.
References __iax2_show_peers(), ast_strlen_zero(), astman_append(), and astman_get_header().
Referenced by load_module().
04769 { 04770 char *a[] = { "iax2", "show", "users" }; 04771 int ret; 04772 const char *id = astman_get_header(m,"ActionID"); 04773 04774 if (!ast_strlen_zero(id)) 04775 astman_append(s, "ActionID: %s\r\n",id); 04776 ret = __iax2_show_peers(1, -1, s, 3, a ); 04777 astman_append(s, "\r\n\r\n" ); 04778 return ret; 04779 } /* /JDG */
| static int match | ( | struct sockaddr_in * | sin, | |
| unsigned short | callno, | |||
| unsigned short | dcallno, | |||
| struct chan_iax2_pvt * | cur, | |||
| int | check_dcallno | |||
| ) | [static] |
Definition at line 1438 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 __find_callno(), ao2_callback(), ast_parse_device_state(), check_blacklist(), find_command(), get_sip_pvt_byid_locked(), handle_updates(), pbx_find_extension(), pvt_cmp_cb(), realtime_switch_common(), and softhangup_exec().
01439 { 01440 if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) && 01441 (cur->addr.sin_port == sin->sin_port)) { 01442 /* This is the main host */ 01443 if ( (cur->peercallno == 0 || cur->peercallno == callno) && 01444 (check_dcallno ? dcallno == cur->callno : 1) ) { 01445 /* That's us. Be sure we keep track of the peer call number */ 01446 return 1; 01447 } 01448 } 01449 if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) && 01450 (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) { 01451 /* We're transferring */ 01452 if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno)) 01453 return 1; 01454 } 01455 return 0; 01456 }
| static void memcpy_decrypt | ( | unsigned char * | dst, | |
| const unsigned char * | src, | |||
| int | len, | |||
| aes_decrypt_ctx * | dcx | |||
| ) | [static] |
Definition at line 4137 of file chan_iax2.c.
References aes_decrypt(), ast_log(), and LOG_WARNING.
Referenced by decode_frame().
04138 { 04139 #if 0 04140 /* Debug with "fake encryption" */ 04141 int x; 04142 if (len % 16) 04143 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 04144 for (x=0;x<len;x++) 04145 dst[x] = src[x] ^ 0xff; 04146 #else 04147 unsigned char lastblock[16] = { 0 }; 04148 int x; 04149 while(len > 0) { 04150 aes_decrypt(src, dst, dcx); 04151 for (x=0;x<16;x++) 04152 dst[x] ^= lastblock[x]; 04153 memcpy(lastblock, src, sizeof(lastblock)); 04154 dst += 16; 04155 src += 16; 04156 len -= 16; 04157 } 04158 #endif 04159 }
| static void memcpy_encrypt | ( | unsigned char * | dst, | |
| const unsigned char * | src, | |||
| int | len, | |||
| aes_encrypt_ctx * | ecx | |||
| ) | [static] |
Definition at line 4161 of file chan_iax2.c.
References aes_encrypt(), ast_log(), and LOG_WARNING.
Referenced by encrypt_frame().
04162 { 04163 #if 0 04164 /* Debug with "fake encryption" */ 04165 int x; 04166 if (len % 16) 04167 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 04168 for (x=0;x<len;x++) 04169 dst[x] = src[x] ^ 0xff; 04170 #else 04171 unsigned char curblock[16] = { 0 }; 04172 int x; 04173 while(len > 0) { 04174 for (x=0;x<16;x++) 04175 curblock[x] ^= src[x]; 04176 aes_encrypt(curblock, dst, ecx); 04177 memcpy(curblock, dst, sizeof(curblock)); 04178 dst += 16; 04179 src += 16; 04180 len -= 16; 04181 } 04182 #endif 04183 }
| static void merge_encryption | ( | struct chan_iax2_pvt * | p, | |
| unsigned int | enc | |||
| ) | [static] |
Definition at line 5346 of file chan_iax2.c.
References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.
Referenced by authenticate_reply(), and socket_process().
05347 { 05348 /* Select exactly one common encryption if there are any */ 05349 p->encmethods &= enc; 05350 if (p->encmethods) { 05351 if (p->encmethods & IAX_ENCRYPT_AES128) 05352 p->encmethods = IAX_ENCRYPT_AES128; 05353 else 05354 p->encmethods = 0; 05355 } 05356 }
| static void* network_thread | ( | void * | ignore | ) | [static] |
Definition at line 9085 of file chan_iax2.c.
References 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_log(), ast_mutex_trylock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, f, iax2_sched_add(), iax_frame_free(), iaxq, iaxs, iaxsl, LOG_DEBUG, option_debug, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_packet(), iax_frame::sentyet, and timing_read().
Referenced by start_network_thread().
09086 { 09087 /* Our job is simple: Send queued messages, retrying if necessary. Read frames 09088 from the network, and queue them for delivery to the channels */ 09089 int res, count, wakeup; 09090 struct iax_frame *f; 09091 09092 if (timingfd > -1) 09093 ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL); 09094 09095 for(;;) { 09096 pthread_testcancel(); 09097 09098 /* Go through the queue, sending messages which have not yet been 09099 sent, and scheduling retransmissions if appropriate */ 09100 AST_LIST_LOCK(&iaxq.queue); 09101 count = 0; 09102 wakeup = -1; 09103 AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) { 09104 if (f->sentyet) 09105 continue; 09106 09107 /* Try to lock the pvt, if we can't... don't fret - defer it till later */ 09108 if (ast_mutex_trylock(&iaxsl[f->callno])) { 09109 wakeup = 1; 09110 continue; 09111 } 09112 09113 f->sentyet++; 09114 09115 if (iaxs[f->callno]) { 09116 send_packet(f); 09117 count++; 09118 } 09119 09120 ast_mutex_unlock(&iaxsl[f->callno]); 09121 09122 if (f->retries < 0) { 09123 /* This is not supposed to be retransmitted */ 09124 AST_LIST_REMOVE_CURRENT(&iaxq.queue, list); 09125 iaxq.count--; 09126 /* Free the iax frame */ 09127 iax_frame_free(f); 09128 } else { 09129 /* We need reliable delivery. Schedule a retransmission */ 09130 f->retries++; 09131 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 09132 } 09133 } 09134 AST_LIST_TRAVERSE_SAFE_END 09135 AST_LIST_UNLOCK(&iaxq.queue); 09136 09137 pthread_testcancel(); 09138 09139 if (option_debug && count >= 20) 09140 ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count); 09141 09142 /* Now do the IO, and run scheduled tasks */ 09143 res = ast_io_wait(io, wakeup); 09144 if (res >= 0) { 09145 if (option_debug && res >= 20) 09146 ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res); 09147 } 09148 } 09149 return NULL; 09150 }
| static struct chan_iax2_pvt* new_iax | ( | struct sockaddr_in * | sin, | |
| const char * | host | |||
| ) | [static, read] |
Definition at line 1379 of file chan_iax2.c.
References ao2_alloc(), ao2_ref(), ast_string_field_init, ast_string_field_set, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, chan_iax2_pvt::bridgecallno, chan_iax2_pvt::callno, exten, chan_iax2_pvt::initid, chan_iax2_pvt::jb, jb_new(), jb_setconf(), chan_iax2_pvt::jbid, chan_iax2_pvt::lagid, jb_conf::max_contig_interp, jb_conf::max_jitterbuf, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, prefs, chan_iax2_pvt::prefs, pvt_destructor(), jb_conf::resync_threshold, and chan_iax2_pvt::transfercallno.
Referenced by __find_callno().
01380 { 01381 struct chan_iax2_pvt *tmp; 01382 jb_conf jbconf; 01383 01384 if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) { 01385 return NULL; 01386 } 01387 01388 if (ast_string_field_init(tmp, 32)) { 01389 ao2_ref(tmp, -1); 01390 tmp = NULL; 01391 return NULL; 01392 } 01393 01394 tmp->prefs = prefs; 01395 tmp->callno = 0; 01396 tmp->peercallno = 0; 01397 tmp->transfercallno = 0; 01398 tmp->bridgecallno = 0; 01399 tmp->pingid = -1; 01400 tmp->lagid = -1; 01401 tmp->autoid = -1; 01402 tmp->authid = -1; 01403 tmp->initid = -1; 01404 01405 ast_string_field_set(tmp,exten, "s"); 01406 ast_string_field_set(tmp,host, host); 01407 01408 tmp->jb = jb_new(); 01409 tmp->jbid = -1; 01410 jbconf.max_jitterbuf = maxjitterbuffer; 01411 jbconf.resync_threshold = resyncthreshold; 01412 jbconf.max_contig_interp = maxjitterinterps; 01413 jb_setconf(tmp->jb,&jbconf); 01414 01415 return tmp; 01416 }
| 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 |
The dial string format is: [username[:password]@]peer[:port][/exten[@context]][/options]
Definition at line 3200 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().
03201 { 03202 if (ast_strlen_zero(data)) 03203 return; 03204 03205 pds->peer = strsep(&data, "/"); 03206 pds->exten = strsep(&data, "/"); 03207 pds->options = data; 03208 03209 if (pds->exten) { 03210 data = pds->exten; 03211 pds->exten = strsep(&data, "@"); 03212 pds->context = data; 03213 } 03214 03215 if (strchr(pds->peer, '@')) { 03216 data = pds->peer; 03217 pds->username = strsep(&data, "@"); 03218 pds->peer = data; 03219 } 03220 03221 if (pds->username) { 03222 data = pds->username; 03223 pds->username = strsep(&data, ":"); 03224 pds->password = data; 03225 } 03226 03227 data = pds->peer; 03228 pds->peer = strsep(&data, ":"); 03229 pds->port = data; 03230 03231 /* check for a key name wrapped in [] in the secret position, if found, 03232 move it to the key field instead 03233 */ 03234 if (pds->password && (pds->password[0] == '[')) { 03235 pds->key = ast_strip_quoted(pds->password, "[", "]"); 03236 pds->password = NULL; 03237 } 03238 }
| static int peer_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1117 of file chan_iax2.c.
Referenced by load_module().
01118 { 01119 struct iax2_peer *peer = obj, *peer2 = arg; 01120 01121 return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0; 01122 }
| static int peer_delme_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 9783 of file chan_iax2.c.
References ast_set_flag, and IAX_DELME.
Referenced by delete_users().
09784 { 09785 struct iax2_peer *peer = obj; 09786 09787 ast_set_flag(peer, IAX_DELME); 09788 09789 return 0; 09790 }
| static void peer_destructor | ( | void * | obj | ) | [static] |
Definition at line 9308 of file chan_iax2.c.
References ast_dnsmgr_release(), 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(), iaxsl, and register_peer_exten().
Referenced by build_peer().
09309 { 09310 struct iax2_peer *peer = obj; 09311 09312 ast_free_ha(peer->ha); 09313 09314 if (peer->callno > 0) { 09315 ast_mutex_lock(&iaxsl[peer->callno]); 09316 iax2_destroy(peer->callno); 09317 ast_mutex_unlock(&iaxsl[peer->callno]); 09318 } 09319 09320 register_peer_exten(peer, 0); 09321 09322 if (peer->dnsmgr) 09323 ast_dnsmgr_release(peer->dnsmgr); 09324 09325 ast_string_field_free_memory(peer); 09326 }
| static int peer_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1107 of file chan_iax2.c.
References ast_str_hash().
Referenced by load_module().
01108 { 01109 const struct iax2_peer *peer = obj; 01110 01111 return ast_str_hash(peer->name); 01112 }
Definition at line 1164 of file chan_iax2.c.
References ao2_ref().
Referenced by __iax2_poke_noanswer(), iax2_poke_peer(), iax2_prune_realtime(), realtime_peer(), reg_source_db(), socket_process(), and update_registry().
01165 { 01166 ao2_ref(peer, +1); 01167 return peer; 01168 }
| static int peer_set_sock_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 11083 of file chan_iax2.c.
References iax2_peer::sockfd.
Referenced by load_module().
11084 { 11085 struct iax2_peer *peer = obj; 11086 11087 if (peer->sockfd < 0) 11088 peer->sockfd = defaultsockfd; 11089 11090 return 0; 11091 }
| 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 9235 of file chan_iax2.c.
References iax2_registry::addr, 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_DEBUG, LOG_WARNING, option_debug, socket_read(), iax2_peer::sockfd, and strsep().
Referenced by build_peer().
09236 { 09237 struct sockaddr_in sin; 09238 int nonlocal = 1; 09239 int port = IAX_DEFAULT_PORTNO; 09240 int sockfd = defaultsockfd; 09241 char *tmp; 09242 char *addr; 09243 char *portstr; 09244 09245 if (!(tmp = ast_strdupa(srcaddr))) 09246 return -1; 09247 09248 addr = strsep(&tmp, ":"); 09249 portstr = tmp; 09250 09251 if (portstr) { 09252 port = atoi(portstr); 09253 if (port < 1) 09254 port = IAX_DEFAULT_PORTNO; 09255 } 09256 09257 if (!ast_get_ip(&sin, addr)) { 09258 struct ast_netsock *sock; 09259 int res; 09260 09261 sin.sin_port = 0; 09262 sin.sin_family = AF_INET; 09263 res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin)); 09264 if (res == 0) { 09265 /* ip address valid. */ 09266 sin.sin_port = htons(port); 09267 if (!(sock = ast_netsock_find(netsock, &sin))) 09268 sock = ast_netsock_find(outsock, &sin); 09269 if (sock) { 09270 sockfd = ast_netsock_sockfd(sock); 09271 nonlocal = 0; 09272 } else { 09273 unsigned int orig_saddr = sin.sin_addr.s_addr; 09274 /* INADDR_ANY matches anyway! */ 09275 sin.sin_addr.s_addr = INADDR_ANY; 09276 if (ast_netsock_find(netsock, &sin)) { 09277 sin.sin_addr.s_addr = orig_saddr; 09278 sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL); 09279 if (sock) { 09280 sockfd = ast_netsock_sockfd(sock); 09281 ast_netsock_unref(sock); 09282 nonlocal = 0; 09283 } else { 09284 nonlocal = 2; 09285 } 09286 } 09287 } 09288 } 09289 } 09290 09291 peer->sockfd = sockfd; 09292 09293 if (nonlocal == 1) { 09294 ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n", 09295 srcaddr, peer->name); 09296 return -1; 09297 } else if (nonlocal == 2) { 09298 ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n", 09299 srcaddr, peer->name); 09300 return -1; 09301 } else { 09302 if (option_debug) 09303 ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name); 09304 return 0; 09305 } 09306 }
| static int peer_status | ( | struct iax2_peer * | peer, | |
| char * | status, | |||
| int | statuslen | |||
| ) | [static] |
peer_status: Report Peer status in character string
Definition at line 2327 of file chan_iax2.c.
References iax2_peer::lastms, and iax2_peer::maxms.
Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), function_iaxpeer(), function_sippeer(), and iax2_show_peer().
02328 { 02329 int res = 0; 02330 if (peer->maxms) { 02331 if (peer->lastms < 0) { 02332 ast_copy_string(status, "UNREACHABLE", statuslen); 02333 } else if (peer->lastms > peer->maxms) { 02334 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 02335 res = 1; 02336 } else if (peer->lastms) { 02337 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 02338 res = 1; 02339 } else { 02340 ast_copy_string(status, "UNKNOWN", statuslen); 02341 } 02342 } else { 02343 ast_copy_string(status, "Unmonitored", statuslen); 02344 res = -1; 02345 } 02346 return res; 02347 }
Definition at line 1170 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(), complete_iax2_show_peer(), create_addr(), function_iaxpeer(), iax2_devicestate(), iax2_getpeername(), iax2_getpeertrunk(), iax2_poke_noanswer(), iax2_poke_peer(), iax2_prune_realtime(), iax2_show_peer(), poke_all_peers(), prune_peers(), realtime_peer(), reg_source_db(), register_verify(), registry_authrequest(), set_config(), socket_process(), unlink_peer(), and update_registry().
01171 { 01172 ao2_ref(peer, -1); 01173 return NULL; 01174 }
| static void poke_all_peers | ( | void | ) | [static] |
Definition at line 10244 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), iax2_poke_peer(), peer_unref(), and peers.
Referenced by reload_config().
10245 { 10246 struct ao2_iterator i; 10247 struct iax2_peer *peer; 10248 10249 i = ao2_iterator_init(peers, 0); 10250 while ((peer = ao2_iterator_next(&i))) { 10251 iax2_poke_peer(peer, 0); 10252 peer_unref(peer); 10253 } 10254 }
| static void prune_peers | ( | void | ) | [static] |
Definition at line 9841 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_test_flag, IAX_DELME, peer_unref(), peers, and unlink_peer().
09842 { 09843 struct iax2_peer *peer; 09844 struct ao2_iterator i; 09845 09846 i = ao2_iterator_init(peers, 0); 09847 while ((peer = ao2_iterator_next(&i))) { 09848 if (ast_test_flag(peer, IAX_DELME)) 09849 unlink_peer(peer); 09850 peer_unref(peer); 09851 } 09852 }
| static void prune_users | ( | void | ) | [static] |
Definition at line 9827 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ao2_unlink(), ast_test_flag, IAX_DELME, user_unref(), and users.
Referenced by reload_config().
09828 { 09829 struct iax2_user *user; 09830 struct ao2_iterator i; 09831 09832 i = ao2_iterator_init(users, 0); 09833 while ((user = ao2_iterator_next(&i))) { 09834 if (ast_test_flag(user, IAX_DELME)) 09835 ao2_unlink(users, user); 09836 user_unref(user); 09837 } 09838 }
| static int pvt_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 11100 of file chan_iax2.c.
References chan_iax2_pvt::frames_received, and match().
Referenced by load_module().
11101 { 11102 struct chan_iax2_pvt *pvt = obj, *pvt2 = arg; 11103 11104 /* The frames_received field is used to hold whether we're matching 11105 * against a full frame or not ... */ 11106 11107 return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 11108 pvt2->frames_received) ? CMP_MATCH : 0; 11109 }
| static void pvt_destructor | ( | void * | obj | ) | [static] |
Definition at line 1340 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_set_flag, ast_string_field_free_memory, ast_variables_destroy(), iax2_registry::callno, chan_iax2_pvt::callno, iax_frame::callno, jb_frame::data, iax2_destroy_helper(), iax2_frame_free(), IAX_ALREADYGONE, iaxq, chan_iax2_pvt::jb, jb_destroy(), jb_getall(), JB_OK, chan_iax2_pvt::owner, chan_iax2_pvt::reg, iax_frame::retries, and chan_iax2_pvt::vars.
Referenced by new_iax().
01341 { 01342 struct chan_iax2_pvt *pvt = obj; 01343 struct iax_frame *cur = NULL; 01344 01345 iax2_destroy_helper(pvt); 01346 01347 /* Already gone */ 01348 ast_set_flag(pvt, IAX_ALREADYGONE); 01349 01350 AST_LIST_LOCK(&iaxq.queue); 01351 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 01352 /* Cancel any pending transmissions */ 01353 if (cur->callno == pvt->callno) { 01354 cur->retries = -1; 01355 } 01356 } 01357 AST_LIST_UNLOCK(&iaxq.queue); 01358 01359 if (pvt->reg) { 01360 pvt->reg->callno = 0; 01361 } 01362 01363 if (!pvt->owner) { 01364 jb_frame frame; 01365 if (pvt->vars) { 01366 ast_variables_destroy(pvt->vars); 01367 pvt->vars = NULL; 01368 } 01369 01370 while (jb_getall(pvt->jb, &frame) == JB_OK) { 01371 iax2_frame_free(frame.data); 01372 } 01373 01374 jb_destroy(pvt->jb); 01375 ast_string_field_free_memory(pvt); 01376 } 01377 }
| static int pvt_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 11093 of file chan_iax2.c.
References chan_iax2_pvt::peercallno.
Referenced by load_module().
11094 { 11095 const struct chan_iax2_pvt *pvt = obj; 11096 11097 return pvt->peercallno; 11098 }
| static int raw_hangup | ( | struct sockaddr_in * | sin, | |
| unsigned short | src, | |||
| unsigned short | dst, | |||
| int | sockfd | |||
| ) | [static] |
Definition at line 5328 of file chan_iax2.c.
References AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), compress_subclass(), ast_iax2_full_hdr::csub, ast_iax2_full_hdr::dcallno, IAX_COMMAND_INVAL, IAX_FLAG_FULL, iax_showframe(), ast_iax2_full_hdr::iseqno, LOG_DEBUG, 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().
05329 { 05330 struct ast_iax2_full_hdr fh; 05331 fh.scallno = htons(src | IAX_FLAG_FULL); 05332 fh.dcallno = htons(dst); 05333 fh.ts = 0; 05334 fh.oseqno = 0; 05335 fh.iseqno = 0; 05336 fh.type = AST_FRAME_IAX; 05337 fh.csub = compress_subclass(IAX_COMMAND_INVAL); 05338 if (iaxdebug) 05339 iax_showframe(NULL, &fh, 0, sin, 0); 05340 if (option_debug) 05341 ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n", 05342 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst); 05343 return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin)); 05344 }
| static struct iax2_peer * realtime_peer | ( | const char * | peername, | |
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 2802 of file chan_iax2.c.
References iax2_peer::addr, ast_copy_flags, ast_get_time_t(), ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_log(), 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, LOG_DEBUG, ast_variable::name, ast_variable::next, option_debug, peer_ref(), peer_unref(), peers, realtime_update_peer(), reg_source_db(), ast_variable::value, and var.
02803 { 02804 struct ast_variable *var = NULL; 02805 struct ast_variable *tmp; 02806 struct iax2_peer *peer=NULL; 02807 time_t regseconds = 0, nowtime; 02808 int dynamic=0; 02809 02810 if (peername) { 02811 var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", NULL); 02812 if (!var && sin) 02813 var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), NULL); 02814 } else if (sin) { 02815 char porta[25]; 02816 sprintf(porta, "%d", ntohs(sin->sin_port)); 02817 var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 02818 if (var) { 02819 /* We'll need the peer name in order to build the structure! */ 02820 for (tmp = var; tmp; tmp = tmp->next) { 02821 if (!strcasecmp(tmp->name, "name")) 02822 peername = tmp->value; 02823 } 02824 } 02825 } 02826 if (!var && peername) { /* Last ditch effort */ 02827 var = ast_load_realtime("iaxpeers", "name", peername, NULL); 02828 /*!\note 02829 * If this one loaded something, then we need to ensure that the host 02830 * field matched. The only reason why we can't have this as a criteria 02831 * is because we only have the IP address and the host field might be 02832 * set as a name (and the reverse PTR might not match). 02833 */ 02834 if (var && sin) { 02835 for (tmp = var; tmp; tmp = tmp->next) { 02836 if (!strcasecmp(tmp->name, "host")) { 02837 struct ast_hostent ahp; 02838 struct hostent *hp; 02839 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 02840 /* No match */ 02841 ast_variables_destroy(var); 02842 var = NULL; 02843 } 02844 break; 02845 } 02846 } 02847 } 02848 } 02849 if (!var) 02850 return NULL; 02851 02852 peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1); 02853 02854 if (!peer) { 02855 ast_variables_destroy(var); 02856 return NULL; 02857 } 02858 02859 for (tmp = var; tmp; tmp = tmp->next) { 02860 /* Make sure it's not a user only... */ 02861 if (!strcasecmp(tmp->name, "type")) { 02862 if (strcasecmp(tmp->value, "friend") && 02863 strcasecmp(tmp->value, "peer")) { 02864 /* Whoops, we weren't supposed to exist! */ 02865 peer = peer_unref(peer); 02866 break; 02867 } 02868 } else if (!strcasecmp(tmp->name, "regseconds")) { 02869 ast_get_time_t(tmp->value, ®seconds, 0, NULL); 02870 } else if (!strcasecmp(tmp->name, "ipaddr")) { 02871 inet_aton(tmp->value, &(peer->addr.sin_addr)); 02872 } else if (!strcasecmp(tmp->name, "port")) { 02873 peer->addr.sin_port = htons(atoi(tmp->value)); 02874 } else if (!strcasecmp(tmp->name, "host")) { 02875 if (!strcasecmp(tmp->value, "dynamic")) 02876 dynamic = 1; 02877 } 02878 } 02879 02880 ast_variables_destroy(var); 02881 02882 if (!peer) 02883 return NULL; 02884 02885 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 02886 ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS); 02887 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) { 02888 if (peer->expire > -1) { 02889 if (!ast_sched_del(sched, peer->expire)) { 02890 peer->expire = -1; 02891 peer_unref(peer); 02892 } 02893 } 02894 peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer)); 02895 if (peer->expire == -1) 02896 peer_unref(peer); 02897 } 02898 ao2_link(peers, peer); 02899 if (ast_test_flag(peer, IAX_DYNAMIC)) 02900 reg_source_db(peer); 02901 } else { 02902 ast_set_flag(peer, IAX_TEMPONLY); 02903 } 02904 02905 if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) { 02906 time(&nowtime); 02907 if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) { 02908 memset(&peer->addr, 0, sizeof(peer->addr)); 02909 realtime_update_peer(peer->name, &peer->addr, 0); 02910 if (option_debug) 02911 ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n", 02912 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 02913 } 02914 else { 02915 if (option_debug) 02916 ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n", 02917 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 02918 } 02919 } 02920 02921 return peer; 02922 }
| static void realtime_update_peer | ( | const char * | peername, | |
| struct sockaddr_in * | sin, | |||
| time_t | regtime | |||
| ) | [static] |
Definition at line 2995 of file chan_iax2.c.
References ast_inet_ntoa(), and ast_update_realtime().
Referenced by __expire_registry(), realtime_peer(), update_peer(), and update_registry().
02996 { 02997 char port[10]; 02998 char regseconds[20]; 02999 03000 snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime); 03001 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 03002 ast_update_realtime("iaxpeers", "name", peername, 03003 "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 03004 "regseconds", regseconds, NULL); 03005 }
| static struct iax2_user* realtime_user | ( | const char * | username, | |
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 2924 of file chan_iax2.c.
References 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, users, ast_variable::value, and var.
02925 { 02926 struct ast_variable *var; 02927 struct ast_variable *tmp; 02928 struct iax2_user *user=NULL; 02929 02930 var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL); 02931 if (!var) 02932 var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), NULL); 02933 if (!var && sin) { 02934 char porta[6]; 02935 snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port)); 02936 var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 02937 if (!var) 02938 var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 02939 } 02940 if (!var) { /* Last ditch effort */ 02941 var = ast_load_realtime("iaxusers", "name", username, NULL); 02942 /*!\note 02943 * If this one loaded something, then we need to ensure that the host 02944 * field matched. The only reason why we can't have this as a criteria 02945 * is because we only have the IP address and the host field might be 02946 * set as a name (and the reverse PTR might not match). 02947 */ 02948 if (var) { 02949 for (tmp = var; tmp; tmp = tmp->next) { 02950 if (!strcasecmp(tmp->name, "host")) { 02951 struct ast_hostent ahp; 02952 struct hostent *hp; 02953 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 02954 /* No match */ 02955 ast_variables_destroy(var); 02956 var = NULL; 02957 } 02958 break; 02959 } 02960 } 02961 } 02962 } 02963 if (!var) 02964 return NULL; 02965 02966 tmp = var; 02967 while(tmp) { 02968 /* Make sure it's not a peer only... */ 02969 if (!strcasecmp(tmp->name, "type")) { 02970 if (strcasecmp(tmp->value, "friend") && 02971 strcasecmp(tmp->value, "user")) { 02972 return NULL; 02973 } 02974 } 02975 tmp = tmp->next; 02976 } 02977 02978 user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)); 02979 02980 ast_variables_destroy(var); 02981 02982 if (!user) 02983 return NULL; 02984 02985 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 02986 ast_set_flag(user, IAX_RTCACHEFRIENDS); 02987 ao2_link(users, user); 02988 } else { 02989 ast_set_flag(user, IAX_TEMPONLY); 02990 } 02991 02992 return user; 02993 }
| static void reg_source_db | ( | struct iax2_peer * | p | ) | [static] |
Definition at line 6110 of file chan_iax2.c.
References iax2_peer::addr, ast_db_get(), ast_device_state_changed(), ast_inet_ntoa(), ast_sched_del(), ast_test_flag, ast_verbose(), iax2_peer::expire, expire_registry(), iax2_peer::expiry, iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), IAX_TEMPONLY, option_verbose, peer_ref(), peer_unref(), register_peer_exten(), and VERBOSE_PREFIX_3.
Referenced by build_peer(), realtime_peer(), set_config(), and temp_peer().
06111 { 06112 char data[80]; 06113 struct in_addr in; 06114 char *c, *d; 06115 if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) { 06116 c = strchr(data, ':'); 06117 if (c) { 06118 *c = '\0'; 06119 c++; 06120 if (inet_aton(data, &in)) { 06121 d = strchr(c, ':'); 06122 if (d) { 06123 *d = '\0'; 06124 d++; 06125 if (option_verbose > 2) 06126 ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 06127 ast_inet_ntoa(in), atoi(c), atoi(d)); 06128 iax2_poke_peer(p, 0); 06129 p->expiry = atoi(d); 06130 memset(&p->addr, 0, sizeof(p->addr)); 06131 p->addr.sin_family = AF_INET; 06132 p->addr.sin_addr = in; 06133 p->addr.sin_port = htons(atoi(c)); 06134 if (p->expire > -1) { 06135 if (!ast_sched_del(sched, p->expire)) { 06136 p->expire = -1; 06137 peer_unref(p); 06138 } 06139 } 06140 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 06141 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 06142 if (p->expire == -1) 06143 peer_unref(p); 06144 if (iax2_regfunk) 06145 iax2_regfunk(p->name, 1); 06146 register_peer_exten(p, 1); 06147 } 06148 06149 } 06150 } 06151 } 06152 }
| static void register_peer_exten | ( | struct iax2_peer * | peer, | |
| int | onoff | |||
| ) | [static] |
Definition at line 6030 of file chan_iax2.c.
References ast_add_extension(), ast_context_remove_extension(), ast_exists_extension(), ast_free, ast_strdup, ast_strlen_zero(), ext, S_OR, and strsep().
Referenced by __expire_registry(), expire_register(), parse_register_contact(), peer_destructor(), reg_source_db(), sip_destroy_peer(), and update_registry().
06031 { 06032 char multi[256]; 06033 char *stringp, *ext; 06034 if (!ast_strlen_zero(regcontext)) { 06035 ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); 06036 stringp = multi; 06037 while((ext = strsep(&stringp, "&"))) { 06038 if (onoff) { 06039 if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL)) 06040 ast_add_extension(regcontext, 1, ext, 1, NULL, NULL, 06041 "Noop", ast_strdup(peer->name), ast_free, "IAX2"); 06042 } else 06043 ast_context_remove_extension(regcontext, ext, 1, NULL); 06044 } 06045 } 06046 }
| static int register_verify | ( | int | callno, | |
| struct sockaddr_in * | sin, | |||
| struct iax_ies * | ies | |||
| ) | [static] |
Verify inbound registration.
Definition at line 5492 of file chan_iax2.c.
References iax2_peer::addr, ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_device_state_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, iax2_registry::expire, chan_iax2_pvt::expiry, expiry, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, IAX_STATE_UNCHANGED, iaxs, iaxsl, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, peer_unref(), iax_ies::refresh, iax_ies::rsa_result, iax2_registry::secret, strsep(), and iax_ies::username.
Referenced by handle_request_register(), and socket_process().
05493 { 05494 char requeststr[256] = ""; 05495 char peer[256] = ""; 05496 char md5secret[256] = ""; 05497 char rsasecret[256] = ""; 05498 char secret[256] = ""; 05499 struct iax2_peer *p = NULL; 05500 struct ast_key *key; 05501 char *keyn; 05502 int x; 05503 int expire = 0; 05504 int res = -1; 05505 05506 ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED); 05507 /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */ 05508 if (ies->username) 05509 ast_copy_string(peer, ies->username, sizeof(peer)); 05510 if (ies->password) 05511 ast_copy_string(secret, ies->password, sizeof(secret)); 05512 if (ies->md5_result) 05513 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 05514 if (ies->rsa_result) 05515 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 05516 if (ies->refresh) 05517 expire = ies->refresh; 05518 05519 if (ast_strlen_zero(peer)) { 05520 ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr)); 05521 return -1; 05522 } 05523 05524 /* SLD: first call to lookup peer during registration */ 05525 ast_mutex_unlock(&iaxsl[callno]); 05526 p = find_peer(peer, 1); 05527 ast_mutex_lock(&iaxsl[callno]); 05528 if (!p || !iaxs[callno]) { 05529 if (authdebug && !p) 05530 ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 05531 goto return_unref; 05532 } 05533 05534 if (!ast_test_flag(p, IAX_DYNAMIC)) { 05535 if (authdebug) 05536 ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 05537 goto return_unref; 05538 } 05539 05540 if (!ast_apply_ha(p->ha, sin)) { 05541 if (authdebug) 05542 ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 05543 goto return_unref; 05544 } 05545 if (!inaddrcmp(&p->addr, sin)) 05546 ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED); 05547 ast_string_field_set(iaxs[callno], secret, p->secret); 05548 ast_string_field_set(iaxs[callno], inkeys, p->inkeys); 05549 /* Check secret against what we have on file */ 05550 if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) { 05551 if (!ast_strlen_zero(p->inkeys)) { 05552 char tmpkeys[256]; 05553 char *stringp=NULL; 05554 ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys)); 05555 stringp=tmpkeys; 05556 keyn = strsep(&stringp, ":"); 05557 while(keyn) { 05558 key = ast_key_get(keyn, AST_KEY_PUBLIC); 05559 if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) { 05560 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05561 break; 05562 } else if (!key) 05563 ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn); 05564 keyn = strsep(&stringp, ":"); 05565 } 05566 if (!keyn) { 05567 if (authdebug) 05568 ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys); 05569 goto return_unref; 05570 } 05571 } else { 05572 if (authdebug) 05573 ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer); 05574 goto return_unref; 05575 } 05576 } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) { 05577 struct MD5Context md5; 05578 unsigned char digest[16]; 05579 char *tmppw, *stringp; 05580 05581 tmppw = ast_strdupa(p->secret); 05582 stringp = tmppw; 05583 while((tmppw = strsep(&stringp, ";"))) { 05584 MD5Init(&md5); 05585 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 05586 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 05587 MD5Final(digest, &md5); 05588 for (x=0;x<16;x++) 05589 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 05590 if (!strcasecmp(requeststr, md5secret)) 05591 break; 05592 } 05593 if (tmppw) { 05594 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05595 } else { 05596 if (authdebug) 05597 ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret); 05598 goto return_unref; 05599 } 05600 } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) { 05601 /* They've provided a plain text password and we support that */ 05602 if (strcmp(secret, p->secret)) { 05603 if (authdebug) 05604 ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 05605 goto return_unref; 05606 } else 05607 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05608 } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) { 05609 if (authdebug) 05610 ast_log(LOG_NOTICE, "Inappropriate authentication received\n"); 05611 goto return_unref; 05612 } 05613 ast_string_field_set(iaxs[callno], peer, peer); 05614 /* Choose lowest expiry number */ 05615 if (expire && (expire < iaxs[callno]->expiry)) 05616 iaxs[callno]->expiry = expire; 05617 05618 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 05619 05620 res = 0; 05621 05622 return_unref: 05623 if (p) 05624 peer_unref(p); 05625 05626 return res; 05627 }
| static int registry_authrequest | ( | int | callno | ) | [static] |
Definition at line 6289 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_strdupa, ast_string_field_set, iax2_peer::authmethods, iax_ie_data::buf, find_peer(), IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_REGAUTH, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CHALLENGE, IAX_IE_USERNAME, iaxs, iaxsl, LOG_WARNING, peer_unref(), iax_ie_data::pos, and send_command().
Referenced by socket_process().
06290 { 06291 struct iax_ie_data ied; 06292 struct iax2_peer *p; 06293 char challenge[10]; 06294 const char *peer_name; 06295 int res = -1; 06296 06297 peer_name = ast_strdupa(iaxs[callno]->peer); 06298 06299 /* SLD: third call to find_peer in registration */ 06300 ast_mutex_unlock(&iaxsl[callno]); 06301 p = find_peer(peer_name, 1); 06302 ast_mutex_lock(&iaxsl[callno]); 06303 if (!iaxs[callno]) 06304 goto return_unref; 06305 if (!p) { 06306 ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name); 06307 goto return_unref; 06308 } 06309 06310 memset(&ied, 0, sizeof(ied)); 06311 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 06312 if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) { 06313 /* Build the challenge */ 06314 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 06315 ast_string_field_set(iaxs[callno], challenge, challenge); 06316 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge); 06317 } 06318 iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name); 06319 06320 res = 0; 06321 06322 return_unref: 06323 peer_unref(p); 06324 06325 return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);; 06326 }
| static int registry_rerequest | ( | struct iax_ies * | ies, | |
| int | callno, | |||
| struct sockaddr_in * | sin | |||
| ) | [static] |
Definition at line 6328 of file chan_iax2.c.
References iax2_registry::addr, 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, iaxs, 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().
06329 { 06330 struct iax2_registry *reg; 06331 /* Start pessimistic */ 06332 struct iax_ie_data ied; 06333 char peer[256] = ""; 06334 char challenge[256] = ""; 06335 int res; 06336 int authmethods = 0; 06337 if (ies->authmethods) 06338 authmethods = ies->authmethods; 06339 if (ies->username) 06340 ast_copy_string(peer, ies->username, sizeof(peer)); 06341 if (ies->challenge) 06342 ast_copy_string(challenge, ies->challenge, sizeof(challenge)); 06343 memset(&ied, 0, sizeof(ied)); 06344 reg = iaxs[callno]->reg; 06345 if (reg) { 06346 if (inaddrcmp(®->addr, sin)) { 06347 ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 06348 return -1; 06349 } 06350 if (ast_strlen_zero(reg->secret)) { 06351 ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username); 06352 reg->regstate = REG_STATE_NOAUTH; 06353 return -1; 06354 } 06355 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 06356 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 06357 if (reg->secret[0] == '[') { 06358 char tmpkey[256]; 06359 ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey)); 06360 tmpkey[strlen(tmpkey) - 1] = '\0'; 06361 res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL); 06362 } else 06363 res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL); 06364 if (!res) { 06365 reg->regstate = REG_STATE_AUTHSENT; 06366 return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 06367 } else 06368 return -1; 06369 ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer); 06370 } else 06371 ast_log(LOG_NOTICE, "Can't reregister without a reg\n"); 06372 return -1; 06373 }
| static char* regstate2str | ( | int | regstate | ) | [static] |
Definition at line 4781 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_response_register(), iax2_show_registry(), sip_reg_timeout(), and sip_show_registry().
04782 { 04783 switch(regstate) { 04784 case REG_STATE_UNREGISTERED: 04785 return "Unregistered"; 04786 case REG_STATE_REGSENT: 04787 return "Request Sent"; 04788 case REG_STATE_AUTHSENT: 04789 return "Auth. Sent"; 04790 case REG_STATE_REGISTERED: 04791 return "Registered"; 04792 case REG_STATE_REJECTED: 04793 return "Rejected"; 04794 case REG_STATE_TIMEOUT: 04795 return "Timeout"; 04796 case REG_STATE_NOAUTH: 04797 return "No Authentication"; 04798 default: 04799 return "Unknown"; 04800 } 04801 }
| static int reload | ( | void | ) | [static] |
Definition at line 10281 of file chan_iax2.c.
References reload_config().
10282 { 10283 return reload_config(); 10284 }
| static int reload_config | ( | void | ) | [static] |
Definition at line 10255 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, config, iax2_do_register(), iax_provision_reload(), poke_all_peers(), prune_peers(), prune_users(), reload_firmware(), and set_config().
10256 { 10257 char *config = "iax.conf"; 10258 struct iax2_registry *reg; 10259 10260 if (set_config(config, 1) > 0) { 10261 prune_peers(); 10262 prune_users(); 10263 AST_LIST_LOCK(®istrations); 10264 AST_LIST_TRAVERSE(®istrations, reg, entry) 10265 iax2_do_register(reg); 10266 AST_LIST_UNLOCK(®istrations); 10267 /* Qualify hosts, too */ 10268 poke_all_peers(); 10269 } 10270 reload_firmware(0); 10271 iax_provision_reload(); 10272 10273 return 0; 10274 }
| static void reload_firmware | ( | int | unload | ) | [static] |
Definition at line 1960 of file chan_iax2.c.
References ast_config_AST_DATA_DIR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), iax_firmware::dead, destroy_firmware(), errno, ast_firmware_list::lock, LOG_WARNING, iax_firmware::next, option_verbose, try_firmware(), VERBOSE_PREFIX_2, ast_firmware_list::wares, and waresl.
Referenced by __unload_module(), load_module(), and reload_config().
01961 { 01962 struct iax_firmware *cur, *curl, *curp; 01963 DIR *fwd; 01964 struct dirent *de; 01965 char dir[256]; 01966 char fn[256]; 01967 /* Mark all as dead */ 01968 ast_mutex_lock(&waresl.lock); 01969 cur = waresl.wares; 01970 while(cur) { 01971 cur->dead = 1; 01972 cur = cur->next; 01973 } 01974 01975 /* Now that we've freed them, load the new ones */ 01976 if (!unload) { 01977 snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR); 01978 fwd = opendir(dir); 01979 if (fwd) { 01980 while((de = readdir(fwd))) { 01981 if (de->d_name[0] != '.') { 01982 snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name); 01983 if (!try_firmware(fn)) { 01984 if (option_verbose > 1) 01985 ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name); 01986 } 01987 } 01988 } 01989 closedir(fwd); 01990 } else 01991 ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno)); 01992 } 01993 01994 /* Clean up leftovers */ 01995 cur = waresl.wares; 01996 curp = NULL; 01997 while(cur) { 01998 curl = cur; 01999 cur = cur->next; 02000 if (curl->dead) { 02001 if (curp) { 02002 curp->next = cur; 02003 } else { 02004 waresl.wares = cur; 02005 } 02006 destroy_firmware(curl); 02007 } else { 02008 curp = cur; 02009 } 02010 } 02011 ast_mutex_unlock(&waresl.lock); 02012 }
| static void remove_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1255 of file chan_iax2.c.
References ao2_unlink(), ast_log(), iax_peercallno_pvts, LOG_ERROR, and chan_iax2_pvt::peercallno.
Referenced by complete_transfer(), iax2_destroy(), and socket_process().
01256 { 01257 if (!pvt->peercallno) { 01258 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01259 return; 01260 } 01261 01262 ao2_unlink(iax_peercallno_pvts, pvt); 01263 }
Definition at line 6832 of file chan_iax2.c.
References iax_frame::callno, iax_rr::delay, iax_rr::dropped, iaxs, 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().
06833 { 06834 iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter; 06835 iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24; 06836 iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff; 06837 iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts; 06838 iaxs[fr->callno]->remote_rr.delay = ies->rr_delay; 06839 iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped; 06840 iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo; 06841 }
| static void* sched_thread | ( | void * | ignore | ) | [static] |
Definition at line 9057 of file chan_iax2.c.
References ast_cond_timedwait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), LOG_DEBUG, and option_debug.
Referenced by start_network_thread().
09058 { 09059 int count; 09060 int res; 09061 struct timeval tv; 09062 struct timespec ts; 09063 09064 for (;;) { 09065 res = ast_sched_wait(sched); 09066 if ((res > 1000) || (res < 0)) 09067 res = 1000; 09068 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000)); 09069 ts.tv_sec = tv.tv_sec; 09070 ts.tv_nsec = tv.tv_usec * 1000; 09071 09072 pthread_testcancel(); 09073 ast_mutex_lock(&sched_lock); 09074 ast_cond_timedwait(&sched_cond, &sched_lock, &ts); 09075 ast_mutex_unlock(&sched_lock); 09076 pthread_testcancel(); 09077 09078 count = ast_sched_runq(sched); 09079 if (option_debug && count >= 20) 09080 ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count); 09081 } 09082 return NULL; 09083 }
| static int schedule_delivery | ( | struct iax_frame * | fr, | |
| int | updatehistory, | |||
| int | fromtrunk, | |||
| unsigned int * | tsout | |||
| ) | [static] |
IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] was valid before calling it, it may no longer be valid after calling it.
Definition at line 2655 of file chan_iax2.c.
References __do_deliver(), iax_frame::af, ast_bridged_channel(), AST_CHAN_TP_WANTSJITTER, ast_codec_get_samples(), AST_FRAME_CNG, AST_FRAME_VOICE, ast_log(), AST_SCHED_DEL, ast_test_flag, ast_tvadd(), calc_rxstamp(), iax_frame::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), IAX_FORCEJITTERBUF, IAX_USEJITTERBUF, iaxs, 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, len, LOG_DEBUG, option_debug, chan_iax2_pvt::owner, ast_channel_tech::properties, chan_iax2_pvt::rxcore, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().
Referenced by socket_process().
02656 { 02657 int type, len; 02658 int ret; 02659 int needfree = 0; 02660 struct ast_channel *owner = NULL; 02661 struct ast_channel *bridge = NULL; 02662 02663 /* Attempt to recover wrapped timestamps */ 02664 unwrap_timestamp(fr); 02665 02666 /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */ 02667 if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore)) 02668 fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000)); 02669 else { 02670 #if 0 02671 if (option_debug) 02672 ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n"); 02673 #endif 02674 fr->af.delivery = ast_tv(0,0); 02675 } 02676 02677 type = JB_TYPE_CONTROL; 02678 len = 0; 02679 02680 if(fr->af.frametype == AST_FRAME_VOICE) { 02681 type = JB_TYPE_VOICE; 02682 len = ast_codec_get_samples(&fr->af) / 8; 02683 } else if(fr->af.frametype == AST_FRAME_CNG) { 02684 type = JB_TYPE_SILENCE; 02685 } 02686 02687 if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) { 02688 if (tsout) 02689 *tsout = fr->ts; 02690 __do_deliver(fr); 02691 return -1; 02692 } 02693 02694 if ((owner = iaxs[fr->callno]->owner)) 02695 bridge = ast_bridged_channel(owner); 02696 02697 /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to 02698 * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */ 02699 if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) { 02700 jb_frame frame; 02701 02702 /* deliver any frames in the jb */ 02703 while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) { 02704 __do_deliver(frame.data); 02705 /* __do_deliver() can make the call disappear */ 02706 if (!iaxs[fr->callno]) 02707 return -1; 02708 } 02709 02710 jb_reset(iaxs[fr->callno]->jb); 02711 02712 AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid); 02713 02714 /* deliver this frame now */ 02715 if (tsout) 02716 *tsout = fr->ts; 02717 __do_deliver(fr); 02718 return -1; 02719 } 02720 02721 /* insert into jitterbuffer */ 02722 /* TODO: Perhaps we could act immediately if it's not droppable and late */ 02723 ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts, 02724 calc_rxstamp(iaxs[fr->callno],fr->ts)); 02725 if (ret == JB_DROP) { 02726 needfree++; 02727 } else if (ret == JB_SCHED) { 02728 update_jbsched(iaxs[fr->callno]); 02729 } 02730 if (tsout) 02731 *tsout = fr->ts; 02732 if (needfree) { 02733 /* Free our iax frame */ 02734 iax2_frame_free(fr); 02735 return -1; 02736 } 02737 return 0; 02738 }
| static int send_apathetic_reply | ( | unsigned short | callno, | |
| unsigned short | dcallno, | |||
| struct sockaddr_in * | sin, | |||
| int | command, | |||
| int | ts, | |||
| unsigned char | seqno | |||
| ) | [static] |
Definition at line 3173 of file chan_iax2.c.
References AST_FRAME_IAX, compress_subclass(), and ast_iax2_full_hdr::scallno.
Referenced by socket_process().
03174 { 03175 struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno), 03176 .ts = htonl(ts), .iseqno = seqno, .oseqno = seqno, .type = AST_FRAME_IAX, 03177 .csub = compress_subclass(command) }; 03178 03179 return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin)); 03180 }
| 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 5065 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_poke_peer(), iax2_provision(), iax2_start_transfer(), registry_authrequest(), registry_rerequest(), send_command_locked(), and socket_process().
05066 { 05067 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0); 05068 }
| 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 5084 of file chan_iax2.c.
References __send_command(), chan_iax2_pvt::callno, iax2_predestroy(), and iaxs.
Referenced by __auth_reject(), __auto_hangup(), authenticate_request(), iax2_hangup(), socket_process(), and update_registry().
05085 { 05086 int call_num = i->callno; 05087 /* It is assumed that the callno has already been locked */ 05088 iax2_predestroy(i->callno); 05089 if (!iaxs[call_num]) 05090 return -1; 05091 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1); 05092 }
| 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 5094 of file chan_iax2.c.
References __send_command().
Referenced by iax2_vnak(), and socket_process().
05095 { 05096 return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0); 05097 }
| 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 5070 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), iaxs, iaxsl, and send_command().
Referenced by iax2_answer(), iax2_digit_begin(), iax2_digit_end(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), and iax2_transfer().
05071 { 05072 int res; 05073 ast_mutex_lock(&iaxsl[callno]); 05074 res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno); 05075 ast_mutex_unlock(&iaxsl[callno]); 05076 return res; 05077 }
| 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 5099 of file chan_iax2.c.
References __send_command().
Referenced by socket_process(), and try_transfer().
05100 { 05101 return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0); 05102 }
| static int send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1061 of file chan_iax2.c.
References __send_lagrq(), and schedule_action.
Referenced by __find_callno(), __send_lagrq(), and make_trunk().
01062 { 01063 #ifdef SCHED_MULTITHREADED 01064 if (schedule_action(__send_lagrq, data)) 01065 #endif 01066 __send_lagrq(data); 01067 return 0; 01068 }
| static int send_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 2085 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax2_registry::addr, ast_inet_ntoa(), ast_log(), iax_frame::callno, iax2_registry::callno, iax_frame::data, iax_frame::datalen, errno, error(), handle_error(), iax_showframe(), iaxs, LOG_DEBUG, option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, transfer, iax_frame::transfer, and iax_frame::ts.
Referenced by __attempt_transmit(), iax2_send(), network_thread(), and vnak_retransmit().
02086 { 02087 int res; 02088 int callno = f->callno; 02089 02090 /* Don't send if there was an error, but return error instead */ 02091 if (!callno || !iaxs[callno] || iaxs[callno]->error) 02092 return -1; 02093 02094 /* Called with iaxsl held */ 02095 if (option_debug > 2 && iaxdebug) 02096 ast_log(LOG_DEBUG, "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)); 02097 if (f->transfer) { 02098 if (iaxdebug) 02099 iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr)); 02100 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer, 02101 sizeof(iaxs[callno]->transfer)); 02102 } else { 02103 if (iaxdebug) 02104 iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr)); 02105 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr, 02106 sizeof(iaxs[callno]->addr)); 02107 } 02108 if (res < 0) { 02109 if (option_debug && iaxdebug) 02110 ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno)); 02111 handle_error(); 02112 } else 02113 res = 0; 02114 return res; 02115 }
| static int send_ping | ( | const void * | data | ) | [static] |
Definition at line 1021 of file chan_iax2.c.
References __send_ping(), and schedule_action.
Referenced by __find_callno(), __send_ping(), and make_trunk().
01022 { 01023 #ifdef SCHED_MULTITHREADED 01024 if (schedule_action(__send_ping, data)) 01025 #endif 01026 __send_ping(data); 01027 return 0; 01028 }
| static int send_trunk | ( | struct iax2_trunk_peer * | tpeer, | |
| struct timeval * | now | |||
| ) | [static] |
Definition at line 6510 of file chan_iax2.c.
References iax2_trunk_peer::addr, iax_frame::afdata, ast_inet_ntoa(), ast_log(), 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, LOG_DEBUG, ast_iax2_meta_hdr::metacmd, option_debug, 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 timing_read().
06511 { 06512 int res = 0; 06513 struct iax_frame *fr; 06514 struct ast_iax2_meta_hdr *meta; 06515 struct ast_iax2_meta_trunk_hdr *mth; 06516 int calls = 0; 06517 06518 /* Point to frame */ 06519 fr = (struct iax_frame *)tpeer->trunkdata; 06520 /* Point to meta data */ 06521 meta = (struct ast_iax2_meta_hdr *)fr->afdata; 06522 mth = (struct ast_iax2_meta_trunk_hdr *)meta->data; 06523 if (tpeer->trunkdatalen) { 06524 /* We're actually sending a frame, so fill the meta trunk header and meta header */ 06525 meta->zeros = 0; 06526 meta->metacmd = IAX_META_TRUNK; 06527 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) 06528 meta->cmddata = IAX_META_TRUNK_MINI; 06529 else 06530 meta->cmddata = IAX_META_TRUNK_SUPERMINI; 06531 mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now)); 06532 /* And the rest of the ast_iax2 header */ 06533 fr->direction = DIRECTION_OUTGRESS; 06534 fr->retrans = -1; 06535 fr->transfer = 0; 06536 /* Any appropriate call will do */ 06537 fr->data = fr->afdata; 06538 fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr); 06539 res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd); 06540 calls = tpeer->calls; 06541 #if 0 06542 if (option_debug) 06543 ast_log(LOG_DEBUG, "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)); 06544 #endif 06545 /* Reset transmit trunk side data */ 06546 tpeer->trunkdatalen = 0; 06547 tpeer->calls = 0; 06548 } 06549 if (res < 0) 06550 return res; 06551 return calls; 06552 }
| static int set_config | ( | char * | config_file, | |
| int | reload | |||
| ) | [static] |
Load configuration.
Definition at line 9885 of file chan_iax2.c.
References __ao2_link(), ast_category_browse(), ast_cdr_amaflags2int(), ast_clear_flag, ast_config_destroy(), ast_config_load(), ast_context_create(), ast_context_find(), 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_str2tos(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), build_peer(), build_user(), capability, DEFAULT_MAXMS, errno, format, gen, get_encrypt_methods(), 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_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_PEER_BUCKETS, ast_variable::name, ast_variable::next, option_verbose, peer_unref(), peers, portno, prefs, reg_source_db(), iax2_registry::secret, set_config_destroy(), set_timing(), socket_read(), user_unref(), users, ast_variable::value, and VERBOSE_PREFIX_2.
Referenced by load_module(), reload(), and reload_config().
09886 { 09887 struct ast_config *cfg, *ucfg; 09888 int capability=iax2_capability; 09889 struct ast_variable *v; 09890 char *cat; 09891 const char *utype; 09892 const char *tosval; 09893 int format; 09894 int portno = IAX_DEFAULT_PORTNO; 09895 int x; 09896 struct iax2_user *user; 09897 struct iax2_peer *peer; 09898 struct ast_netsock *ns; 09899 #if 0 09900 static unsigned short int last_port=0; 09901 #endif 09902 09903 cfg = ast_config_load(config_file); 09904 09905 if (!cfg) { 09906 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); 09907 return -1; 09908 } 09909 09910 if (reload) { 09911 set_config_destroy(); 09912 } 09913 09914 /* Reset global codec prefs */ 09915 memset(&prefs, 0 , sizeof(struct ast_codec_pref)); 09916 09917 /* Reset Global Flags */ 09918 memset(&globalflags, 0, sizeof(globalflags)); 09919 ast_set_flag(&globalflags, IAX_RTUPDATE); 09920 09921 #ifdef SO_NO_CHECK 09922 nochecksums = 0; 09923 #endif 09924 09925 min_reg_expire = IAX_DEFAULT_REG_EXPIRE; 09926 max_reg_expire = IAX_DEFAULT_REG_EXPIRE; 09927 09928 maxauthreq = 3; 09929 09930 v = ast_variable_browse(cfg, "general"); 09931 09932 /* Seed initial tos value */ 09933 tosval = ast_variable_retrieve(cfg, "general", "tos"); 09934 if (tosval) { 09935 if (ast_str2tos(tosval, &tos)) 09936 ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n"); 09937 } 09938 while(v) { 09939 if (!strcasecmp(v->name, "bindport")){ 09940 if (reload) 09941 ast_log(LOG_NOTICE, "Ignoring bindport on reload\n"); 09942 else 09943 portno = atoi(v->value); 09944 } else if (!strcasecmp(v->name, "pingtime")) 09945 ping_time = atoi(v->value); 09946 else if (!strcasecmp(v->name, "iaxthreadcount")) { 09947 if (reload) { 09948 if (atoi(v->value) != iaxthreadcount) 09949 ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n"); 09950 } else { 09951 iaxthreadcount = atoi(v->value); 09952 if (iaxthreadcount < 1) { 09953 ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n"); 09954 iaxthreadcount = 1; 09955 } else if (iaxthreadcount > 256) { 09956 ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n"); 09957 iaxthreadcount = 256; 09958 } 09959 } 09960 } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) { 09961 if (reload) { 09962 AST_LIST_LOCK(&dynamic_list); 09963 iaxmaxthreadcount = atoi(v->value); 09964 AST_LIST_UNLOCK(&dynamic_list); 09965 } else { 09966 iaxmaxthreadcount = atoi(v->value); 09967 if (iaxmaxthreadcount < 0) { 09968 ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n"); 09969 iaxmaxthreadcount = 0; 09970 } else if (iaxmaxthreadcount > 256) { 09971 ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n"); 09972 iaxmaxthreadcount = 256; 09973 } 09974 } 09975 } else if (!strcasecmp(v->name, "nochecksums")) { 09976 #ifdef SO_NO_CHECK 09977 if (ast_true(v->value)) 09978 nochecksums = 1; 09979 else 09980 nochecksums = 0; 09981 #else 09982 if (ast_true(v->value)) 09983 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 09984 #endif 09985 } 09986 else if (!strcasecmp(v->name, "maxjitterbuffer")) 09987 maxjitterbuffer = atoi(v->value); 09988 else if (!strcasecmp(v->name, "resyncthreshold")) 09989 resyncthreshold = atoi(v->value); 09990 else if (!strcasecmp(v->name, "maxjitterinterps")) 09991 maxjitterinterps = atoi(v->value); 09992 else if (!strcasecmp(v->name, "lagrqtime")) 09993 lagrq_time = atoi(v->value); 09994 else if (!strcasecmp(v->name, "maxregexpire")) 09995 max_reg_expire = atoi(v->value); 09996 else if (!strcasecmp(v->name, "minregexpire")) 09997 min_reg_expire = atoi(v->value); 09998 else if (!strcasecmp(v->name, "bindaddr")) { 09999 if (reload) { 10000 ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n"); 10001 } else { 10002 if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) { 10003 ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno); 10004 } else { 10005 if (option_verbose > 1) { 10006 if (strchr(v->value, ':')) 10007 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value); 10008 else 10009 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno); 10010 } 10011 if (defaultsockfd < 0) 10012 defaultsockfd = ast_netsock_sockfd(ns); 10013 ast_netsock_unref(ns); 10014 } 10015 } 10016 } else if (!strcasecmp(v->name, "authdebug")) 10017 authdebug = ast_true(v->value); 10018 else if (!strcasecmp(v->name, "encryption")) 10019 iax2_encryption = get_encrypt_methods(v->value); 10020 else if (!strcasecmp(v->name, "notransfer")) { 10021 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 10022 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 10023 ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER); 10024 } else if (!strcasecmp(v->name, "transfer")) { 10025 if (!strcasecmp(v->value, "mediaonly")) { 10026 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 10027 } else if (ast_true(v->value)) { 10028 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 10029 } else 10030 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 10031 } else if (!strcasecmp(v->name, "codecpriority")) { 10032 if(!strcasecmp(v->value, "caller")) 10033 ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST); 10034 else if(!strcasecmp(v->value, "disabled")) 10035 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 10036 else if(!strcasecmp(v->value, "reqonly")) { 10037 ast_set_flag((&globalflags), IAX_CODEC_NOCAP); 10038 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 10039 } 10040 } else if (!strcasecmp(v->name, "jitterbuffer")) 10041 ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 10042 else if (!strcasecmp(v->name, "forcejitterbuffer")) 10043 ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF); 10044 else if (!strcasecmp(v->name, "delayreject")) 10045 delayreject = ast_true(v->value); 10046 else if (!strcasecmp(v->name, "allowfwdownload")) 10047 ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD); 10048 else if (!strcasecmp(v->name, "rtcachefriends")) 10049 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS); 10050 else if (!strcasecmp(v->name, "rtignoreregexpire")) 10051 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE); 10052 else if (!strcasecmp(v->name, "rtupdate")) 10053 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE); 10054 else if (!strcasecmp(v->name, "trunktimestamps")) 10055 ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS); 10056 else if (!strcasecmp(v->name, "rtautoclear")) { 10057 int i = atoi(v->value); 10058 if(i > 0) 10059 global_rtautoclear = i; 10060 else 10061 i = 0; 10062 ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR); 10063 } else if (!strcasecmp(v->name, "trunkfreq")) { 10064 trunkfreq = atoi(v->value); 10065 if (trunkfreq < 10) 10066 trunkfreq = 10; 10067 } else if (!strcasecmp(v->name, "autokill")) { 10068 if (sscanf(v->value, "%d", &x) == 1) { 10069 if (x >= 0) 10070 autokill = x; 10071 else 10072 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); 10073 } else if (ast_true(v->value)) { 10074 autokill = DEFAULT_MAXMS; 10075 } else { 10076 autokill = 0; 10077 } 10078 } else if (!strcasecmp(v->name, "bandwidth")) { 10079 if (!strcasecmp(v->value, "low")) { 10080 capability = IAX_CAPABILITY_LOWBANDWIDTH; 10081 } else if (!strcasecmp(v->value, "medium")) { 10082 capability = IAX_CAPABILITY_MEDBANDWIDTH; 10083 } else if (!strcasecmp(v->value, "high")) { 10084 capability = IAX_CAPABILITY_FULLBANDWIDTH; 10085 } else 10086 ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n"); 10087 } else if (!strcasecmp(v->name, "allow")) { 10088 ast_parse_allow_disallow(&prefs, &capability, v->value, 1); 10089 } else if (!strcasecmp(v->name, "disallow")) { 10090 ast_parse_allow_disallow(&prefs, &capability, v->value, 0); 10091 } else if (!strcasecmp(v->name, "register")) { 10092 iax2_register(v->value, v->lineno); 10093 } else if (!strcasecmp(v->name, "iaxcompat")) { 10094 iaxcompat = ast_true(v->value); 10095 } else if (!strcasecmp(v->name, "regcontext")) { 10096 ast_copy_string(regcontext, v->value, sizeof(regcontext)); 10097 /* Create context if it doesn't exist already */ 10098 if (!ast_context_find(regcontext)) 10099 ast_context_create(NULL, regcontext, "IAX2"); 10100 } else if (!strcasecmp(v->name, "tos")) { 10101 if (ast_str2tos(v->value, &tos)) 10102 ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno); 10103 } else if (!strcasecmp(v->name, "accountcode")) { 10104 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 10105 } else if (!strcasecmp(v->name, "mohinterpret")) { 10106 ast_copy_string(mohinterpret, v->value, sizeof(user->mohinterpret)); 10107 } else if (!strcasecmp(v->name, "mohsuggest")) { 10108 ast_copy_string(mohsuggest, v->value, sizeof(user->mohsuggest)); 10109 } else if (!strcasecmp(v->name, "amaflags")) { 10110 format = ast_cdr_amaflags2int(v->value); 10111 if (format < 0) { 10112 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 10113 } else { 10114 amaflags = format; 10115 } 10116 } else if (!strcasecmp(v->name, "language")) { 10117 ast_copy_string(language, v->value, sizeof(language)); 10118 } else if (!strcasecmp(v->name, "maxauthreq")) { 10119 maxauthreq = atoi(v->value); 10120 if (maxauthreq < 0) 10121 maxauthreq = 0; 10122 } else if (!strcasecmp(v->name, "adsi")) { 10123 adsi = ast_true(v->value); 10124 } /*else if (strcasecmp(v->name,"type")) */ 10125 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 10126 v = v->next; 10127 } 10128 10129 if (defaultsockfd < 0) { 10130 if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) { 10131 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 10132 } else { 10133 if (option_verbose > 1) 10134 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno); 10135 defaultsockfd = ast_netsock_sockfd(ns); 10136 ast_netsock_unref(ns); 10137 } 10138 } 10139 if (reload) { 10140 ast_netsock_release(outsock); 10141 outsock = ast_netsock_list_alloc(); 10142 if (!outsock) { 10143 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 10144 return -1; 10145 } 10146 ast_netsock_init(outsock); 10147 } 10148 10149 if (min_reg_expire > max_reg_expire) { 10150 ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n", 10151 min_reg_expire, max_reg_expire, max_reg_expire); 10152 min_reg_expire = max_reg_expire; 10153 } 10154 iax2_capability = capability; 10155 10156 ucfg = ast_config_load("users.conf"); 10157 if (ucfg) { 10158 struct ast_variable *gen; 10159 int genhasiax; 10160 int genregisteriax; 10161 const char *hasiax, *registeriax; 10162 10163 genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax")); 10164 genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax")); 10165 gen = ast_variable_browse(ucfg, "general"); 10166 cat = ast_category_browse(ucfg, NULL); 10167 while (cat) { 10168 if (strcasecmp(cat, "general")) { 10169 hasiax = ast_variable_retrieve(ucfg, cat, "hasiax"); 10170 registeriax = ast_variable_retrieve(ucfg, cat, "registeriax"); 10171 if (ast_true(hasiax) || (!hasiax && genhasiax)) { 10172 /* Start with general parameters, then specific parameters, user and peer */ 10173 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0); 10174 if (user) { 10175 __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10176 user = user_unref(user); 10177 } 10178 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); 10179 if (peer) { 10180 if (ast_test_flag(peer, IAX_DYNAMIC)) 10181 reg_source_db(peer); 10182 __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10183 peer = peer_unref(peer); 10184 } 10185 } 10186 if (ast_true(registeriax) || (!registeriax && genregisteriax)) { 10187 char tmp[256]; 10188 const char *host = ast_variable_retrieve(ucfg, cat, "host"); 10189 const char *username = ast_variable_retrieve(ucfg, cat, "username"); 10190 const char *secret = ast_variable_retrieve(ucfg, cat, "secret"); 10191 if (!host) 10192 host = ast_variable_retrieve(ucfg, "general", "host"); 10193 if (!username) 10194 username = ast_variable_retrieve(ucfg, "general", "username"); 10195 if (!secret) 10196 secret = ast_variable_retrieve(ucfg, "general", "secret"); 10197 if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { 10198 if (!ast_strlen_zero(secret)) 10199 snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host); 10200 else 10201 snprintf(tmp, sizeof(tmp), "%s@%s", username, host); 10202 iax2_register(tmp, 0); 10203 } 10204 } 10205 } 10206 cat = ast_category_browse(ucfg, cat); 10207 } 10208 ast_config_destroy(ucfg); 10209 } 10210 10211 cat = ast_category_browse(cfg, NULL); 10212 while(cat) { 10213 if (strcasecmp(cat, "general")) { 10214 utype = ast_variable_retrieve(cfg, cat, "type"); 10215 if (utype) { 10216 if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) { 10217 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0); 10218 if (user) { 10219 __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10220 user = user_unref(user); 10221 } 10222 } 10223 if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) { 10224 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); 10225 if (peer) { 10226 if (ast_test_flag(peer, IAX_DYNAMIC)) 10227 reg_source_db(peer); 10228 __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10229 peer = peer_unref(peer); 10230 } 10231 } else if (strcasecmp(utype, "user")) { 10232 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file); 10233 } 10234 } else 10235 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 10236 } 10237 cat = ast_category_browse(cfg, cat); 10238 } 10239 ast_config_destroy(cfg); 10240 set_timing(); 10241 return 1; 10242 }
| static void set_config_destroy | ( | void | ) | [static] |
Definition at line 9869 of file chan_iax2.c.
References ast_clear_flag, delete_users(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, and IAX_USEJITTERBUF.
Referenced by set_config().
09870 { 09871 strcpy(accountcode, ""); 09872 strcpy(language, ""); 09873 strcpy(mohinterpret, "default"); 09874 strcpy(mohsuggest, ""); 09875 amaflags = 0; 09876 delayreject = 0; 09877 ast_clear_flag((&globalflags), IAX_NOTRANSFER); 09878 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 09879 ast_clear_flag((&globalflags), IAX_USEJITTERBUF); 09880 ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF); 09881 delete_users(); 09882 }
| static void set_timing | ( | void | ) | [static] |
Definition at line 9854 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by set_config().
09855 { 09856 #ifdef HAVE_ZAPTEL 09857 int bs = trunkfreq * 8; 09858 if (timingfd > -1) { 09859 if ( 09860 #ifdef ZT_TIMERACK 09861 ioctl(timingfd, ZT_TIMERCONFIG, &bs) && 09862 #endif 09863 ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs)) 09864 ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n"); 09865 } 09866 #endif 09867 }
| static void signal_condition | ( | ast_mutex_t * | lock, | |
| ast_cond_t * | cond | |||
| ) | [static] |
Definition at line 759 of file chan_iax2.c.
References ast_cond_signal(), ast_mutex_lock(), and ast_mutex_unlock().
Referenced by __schedule_action(), iax2_sched_add(), iax2_transmit(), and socket_read().
00760 { 00761 ast_mutex_lock(lock); 00762 ast_cond_signal(cond); 00763 ast_mutex_unlock(lock); 00764 }
| static int socket_process | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 6984 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, ast_async_goto(), ast_best_codec(), ast_bridged_channel(), AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_clear_flag, ast_codec_choose(), ast_codec_get_samples(), ast_codec_pref_convert(), ast_codec_pref_index(), ast_codec_pref_string(), AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_device_state_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_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), 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_verbose(), auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), chan_iax2_pvt::authmethods, iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, iax_frame::cacheable, calc_timestamp(), iax_ies::called_number, iax2_peer::callno, chan_iax2_pvt::callno, ast_iax2_meta_trunk_entry::callno, ast_iax2_mini_hdr::callno, iax2_registry::callno, iax_frame::callno, chan_iax2_pvt::capability, iax_ies::cause, iax_ies::causecode, check_access(), check_provisioning(), chan_iax2_pvt::chosenformat, cid_num, ast_iax2_meta_hdr::cmddata, iax_ies::codec_prefs, complete_dpreply(), complete_transfer(), construct_rr(), ast_iax2_full_hdr::csub, ast_frame::data, ast_iax2_meta_trunk_hdr::data, ast_iax2_meta_hdr::data, ast_frame::datalen, 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, iax_frame::final, find_callno(), find_callno_locked(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, iax_ies::format, format, chan_iax2_pvt::frames_received, ast_frame::frametype, iax_ies::fwdesc, ast_channel::hangupcause, iax2_peer::historicms, iax2_ack_registry(), 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_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, 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_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_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_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_STATE_UNCHANGED, IAX_TRUNK, iax_ies::iax_unknown, iaxfrdup2(), iaxq, iaxs, iaxsl, inaddrcmp(), chan_iax2_pvt::initid, chan_iax2_pvt::iseqno, ast_iax2_full_hdr::iseqno, iax_frame::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_frame::len, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, len, ast_channel::lock, iax2_trunk_peer::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_trunk(), ast_frame::mallocd, manager_event(), iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, iax_ies::musiconhold, ast_channel::nativeformats, NEW_ALLOW, NEW_PREVENT, ast_frame::offset, option_debug, option_verbose, chan_iax2_pvt::oseqno, iax_frame::oseqno, ast_iax2_full_hdr::oseqno, iax_frame::outoforder, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), iax2_dpcache::peer, 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, raw_hangup(), ast_channel::readformat, iax_ies::refresh, REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), remove_by_peercallno(), iax_frame::retries, chan_iax2_pvt::rprefs, chan_iax2_pvt::rseqno, iax2_trunk_peer::rxtrunktime, S_OR, ast_frame::samples, save_rr(), ast_iax2_full_hdr::scallno, schedule_delivery(), send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax_ies::serviceident, iax2_peer::smoothing, 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, iax2_trunk_peer::trunkact, try_transfer(), ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_mini_hdr::ts, ast_iax2_meta_trunk_hdr::ts, ast_iax2_full_hdr::type, uncompress_subclass(), update_registry(), iax_ies::username, VERBOSE_PREFIX_3, 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().
06985 { 06986 struct sockaddr_in sin; 06987 int res; 06988 int updatehistory=1; 06989 int new = NEW_PREVENT; 06990 void *ptr; 06991 int dcallno = 0; 06992 struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf; 06993 struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf; 06994 struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf; 06995 struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf; 06996 struct ast_iax2_meta_trunk_hdr *mth; 06997 struct ast_iax2_meta_trunk_entry *mte; 06998 struct ast_iax2_meta_trunk_mini *mtm; 06999 struct iax_frame *fr; 07000 struct iax_frame *cur; 07001 struct ast_frame f = { 0, }; 07002 struct ast_channel *c; 07003 struct iax2_dpcache *dp; 07004 struct iax2_peer *peer; 07005 struct iax2_trunk_peer *tpeer; 07006 struct timeval rxtrunktime; 07007 struct iax_ies ies; 07008 struct iax_ie_data ied0, ied1; 07009 int format; 07010 int fd; 07011 int exists; 07012 int minivid = 0; 07013 unsigned int ts; 07014 char empty[32]=""; /* Safety measure */ 07015 struct iax_frame *duped_fr; 07016 char host_pref_buf[128]; 07017 char caller_pref_buf[128]; 07018 struct ast_codec_pref pref; 07019 char *using_prefs = "mine"; 07020 07021 /* allocate an iax_frame with 4096 bytes of data buffer */ 07022 fr = alloca(sizeof(*fr) + 4096); 07023 memset(fr, 0, sizeof(*fr)); 07024 fr->afdatalen = 4096; /* From alloca() above */ 07025 07026 /* Copy frequently used parameters to the stack */ 07027 res = thread->buf_len; 07028 fd = thread->iofd; 07029 memcpy(&sin, &thread->iosin, sizeof(sin)); 07030 07031 if (res < sizeof(*mh)) { 07032 ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*mh)); 07033 return 1; 07034 } 07035 if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) { 07036 if (res < sizeof(*vh)) { 07037 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)); 07038 return 1; 07039 } 07040 07041 /* This is a video frame, get call number */ 07042 fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd, 0); 07043 minivid = 1; 07044 } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) { 07045 unsigned char metatype; 07046 07047 if (res < sizeof(*meta)) { 07048 ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a meta frame but is too short\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07049 return 1; 07050 } 07051 07052 /* This is a meta header */ 07053 switch(meta->metacmd) { 07054 case IAX_META_TRUNK: 07055 if (res < (sizeof(*meta) + sizeof(*mth))) { 07056 ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %zd min)\n", res, 07057 sizeof(*meta) + sizeof(*mth)); 07058 return 1; 07059 } 07060 mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data); 07061 ts = ntohl(mth->ts); 07062 metatype = meta->cmddata; 07063 res -= (sizeof(*meta) + sizeof(*mth)); 07064 ptr = mth->data; 07065 tpeer = find_tpeer(&sin, fd); 07066 if (!tpeer) { 07067 ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07068 return 1; 07069 } 07070 tpeer->trunkact = ast_tvnow(); 07071 if (!ts || ast_tvzero(tpeer->rxtrunktime)) 07072 tpeer->rxtrunktime = tpeer->trunkact; 07073 rxtrunktime = tpeer->rxtrunktime; 07074 ast_mutex_unlock(&tpeer->lock); 07075 while(res >= sizeof(*mte)) { 07076 /* Process channels */ 07077 unsigned short callno, trunked_ts, len; 07078 07079 if (metatype == IAX_META_TRUNK_MINI) { 07080 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 07081 ptr += sizeof(*mtm); 07082 res -= sizeof(*mtm); 07083 len = ntohs(mtm->len); 07084 callno = ntohs(mtm->mini.callno); 07085 trunked_ts = ntohs(mtm->mini.ts); 07086 } else if (metatype == IAX_META_TRUNK_SUPERMINI) { 07087 mte = (struct ast_iax2_meta_trunk_entry *)ptr; 07088 ptr += sizeof(*mte); 07089 res -= sizeof(*mte); 07090 len = ntohs(mte->len); 07091 callno = ntohs(mte->callno); 07092 trunked_ts = 0; 07093 } else { 07094 ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07095 break; 07096 } 07097 /* Stop if we don't have enough data */ 07098 if (len > res) 07099 break; 07100 fr->callno = find_callno_locked(callno & ~IAX_FLAG_FULL, 0, &sin, NEW_PREVENT, fd, 0); 07101 if (fr->callno) { 07102 /* If it's a valid call, deliver the contents. If not, we 07103 drop it, since we don't have a scallno to use for an INVAL */ 07104 /* Process as a mini frame */ 07105 memset(&f, 0, sizeof(f)); 07106 f.frametype = AST_FRAME_VOICE; 07107 if (iaxs[fr->callno]) { 07108 if (iaxs[fr->callno]->voiceformat > 0) { 07109 f.subclass = iaxs[fr->callno]->voiceformat; 07110 f.datalen = len; 07111 if (f.datalen >= 0) { 07112 if (f.datalen) 07113 f.data = ptr; 07114 if(trunked_ts) { 07115 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff); 07116 } else 07117 fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts); 07118 /* Don't pass any packets until we're started */ 07119 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 07120 /* Common things */ 07121 f.src = "IAX2"; 07122 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 07123 f.samples = ast_codec_get_samples(&f); 07124 iax_frame_wrap(fr, &f); 07125 duped_fr = iaxfrdup2(fr); 07126 if (duped_fr) { 07127 schedule_delivery(duped_fr, updatehistory, 1, &fr->ts); 07128 } 07129 /* It is possible for the pvt structure to go away after we call schedule_delivery */ 07130 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 07131 iaxs[fr->callno]->last = fr->ts; 07132 #if 1 07133 if (option_debug && iaxdebug) 07134 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 07135 #endif 07136 } 07137 } 07138 } else { 07139 ast_log(LOG_WARNING, "Datalen < 0?\n"); 07140 } 07141 } else { 07142 ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n "); 07143 iax2_vnak(fr->callno); 07144 } 07145 } 07146 ast_mutex_unlock(&iaxsl[fr->callno]); 07147 } 07148 ptr += len; 07149 res -= len; 07150 } 07151 07152 } 07153 return 1; 07154 } 07155 07156 #ifdef DEBUG_SUPPORT 07157 if (iaxdebug && (res >= sizeof(*fh))) 07158 iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh)); 07159 #endif 07160 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07161 if (res < sizeof(*fh)) { 07162 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)); 07163 return 1; 07164 } 07165 07166 /* Get the destination call number */ 07167 dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS; 07168 /* Retrieve the type and subclass */ 07169 f.frametype = fh->type; 07170 if (f.frametype == AST_FRAME_VIDEO) { 07171 f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 07172 } else { 07173 f.subclass = uncompress_subclass(fh->csub); 07174 } 07175 07176 /* Deal with POKE/PONG without allocating a callno */ 07177 if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_POKE) { 07178 /* Reply back with a PONG, but don't care about the result. */ 07179 send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_PONG, ntohs(fh->ts), fh->oseqno); 07180 return 1; 07181 } else if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK && dcallno == 1) { 07182 /* Ignore */ 07183 return 1; 07184 } 07185 07186 if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) || 07187 (f.subclass == IAX_COMMAND_POKE) || (f.subclass == IAX_COMMAND_FWDOWNL) || 07188 (f.subclass == IAX_COMMAND_REGREL))) 07189 new = NEW_ALLOW; 07190 } else { 07191 /* Don't know anything about it yet */ 07192 f.frametype = AST_FRAME_NULL; 07193 f.subclass = 0; 07194 } 07195 07196 if (!fr->callno) { 07197 int check_dcallno = 0; 07198 07199 /* 07200 * We enforce accurate destination call numbers for all full frames except 07201 * LAGRQ and PING commands. This is because older versions of Asterisk 07202 * schedule these commands to get sent very quickly, and they will sometimes 07203 * be sent before they receive the first frame from the other side. When 07204 * that happens, it doesn't contain the destination call number. However, 07205 * not checking it for these frames is safe. 07206 * 07207 * Discussed in the following thread: 07208 * http://lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html 07209 */ 07210 07211 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07212 check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1; 07213 } 07214 07215 fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno); 07216 } 07217 07218 if (fr->callno > 0) 07219 ast_mutex_lock(&iaxsl[fr->callno]); 07220 07221 if (!fr->callno || !iaxs[fr->callno]) { 07222 /* A call arrived for a nonexistent destination. Unless it's an "inval" 07223 frame, reply with an inval */ 07224 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07225 /* We can only raw hangup control frames */ 07226 if (((f.subclass != IAX_COMMAND_INVAL) && 07227 (f.subclass != IAX_COMMAND_TXCNT) && 07228 (f.subclass != IAX_COMMAND_TXACC) && 07229 (f.subclass != IAX_COMMAND_FWDOWNL))|| 07230 (f.frametype != AST_FRAME_IAX)) 07231 raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL, 07232 fd); 07233 } 07234 if (fr->callno > 0) 07235 ast_mutex_unlock(&iaxsl[fr->callno]); 07236 return 1; 07237 } 07238 if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) { 07239 if (decrypt_frame(fr->callno, fh, &f, &res)) { 07240 ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n"); 07241 ast_mutex_unlock(&iaxsl[fr->callno]); 07242 return 1; 07243 } 07244 #ifdef DEBUG_SUPPORT 07245 else if (iaxdebug) 07246 iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh)); 07247 #endif 07248 } 07249 07250 /* count this frame */ 07251 iaxs[fr->callno]->frames_received++; 07252 07253 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid && 07254 f.subclass != IAX_COMMAND_TXCNT && /* for attended transfer */ 07255 f.subclass != IAX_COMMAND_TXACC) { /* for attended transfer */ 07256 unsigned short new_peercallno; 07257 07258 new_peercallno = (unsigned short) (ntohs(mh->callno) & ~IAX_FLAG_FULL); 07259 if (new_peercallno && new_peercallno != iaxs[fr->callno]->peercallno) { 07260 if (iaxs[fr->callno]->peercallno) { 07261 remove_by_peercallno(iaxs[fr->callno]); 07262 } 07263 iaxs[fr->callno]->peercallno = new_peercallno; 07264 store_by_peercallno(iaxs[fr->callno]); 07265 } 07266 } 07267 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07268 if (option_debug && iaxdebug) 07269 ast_log(LOG_DEBUG, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass); 07270 /* Check if it's out of order (and not an ACK or INVAL) */ 07271 fr->oseqno = fh->oseqno; 07272 fr->iseqno = fh->iseqno; 07273 fr->ts = ntohl(fh->ts); 07274 #ifdef IAXTESTS 07275 if (test_resync) { 07276 if (option_debug) 07277 ast_log(LOG_DEBUG, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync); 07278 fr->ts += test_resync; 07279 } 07280 #endif /* IAXTESTS */ 07281 #if 0 07282 if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || 07283 ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX && 07284 (f.subclass == IAX_COMMAND_NEW || 07285 f.subclass == IAX_COMMAND_AUTHREQ || 07286 f.subclass == IAX_COMMAND_ACCEPT || 07287 f.subclass == IAX_COMMAND_REJECT)) ) ) 07288 #endif 07289 if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE)) 07290 updatehistory = 0; 07291 if ((iaxs[fr->callno]->iseqno != fr->oseqno) && 07292 (iaxs[fr->callno]->iseqno || 07293 ((f.subclass != IAX_COMMAND_TXCNT) && 07294 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 07295 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 07296 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 07297 (f.subclass != IAX_COMMAND_TXACC)) || 07298 (f.frametype != AST_FRAME_IAX))) { 07299 if ( 07300 ((f.subclass != IAX_COMMAND_ACK) && 07301 (f.subclass != IAX_COMMAND_INVAL) && 07302 (f.subclass != IAX_COMMAND_TXCNT) && 07303 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 07304 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 07305 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 07306 (f.subclass != IAX_COMMAND_TXACC) && 07307 (f.subclass != IAX_COMMAND_VNAK)) || 07308 (f.frametype != AST_FRAME_IAX)) { 07309 /* If it's not an ACK packet, it's out of order. */ 07310 if (option_debug) 07311 ast_log(LOG_DEBUG, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 07312 iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass); 07313 /* Check to see if we need to request retransmission, 07314 * and take sequence number wraparound into account */ 07315 if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) { 07316 /* If we've already seen it, ack it XXX There's a border condition here XXX */ 07317 if ((f.frametype != AST_FRAME_IAX) || 07318 ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) { 07319 if (option_debug) 07320 ast_log(LOG_DEBUG, "Acking anyway\n"); 07321 /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if 07322 we have anything to send, we'll retransmit and get an ACK back anyway XXX */ 07323 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07324 } 07325 } else { 07326 /* Send a VNAK requesting retransmission */ 07327 iax2_vnak(fr->callno); 07328 } 07329 ast_mutex_unlock(&iaxsl[fr->callno]); 07330 return 1; 07331 } 07332 } else { 07333 /* Increment unless it's an ACK or VNAK */ 07334 if (((f.subclass != IAX_COMMAND_ACK) && 07335 (f.subclass != IAX_COMMAND_INVAL) && 07336 (f.subclass != IAX_COMMAND_TXCNT) && 07337 (f.subclass != IAX_COMMAND_TXACC) && 07338 (f.subclass != IAX_COMMAND_VNAK)) || 07339 (f.frametype != AST_FRAME_IAX)) 07340 iaxs[fr->callno]->iseqno++; 07341 } 07342 /* A full frame */ 07343 if (res < sizeof(*fh)) { 07344 ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*fh)); 07345 ast_mutex_unlock(&iaxsl[fr->callno]); 07346 return 1; 07347 } 07348 /* Ensure text frames are NULL-terminated */ 07349 if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') { 07350 if (res < thread->buf_size) 07351 thread->buf[res++] = '\0'; 07352 else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */ 07353 thread->buf[res - 1] = '\0'; 07354 } 07355 f.datalen = res - sizeof(*fh); 07356 07357 /* Handle implicit ACKing unless this is an INVAL, and only if this is 07358 from the real peer, not the transfer peer */ 07359 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 07360 ((f.subclass != IAX_COMMAND_INVAL) || 07361 (f.frametype != AST_FRAME_IAX))) { 07362 unsigned char x; 07363 int call_to_destroy; 07364 /* XXX This code is not very efficient. Surely there is a better way which still 07365 properly handles boundary conditions? XXX */ 07366 /* First we have to qualify that the ACKed value is within our window */ 07367 for (x=iaxs[fr->callno]->rseqno; x != iaxs[fr->callno]->oseqno; x++) 07368 if (fr->iseqno == x) 07369 break; 07370 if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) { 07371 /* The acknowledgement is within our window. Time to acknowledge everything 07372 that it says to */ 07373 for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) { 07374 /* Ack the packet with the given timestamp */ 07375 if (option_debug && iaxdebug) 07376 ast_log(LOG_DEBUG, "Cancelling transmission of packet %d\n", x); 07377 call_to_destroy = 0; 07378 AST_LIST_LOCK(&iaxq.queue); 07379 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 07380 /* If it's our call, and our timestamp, mark -1 retries */ 07381 if ((fr->callno == cur->callno) && (x == cur->oseqno)) { 07382 cur->retries = -1; 07383 /* Destroy call if this is the end */ 07384 if (cur->final) 07385 call_to_destroy = fr->callno; 07386 } 07387 } 07388 AST_LIST_UNLOCK(&iaxq.queue); 07389 if (call_to_destroy) { 07390 if (iaxdebug && option_debug) 07391 ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", call_to_destroy); 07392 ast_mutex_lock(&iaxsl[call_to_destroy]); 07393 iax2_destroy(call_to_destroy); 07394 ast_mutex_unlock(&iaxsl[call_to_destroy]); 07395 } 07396 } 07397 /* Note how much we've received acknowledgement for */ 07398 if (iaxs[fr->callno]) 07399 iaxs[fr->callno]->rseqno = fr->iseqno; 07400 else { 07401 /* Stop processing now */ 07402 ast_mutex_unlock(&iaxsl[fr->callno]); 07403 return 1; 07404 } 07405 } else if (option_debug) 07406 ast_log(LOG_DEBUG, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno); 07407 } 07408 if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 07409 ((f.frametype != AST_FRAME_IAX) || 07410 ((f.subclass != IAX_COMMAND_TXACC) && 07411 (f.subclass != IAX_COMMAND_TXCNT)))) { 07412 /* Only messages we accept from a transfer host are TXACC and TXCNT */ 07413 ast_mutex_unlock(&iaxsl[fr->callno]); 07414 return 1; 07415 } 07416 07417 if (f.datalen) { 07418 if (f.frametype == AST_FRAME_IAX) { 07419 if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) { 07420 ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr)); 07421 ast_mutex_unlock(&iaxsl[fr->callno]); 07422 return 1; 07423 } 07424 f.data = NULL; 07425 f.datalen = 0; 07426 } else 07427 f.data = thread->buf + sizeof(*fh); 07428 } else { 07429 if (f.frametype == AST_FRAME_IAX) 07430 f.data = NULL; 07431 else 07432 f.data = empty; 07433 memset(&ies, 0, sizeof(ies)); 07434 } 07435 07436 /* when we receive the first full frame for a new incoming channel, 07437 it is safe to start the PBX on the channel because we have now 07438 completed a 3-way handshake with the peer */ 07439 if ((f.frametype == AST_FRAME_VOICE) || 07440 (f.frametype == AST_FRAME_VIDEO) || 07441 (f.frametype == AST_FRAME_IAX)) { 07442 if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) { 07443 ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 07444 if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) { 07445 ast_mutex_unlock(&iaxsl[fr->callno]); 07446 return 1; 07447 } 07448 } 07449 } 07450 07451 if (f.frametype == AST_FRAME_VOICE) { 07452 if (f.subclass != iaxs[fr->callno]->voiceformat) { 07453 iaxs[fr->callno]->voiceformat = f.subclass; 07454 if (option_debug) 07455 ast_log(LOG_DEBUG, "Ooh, voice format changed to %d\n", f.subclass); 07456 if (iaxs[fr->callno]->owner) { 07457 int orignative; 07458 retryowner: 07459 if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) { 07460 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 07461 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner; 07462 } 07463 if (iaxs[fr->callno]) { 07464 if (iaxs[fr->callno]->owner) { 07465 orignative = iaxs[fr->callno]->owner->nativeformats; 07466 iaxs[fr->callno]->owner->nativeformats = f.subclass; 07467 if (iaxs[fr->callno]->owner->readformat) 07468 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 07469 iaxs[fr->callno]->owner->nativeformats = orignative; 07470 ast_mutex_unlock(&iaxs[fr->callno]->owner->lock); 07471 } 07472 } else { 07473 if (option_debug) 07474 ast_log(LOG_DEBUG, "Neat, somebody took away the channel at a magical time but i found it!\n"); 07475 ast_mutex_unlock(&iaxsl[fr->callno]); 07476 return 1; 07477 } 07478 } 07479 } 07480 } 07481 if (f.frametype == AST_FRAME_VIDEO) { 07482 if (f.subclass != iaxs[fr->callno]->videoformat) { 07483 if (option_debug) 07484 ast_log(LOG_DEBUG, "Ooh, video format changed to %d\n", f.subclass & ~0x1); 07485 iaxs[fr->callno]->videoformat = f.subclass & ~0x1; 07486 } 07487 } 07488 if (f.frametype == AST_FRAME_IAX) { 07489 AST_SCHED_DEL(sched, iaxs[fr->callno]->initid); 07490 /* Handle the IAX pseudo frame itself */ 07491 if (option_debug && iaxdebug) 07492 ast_log(LOG_DEBUG, "IAX subclass %d received\n", f.subclass); 07493 07494 /* Update last ts unless the frame's timestamp originated with us. */ 07495 if (iaxs[fr->callno]->last < fr->ts && 07496 f.subclass != IAX_COMMAND_ACK && 07497 f.subclass != IAX_COMMAND_PONG && 07498 f.subclass != IAX_COMMAND_LAGRP) { 07499 iaxs[fr->callno]->last = fr->ts; 07500 if (option_debug && iaxdebug) 07501 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 07502 } 07503 07504 switch(f.subclass) { 07505 case IAX_COMMAND_ACK: 07506 /* Do nothing */ 07507 break; 07508 case IAX_COMMAND_QUELCH: 07509 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 07510 /* Generate Manager Hold event, if necessary*/ 07511 if (iaxs[fr->callno]->owner) { 07512 manager_event(EVENT_FLAG_CALL, "Hold", 07513 "Channel: %s\r\n" 07514 "Uniqueid: %s\r\n", 07515 iaxs[fr->callno]->owner->name, 07516 iaxs[fr->callno]->owner->uniqueid); 07517 } 07518 07519 ast_set_flag(iaxs[fr->callno], IAX_QUELCH); 07520 if (ies.musiconhold) { 07521 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 07522 const char *mohsuggest = iaxs[fr->callno]->mohsuggest; 07523 iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, 07524 S_OR(mohsuggest, NULL), 07525 !ast_strlen_zero(mohsuggest) ? strlen(mohsuggest) + 1 : 0); 07526 if (!iaxs[fr->callno]) { 07527 ast_mutex_unlock(&iaxsl[fr->callno]); 07528 return 1; 07529 } 07530 } 07531 } 07532 } 07533 break; 07534 case IAX_COMMAND_UNQUELCH: 07535 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 07536 /* Generate Manager Unhold event, if necessary*/ 07537 if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) { 07538 manager_event(EVENT_FLAG_CALL, "Unhold", 07539 "Channel: %s\r\n" 07540 "Uniqueid: %s\r\n", 07541 iaxs[fr->callno]->owner->name, 07542 iaxs[fr->callno]->owner->uniqueid); 07543 } 07544 07545 ast_clear_flag(iaxs[fr->callno], IAX_QUELCH); 07546 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 07547 iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0); 07548 if (!iaxs[fr->callno]) { 07549 ast_mutex_unlock(&iaxsl[fr->callno]); 07550 return 1; 07551 } 07552 } 07553 } 07554 break; 07555 case IAX_COMMAND_TXACC: 07556 if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) { 07557 /* Ack the packet with the given timestamp */ 07558 AST_LIST_LOCK(&iaxq.queue); 07559 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 07560 /* Cancel any outstanding txcnt's */ 07561 if ((fr->callno == cur->callno) && (cur->transfer)) 07562 cur->retries = -1; 07563 } 07564 AST_LIST_UNLOCK(&iaxq.queue); 07565 memset(&ied1, 0, sizeof(ied1)); 07566 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno); 07567 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1); 07568 iaxs[fr->callno]->transferring = TRANSFER_READY; 07569 } 07570 break; 07571 case IAX_COMMAND_NEW: 07572 /* Ignore if it's already up */ 07573 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) 07574 break; 07575 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 07576 ast_mutex_unlock(&iaxsl[fr->callno]); 07577 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 07578 ast_mutex_lock(&iaxsl[fr->callno]); 07579 if (!iaxs[fr->callno]) { 07580 ast_mutex_unlock(&iaxsl[fr->callno]); 07581 return 1; 07582 } 07583 } 07584 /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */ 07585 if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) { 07586 int new_callno; 07587 if ((new_callno = make_trunk(fr->callno, 1)) != -1) 07588 fr->callno = new_callno; 07589 } 07590 /* For security, always ack immediately */ 07591 if (delayreject) 07592 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07593 if (check_access(fr->callno, &sin, &ies)) { 07594 /* They're not allowed on */ 07595 auth_fail(fr->callno, IAX_COMMAND_REJECT); 07596 if (authdebug) 07597 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); 07598 break; 07599 } 07600 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 07601 const char *context, *exten, *cid_num; 07602 07603 context = ast_strdupa(iaxs[fr->callno]->context); 07604 exten = ast_strdupa(iaxs[fr->callno]->exten); 07605 cid_num = ast_strdupa(iaxs[fr->callno]->cid_num); 07606 07607 /* This might re-enter the IAX code and need the lock */ 07608 ast_mutex_unlock(&iaxsl[fr->callno]); 07609 exists = ast_exists_extension(NULL, context, exten, 1, cid_num); 07610 ast_mutex_lock(&iaxsl[fr->callno]); 07611 07612 if (!iaxs[fr->callno]) { 07613 ast_mutex_unlock(&iaxsl[fr->callno]); 07614 return 1; 07615 } 07616 } else 07617 exists = 0; 07618 if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) { 07619 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 07620 memset(&ied0, 0, sizeof(ied0)); 07621 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 07622 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 07623 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07624 if (!iaxs[fr->callno]) { 07625 ast_mutex_unlock(&iaxsl[fr->callno]); 07626 return 1; 07627 } 07628 if (authdebug) 07629 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); 07630 } else { 07631 /* Select an appropriate format */ 07632 07633 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 07634 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07635 using_prefs = "reqonly"; 07636 } else { 07637 using_prefs = "disabled"; 07638 } 07639 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 07640 memset(&pref, 0, sizeof(pref)); 07641 strcpy(caller_pref_buf, "disabled"); 07642 strcpy(host_pref_buf, "disabled"); 07643 } else { 07644 using_prefs = "mine"; 07645 /* If the information elements are in here... use them */ 07646 if (ies.codec_prefs) 07647 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 07648 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 07649 /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/ 07650 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 07651 pref = iaxs[fr->callno]->rprefs; 07652 using_prefs = "caller"; 07653 } else { 07654 pref = iaxs[fr->callno]->prefs; 07655 } 07656 } else 07657 pref = iaxs[fr->callno]->prefs; 07658 07659 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 07660 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 07661 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 07662 } 07663 if (!format) { 07664 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 07665 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 07666 if (!format) { 07667 memset(&ied0, 0, sizeof(ied0)); 07668 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07669 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07670 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07671 if (!iaxs[fr->callno]) { 07672 ast_mutex_unlock(&iaxsl[fr->callno]); 07673 return 1; 07674 } 07675 if (authdebug) { 07676 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 07677 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); 07678 else 07679 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); 07680 } 07681 } else { 07682 /* Pick one... */ 07683 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07684 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 07685 format = 0; 07686 } else { 07687 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 07688 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 07689 memset(&pref, 0, sizeof(pref)); 07690 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07691 strcpy(caller_pref_buf,"disabled"); 07692 strcpy(host_pref_buf,"disabled"); 07693 } else { 07694 using_prefs = "mine"; 07695 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 07696 /* Do the opposite of what we tried above. */ 07697 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 07698 pref = iaxs[fr->callno]->prefs; 07699 } else { 07700 pref = iaxs[fr->callno]->rprefs; 07701 using_prefs = "caller"; 07702 } 07703 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 07704 07705 } else /* if no codec_prefs IE do it the old way */ 07706 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07707 } 07708 } 07709 07710 if (!format) { 07711 memset(&ied0, 0, sizeof(ied0)); 07712 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07713 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07714 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07715 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07716 if (!iaxs[fr->callno]) { 07717 ast_mutex_unlock(&iaxsl[fr->callno]); 07718 return 1; 07719 } 07720 if (authdebug) 07721 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); 07722 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 07723 break; 07724 } 07725 } 07726 } 07727 if (format) { 07728 /* No authentication required, let them in */ 07729 memset(&ied1, 0, sizeof(ied1)); 07730 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 07731 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 07732 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 07733 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07734 if (option_verbose > 2) 07735 ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n" 07736 "%srequested format = %s,\n" 07737 "%srequested prefs = %s,\n" 07738 "%sactual format = %s,\n" 07739 "%shost prefs = %s,\n" 07740 "%spriority = %s\n", 07741 ast_inet_ntoa(sin.sin_addr), 07742 VERBOSE_PREFIX_4, 07743 ast_getformatname(iaxs[fr->callno]->peerformat), 07744 VERBOSE_PREFIX_4, 07745 caller_pref_buf, 07746 VERBOSE_PREFIX_4, 07747 ast_getformatname(format), 07748 VERBOSE_PREFIX_4, 07749 host_pref_buf, 07750 VERBOSE_PREFIX_4, 07751 using_prefs); 07752 07753 iaxs[fr->callno]->chosenformat = format; 07754 ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 07755 } else { 07756 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 07757 /* If this is a TBD call, we're ready but now what... */ 07758 if (option_verbose > 2) 07759 ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 07760 } 07761 } 07762 } 07763 break; 07764 } 07765 if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5) 07766 merge_encryption(iaxs[fr->callno],ies.encmethods); 07767 else 07768 iaxs[fr->callno]->encmethods = 0; 07769 if (!authenticate_request(fr->callno) && iaxs[fr->callno]) 07770 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED); 07771 if (!iaxs[fr->callno]) { 07772 ast_mutex_unlock(&iaxsl[fr->callno]); 07773 return 1; 07774 } 07775 break; 07776 case IAX_COMMAND_DPREQ: 07777 /* Request status in the dialplan */ 07778 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) && 07779 !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) { 07780 if (iaxcompat) { 07781 /* Spawn a thread for the lookup */ 07782 spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num); 07783 } else { 07784 /* Just look it up */ 07785 dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1); 07786 } 07787 } 07788 break; 07789 case IAX_COMMAND_HANGUP: 07790 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 07791 if (option_debug) 07792 ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr->callno); 07793 /* Set hangup cause according to remote */ 07794 if (ies.causecode && iaxs[fr->callno]->owner) 07795 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 07796 /* Send ack immediately, before we destroy */ 07797 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07798 iax2_destroy(fr->callno); 07799 break; 07800 case IAX_COMMAND_REJECT: 07801 /* Set hangup cause according to remote */ 07802 if (ies.causecode && iaxs[fr->callno]->owner) 07803 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 07804 07805 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 07806 if (iaxs[fr->callno]->owner && authdebug) 07807 ast_log(LOG_WARNING, "Call rejected by %s: %s\n", 07808 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), 07809 ies.cause ? ies.cause : "<Unknown>"); 07810 if (option_debug) 07811 ast_log(LOG_DEBUG, "Immediately destroying %d, having received reject\n", 07812 fr->callno); 07813 } 07814 /* Send ack immediately, before we destroy */ 07815 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, 07816 fr->ts, NULL, 0, fr->iseqno); 07817 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) 07818 iaxs[fr->callno]->error = EPERM; 07819 iax2_destroy(fr->callno); 07820 break; 07821 case IAX_COMMAND_TRANSFER: 07822 { 07823 struct ast_channel *bridged_chan; 07824 07825 if (iaxs[fr->callno]->owner && (bridged_chan = ast_bridged_channel(iaxs[fr->callno]->owner)) && ies.called_number) { 07826 /* Set BLINDTRANSFER channel variables */ 07827 07828 ast_mutex_unlock(&iaxsl[fr->callno]); 07829 pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", bridged_chan->name); 07830 ast_mutex_lock(&iaxsl[fr->callno]); 07831 if (!iaxs[fr->callno]) { 07832 ast_mutex_unlock(&iaxsl[fr->callno]); 07833 return 1; 07834 } 07835 07836 pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", iaxs[fr->callno]->owner->name); 07837 if (!strcmp(ies.called_number, ast_parking_ext())) { 07838 if (iax_park(bridged_chan, iaxs[fr->callno]->owner)) { 07839 ast_log(LOG_WARNING, "Failed to park call on '%s'\n", bridged_chan->name); 07840 } else { 07841 ast_log(LOG_DEBUG, "Parked call on '%s'\n", bridged_chan->name); 07842 } 07843 } else { 07844 if (ast_async_goto(bridged_chan, iaxs[fr->callno]->context, ies.called_number, 1)) 07845 ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", bridged_chan->name, 07846 ies.called_number, iaxs[fr->callno]->context); 07847 else 07848 ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", bridged_chan->name, 07849 ies.called_number, iaxs[fr->callno]->context); 07850 } 07851 } else 07852 ast_log(LOG_DEBUG, "Async goto not applicable on call %d\n", fr->callno); 07853 07854 break; 07855 } 07856 case IAX_COMMAND_ACCEPT: 07857 /* Ignore if call is already up or needs authentication or is a TBD */ 07858 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED)) 07859 break; 07860 if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 07861 /* Send ack immediately, before we destroy */ 07862 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07863 iax2_destroy(fr->callno); 07864 break; 07865 } 07866 if (ies.format) { 07867 iaxs[fr->callno]->peerformat = ies.format; 07868 } else { 07869 if (iaxs[fr->callno]->owner) 07870 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats; 07871 else 07872 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability; 07873 } 07874 if (option_verbose > 2) 07875 ast_verbose(VERBOSE_PREFIX_3 "Call accepted by %s (format %s)\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), ast_getformatname(iaxs[fr->callno]->peerformat)); 07876 if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) { 07877 memset(&ied0, 0, sizeof(ied0)); 07878 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07879 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07880 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07881 if (!iaxs[fr->callno]) { 07882 ast_mutex_unlock(&iaxsl[fr->callno]); 07883 return 1; 07884 } 07885 if (authdebug) 07886 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); 07887 } else { 07888 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07889 if (iaxs[fr->callno]->owner) { 07890 /* Switch us to use a compatible format */ 07891 iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat; 07892 if (option_verbose > 2) 07893 ast_verbose(VERBOSE_PREFIX_3 "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats)); 07894 retryowner2: 07895 if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) { 07896 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 07897 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2; 07898 } 07899 07900 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) { 07901 /* Setup read/write formats properly. */ 07902 if (iaxs[fr->callno]->owner->writeformat) 07903 ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat); 07904 if (iaxs[fr->callno]->owner->readformat) 07905 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 07906 ast_mutex_unlock(&iaxs[fr->callno]->owner->lock); 07907 } 07908 } 07909 } 07910 if (iaxs[fr->callno]) { 07911 ast_mutex_lock(&dpcache_lock); 07912 dp = iaxs[fr->callno]->dpentries; 07913 while(dp) { 07914 if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) { 07915 iax2_dprequest(dp, fr->callno); 07916 } 07917 dp = dp->peer; 07918 } 07919 ast_mutex_unlock(&dpcache_lock); 07920 } 07921 break; 07922 case IAX_COMMAND_POKE: 07923 /* Send back a pong packet with the original timestamp */ 07924 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1); 07925 if (!iaxs[fr->callno]) { 07926 ast_mutex_unlock(&iaxsl[fr->callno]); 07927 return 1; 07928 } 07929 break; 07930 case IAX_COMMAND_PING: 07931 { 07932 struct iax_ie_data pingied; 07933 construct_rr(iaxs[fr->callno], &pingied); 07934 /* Send back a pong packet with the original timestamp */ 07935 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1); 07936 } 07937 break; 07938 case IAX_COMMAND_PONG: 07939 /* Calculate ping time */ 07940 iaxs[fr->callno]->pingtime = calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts; 07941 /* save RR info */ 07942 save_rr(fr, &ies); 07943 07944 if (iaxs[fr->callno]->peerpoke) { 07945 peer = iaxs[fr->callno]->peerpoke; 07946 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) { 07947 if (iaxs[fr->callno]->pingtime <= peer->maxms) { 07948 ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime); 07949 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 07950 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 07951 } 07952 } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) { 07953 if (iaxs[fr->callno]->pingtime > peer->maxms) { 07954 ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime); 07955 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 07956 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 07957 } 07958 } 07959 peer->lastms = iaxs[fr->callno]->pingtime; 07960 if (peer->smoothing && (peer->lastms > -1)) 07961 peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2; 07962 else if (peer->smoothing && peer->lastms < 0) 07963 peer->historicms = (0 + peer->historicms) / 2; 07964 else 07965 peer->historicms = iaxs[fr->callno]->pingtime; 07966 07967 /* Remove scheduled iax2_poke_noanswer */ 07968 if (peer->pokeexpire > -1) { 07969 if (!ast_sched_del(sched, peer->pokeexpire)) { 07970 peer_unref(peer); 07971 peer->pokeexpire = -1; 07972 } 07973 } 07974 /* Schedule the next cycle */ 07975 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) 07976 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 07977 else 07978 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer_ref(peer)); 07979 if (peer->pokeexpire == -1) 07980 peer_unref(peer); 07981 /* and finally send the ack */ 07982 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07983 /* And wrap up the qualify call */ 07984 iax2_destroy(fr->callno); 07985 peer->callno = 0; 07986 if (option_debug) 07987 ast_log(LOG_DEBUG, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms); 07988 } 07989 break; 07990 case IAX_COMMAND_LAGRQ: 07991 case IAX_COMMAND_LAGRP: 07992 f.src = "LAGRQ"; 07993 f.mallocd = 0; 07994 f.offset = 0; 07995 f.samples = 0; 07996 iax_frame_wrap(fr, &f); 07997 if(f.subclass == IAX_COMMAND_LAGRQ) { 07998 /* Received a LAGRQ - echo back a LAGRP */ 07999 fr->af.subclass = IAX_COMMAND_LAGRP; 08000 iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0); 08001 } else { 08002 /* Received LAGRP in response to our LAGRQ */ 08003 unsigned int ts; 08004 /* This is a reply we've been given, actually measure the difference */ 08005 ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af); 08006 iaxs[fr->callno]->lag = ts - fr->ts; 08007 if (option_debug && iaxdebug) 08008 ast_log(LOG_DEBUG, "Peer %s lag measured as %dms\n", 08009 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag); 08010 } 08011 break; 08012 case IAX_COMMAND_AUTHREQ: 08013 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 08014 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>"); 08015 break; 08016 } 08017 if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) { 08018 struct ast_frame hangup_fr = { .frametype = AST_FRAME_CONTROL, 08019 .subclass = AST_CONTROL_HANGUP, 08020 }; 08021 ast_log(LOG_WARNING, 08022 "I don't know how to authenticate %s to %s\n", 08023 ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr)); 08024 iax2_queue_frame(fr->callno, &hangup_fr); 08025 } 08026 if (!iaxs[fr->callno]) { 08027 ast_mutex_unlock(&iaxsl[fr->callno]); 08028 return 1; 08029 } 08030 break; 08031 case IAX_COMMAND_AUTHREP: 08032 /* For security, always ack immediately */ 08033 if (delayreject) 08034 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08035 /* Ignore once we've started */ 08036 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 08037 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>"); 08038 break; 08039 } 08040 if (authenticate_verify(iaxs[fr->callno], &ies)) { 08041 if (authdebug) 08042 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); 08043 memset(&ied0, 0, sizeof(ied0)); 08044 auth_fail(fr->callno, IAX_COMMAND_REJECT); 08045 break; 08046 } 08047 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 08048 /* This might re-enter the IAX code and need the lock */ 08049 exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num); 08050 } else 08051 exists = 0; 08052 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 08053 if (authdebug) 08054 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); 08055 memset(&ied0, 0, sizeof(ied0)); 08056 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 08057 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 08058 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08059 if (!iaxs[fr->callno]) { 08060 ast_mutex_unlock(&iaxsl[fr->callno]); 08061 return 1; 08062 } 08063 } else { 08064 /* Select an appropriate format */ 08065 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 08066 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08067 using_prefs = "reqonly"; 08068 } else { 08069 using_prefs = "disabled"; 08070 } 08071 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 08072 memset(&pref, 0, sizeof(pref)); 08073 strcpy(caller_pref_buf, "disabled"); 08074 strcpy(host_pref_buf, "disabled"); 08075 } else { 08076 using_prefs = "mine"; 08077 if (ies.codec_prefs) 08078 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 08079 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 08080 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 08081 pref = iaxs[fr->callno]->rprefs; 08082 using_prefs = "caller"; 08083 } else { 08084 pref = iaxs[fr->callno]->prefs; 08085 } 08086 } else /* if no codec_prefs IE do it the old way */ 08087 pref = iaxs[fr->callno]->prefs; 08088 08089 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 08090 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 08091 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 08092 } 08093 if (!format) { 08094 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08095 if (option_debug) 08096 ast_log(LOG_DEBUG, "We don't do requested format %s, falling back to peer capability %d\n", ast_getformatname(iaxs[fr->callno]->peerformat), iaxs[fr->callno]->peercapability); 08097 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 08098 } 08099 if (!format) { 08100 if (authdebug) { 08101 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 08102 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); 08103 else 08104 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); 08105 } 08106 memset(&ied0, 0, sizeof(ied0)); 08107 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 08108 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 08109 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08110 if (!iaxs[fr->callno]) { 08111 ast_mutex_unlock(&iaxsl[fr->callno]); 08112 return 1; 08113 } 08114 } else { 08115 /* Pick one... */ 08116 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08117 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 08118 format = 0; 08119 } else { 08120 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 08121 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 08122 memset(&pref, 0, sizeof(pref)); 08123 format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? 08124 iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08125 strcpy(caller_pref_buf,"disabled"); 08126 strcpy(host_pref_buf,"disabled"); 08127 } else { 08128 using_prefs = "mine"; 08129 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 08130 /* Do the opposite of what we tried above. */ 08131 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 08132 pref = iaxs[fr->callno]->prefs; 08133 } else { 08134 pref = iaxs[fr->callno]->rprefs; 08135 using_prefs = "caller"; 08136 } 08137 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 08138 } else /* if no codec_prefs IE do it the old way */ 08139 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08140 } 08141 } 08142 if (!format) { 08143 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08144 if (authdebug) { 08145 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 08146 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); 08147 else 08148 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); 08149 } 08150 memset(&ied0, 0, sizeof(ied0)); 08151 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 08152 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 08153 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08154 if (!iaxs[fr->callno]) { 08155 ast_mutex_unlock(&iaxsl[fr->callno]); 08156 return 1; 08157 } 08158 } 08159 } 08160 } 08161 if (format) { 08162 /* Authentication received */ 08163 memset(&ied1, 0, sizeof(ied1)); 08164 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 08165 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 08166 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 08167 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08168 if (option_verbose > 2) 08169 ast_verbose(VERBOSE_PREFIX_3 "Accepting AUTHENTICATED call from %s:\n" 08170 "%srequested format = %s,\n" 08171 "%srequested prefs = %s,\n" 08172 "%sactual format = %s,\n" 08173 "%shost prefs = %s,\n" 08174 "%spriority = %s\n", 08175 ast_inet_ntoa(sin.sin_addr), 08176 VERBOSE_PREFIX_4, 08177 ast_getformatname(iaxs[fr->callno]->peerformat), 08178 VERBOSE_PREFIX_4, 08179 caller_pref_buf, 08180 VERBOSE_PREFIX_4, 08181 ast_getformatname(format), 08182 VERBOSE_PREFIX_4, 08183 host_pref_buf, 08184 VERBOSE_PREFIX_4, 08185 using_prefs); 08186 08187 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08188 if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format))) 08189 iax2_destroy(fr->callno); 08190 } else { 08191 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 08192 /* If this is a TBD call, we're ready but now what... */ 08193 if (option_verbose > 2) 08194 ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 08195 } 08196 } 08197 } 08198 break; 08199 case IAX_COMMAND_DIAL: 08200 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) { 08201 ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 08202 ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s"); 08203 if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) { 08204 if (authdebug) 08205 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); 08206 memset(&ied0, 0, sizeof(ied0)); 08207 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 08208 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 08209 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08210 if (!iaxs[fr->callno]) { 08211 ast_mutex_unlock(&iaxsl[fr->callno]); 08212 return 1; 08213 } 08214 } else { 08215 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08216 if (option_verbose > 2) 08217 ast_verbose(VERBOSE_PREFIX_3 "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat); 08218 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08219 send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1); 08220 if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat))) 08221 iax2_destroy(fr->callno); 08222 } 08223 } 08224 break; 08225 case IAX_COMMAND_INVAL: 08226 iaxs[fr->callno]->error = ENOTCONN; 08227 if (option_debug) 08228 ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr->callno); 08229 iax2_destroy(fr->callno); 08230 if (option_debug) 08231 ast_log(LOG_DEBUG, "Destroying call %d\n", fr->callno); 08232 break; 08233 case IAX_COMMAND_VNAK: 08234 if (option_debug) 08235 ast_log(LOG_DEBUG, "Received VNAK: resending outstanding frames\n"); 08236 /* Force retransmission */ 08237 vnak_retransmit(fr->callno, fr->iseqno); 08238 break; 08239 case IAX_COMMAND_REGREQ: 08240 case IAX_COMMAND_REGREL: 08241 /* For security, always ack immediately */ 08242 if (delayreject) 08243 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08244 if (register_verify(fr->callno, &sin, &ies)) { 08245 if (!iaxs[fr->callno]) { 08246 ast_mutex_unlock(&iaxsl[fr->callno]); 08247 return 1; 08248 } 08249 /* Send delayed failure */ 08250 auth_fail(fr->callno, IAX_COMMAND_REGREJ); 08251 break; 08252 } 08253 if (!iaxs[fr->callno]) { 08254 ast_mutex_unlock(&iaxsl[fr->callno]); 08255 return 1; 08256 } 08257 if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 08258 ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED)) { 08259 if (f.subclass == IAX_COMMAND_REGREL) 08260 memset(&sin, 0, sizeof(sin)); 08261 if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh)) 08262 ast_log(LOG_WARNING, "Registry error\n"); 08263 if (!iaxs[fr->callno]) { 08264 ast_mutex_unlock(&iaxsl[fr->callno]); 08265 return 1; 08266 } 08267 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 08268 ast_mutex_unlock(&iaxsl[fr->callno]); 08269 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 08270 ast_mutex_lock(&iaxsl[fr->callno]); 08271 if (!iaxs[fr->callno]) { 08272 ast_mutex_unlock(&iaxsl[fr->callno]); 08273 return 1; 08274 } 08275 } 08276 break; 08277 } 08278 registry_authrequest(fr->callno); 08279 if (!iaxs[fr->callno]) { 08280 ast_mutex_unlock(&iaxsl[fr->callno]); 08281 return 1; 08282 } 08283 break; 08284 case IAX_COMMAND_REGACK: 08285 if (iax2_ack_registry(&ies, &sin, fr->callno)) 08286 ast_log(LOG_WARNING, "Registration failure\n"); 08287 /* Send ack immediately, before we destroy */ 08288 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08289 iax2_destroy(fr->callno); 08290 break; 08291 case IAX_COMMAND_REGREJ: 08292 if (iaxs[fr->callno]->reg) { 08293 if (authdebug) { 08294 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)); 08295 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nUsername: %s\r\nStatus: Rejected\r\nCause: %s\r\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : "<unknown>"); 08296 } 08297 iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED; 08298 } 08299 /* Send ack immediately, before we destroy */ 08300 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08301 iax2_destroy(fr->callno); 08302 break; 08303 case IAX_COMMAND_REGAUTH: 08304 /* Authentication request */ 08305 if (registry_rerequest(&ies, fr->callno, &sin)) { 08306 memset(&ied0, 0, sizeof(ied0)); 08307 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found"); 08308 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 08309 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08310 if (!iaxs[fr->callno]) { 08311 ast_mutex_unlock(&iaxsl[fr->callno]); 08312 return 1; 08313 } 08314 } 08315 break; 08316 case IAX_COMMAND_TXREJ: 08317 iaxs[fr->callno]->transferring = 0; 08318 if (option_verbose > 2) 08319 ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 08320 memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer)); 08321 if (iaxs[fr->callno]->bridgecallno) { 08322 if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) { 08323 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0; 08324 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 08325 } 08326 } 08327 break; 08328 case IAX_COMMAND_TXREADY: 08329 if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) || 08330 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) { 08331 if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN) 08332 iaxs[fr->callno]->transferring = TRANSFER_MREADY; 08333 else 08334 iaxs[fr->callno]->transferring = TRANSFER_READY; 08335 if (option_verbose > 2) 08336 ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 08337 if (iaxs[fr->callno]->bridgecallno) { 08338 if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) || 08339 (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) { 08340 /* They're both ready, now release them. */ 08341 if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) { 08342 if (option_verbose > 2) 08343 ast_verbose(VERBOSE_PREFIX_3 "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 08344 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 08345 08346 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA; 08347 iaxs[fr->callno]->transferring = TRANSFER_MEDIA; 08348 08349 memset(&ied0, 0, sizeof(ied0)); 08350 memset(&ied1, 0, sizeof(ied1)); 08351 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 08352 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 08353 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1); 08354 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1); 08355 } else { 08356 if (option_verbose > 2) 08357 ast_verbose(VERBOSE_PREFIX_3 "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 08358 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 08359 08360 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED; 08361 iaxs[fr->callno]->transferring = TRANSFER_RELEASED; 08362 ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE); 08363 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 08364 08365 /* Stop doing lag & ping requests */ 08366 stop_stuff(fr->callno); 08367 stop_stuff(iaxs[fr->callno]->bridgecallno); 08368 08369 memset(&ied0, 0, sizeof(ied0)); 08370 memset(&ied1, 0, sizeof(ied1)); 08371 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 08372 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 08373 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1); 08374 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1); 08375 } 08376 08377 } 08378 } 08379 } 08380 break; 08381 case IAX_COMMAND_TXREQ: 08382 try_transfer(iaxs[fr->callno], &ies); 08383 break; 08384 case IAX_COMMAND_TXCNT: 08385 if (iaxs[fr->callno]->transferring) 08386 send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0); 08387 break; 08388 case IAX_COMMAND_TXREL: 08389 /* Send ack immediately, rather than waiting until we've changed addresses */ 08390 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08391 complete_transfer(fr->callno, &ies); 08392 stop_stuff(fr->callno); /* for attended transfer to work with libiax */ 08393 break; 08394 case IAX_COMMAND_TXMEDIA: 08395 if (iaxs[fr->callno]->transferring == TRANSFER_READY) { 08396 AST_LIST_LOCK(&iaxq.queue); 08397 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 08398 /* Cancel any outstanding frames and start anew */ 08399 if ((fr->callno == cur->callno) && (cur->transfer)) { 08400 cur->retries = -1; 08401 } 08402 } 08403 AST_LIST_UNLOCK(&iaxq.queue); 08404 /* Start sending our media to the transfer address, but otherwise leave the call as-is */ 08405 iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS; 08406 } 08407 break; 08408 case IAX_COMMAND_DPREP: 08409 complete_dpreply(iaxs[fr->callno], &ies); 08410 break; 08411 case IAX_COMMAND_UNSUPPORT: 08412 ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown); 08413 break; 08414 case IAX_COMMAND_FWDOWNL: 08415 /* Firmware download */ 08416 if (!ast_test_flag(&globalflags, IAX_ALLOWFWDOWNLOAD)) { 08417 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, NULL, 0, -1); 08418 break; 08419 } 08420 memset(&ied0, 0, sizeof(ied0)); 08421 res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc); 08422 if (res < 0) 08423 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08424 else if (res > 0) 08425 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 08426 else 08427 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 08428 if (!iaxs[fr->callno]) { 08429 ast_mutex_unlock(&iaxsl[fr->callno]); 08430 return 1; 08431 } 08432 break; 08433 default: 08434 if (option_debug) 08435 ast_log(LOG_DEBUG, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno); 08436 memset(&ied0, 0, sizeof(ied0)); 08437 iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass); 08438 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1); 08439 } 08440 /* Don't actually pass these frames along */ 08441 if ((f.subclass != IAX_COMMAND_ACK) && 08442 (f.subclass != IAX_COMMAND_TXCNT) && 08443 (f.subclass != IAX_COMMAND_TXACC) && 08444 (f.subclass != IAX_COMMAND_INVAL) && 08445 (f.subclass != IAX_COMMAND_VNAK)) { 08446 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 08447 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08448 } 08449 ast_mutex_unlock(&iaxsl[fr->callno]); 08450 return 1; 08451 } 08452 /* Unless this is an ACK or INVAL frame, ack it */ 08453 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 08454 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08455 } else if (minivid) { 08456 f.frametype = AST_FRAME_VIDEO; 08457 if (iaxs[fr->callno]->videoformat > 0) 08458 f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0); 08459 else { 08460 ast_log(LOG_WARNING, "Received mini frame before first full video frame\n "); 08461 iax2_vnak(fr->callno); 08462 ast_mutex_unlock(&iaxsl[fr->callno]); 08463 return 1; 08464 } 08465 f.datalen = res - sizeof(*vh); 08466 if (f.datalen) 08467 f.data = thread->buf + sizeof(*vh); 08468 else 08469 f.data = NULL; 08470 #ifdef IAXTESTS 08471 if (test_resync) { 08472 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff); 08473 } else 08474 #endif /* IAXTESTS */ 08475 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff); 08476 } else { 08477 /* A mini frame */ 08478 f.frametype = AST_FRAME_VOICE; 08479 if (iaxs[fr->callno]->voiceformat > 0) 08480 f.subclass = iaxs[fr->callno]->voiceformat; 08481 else { 08482 if (option_debug) 08483 ast_log(LOG_DEBUG, "Received mini frame before first full voice frame\n"); 08484 iax2_vnak(fr->callno); 08485 ast_mutex_unlock(&iaxsl[fr->callno]); 08486 return 1; 08487 } 08488 f.datalen = res - sizeof(struct ast_iax2_mini_hdr); 08489 if (f.datalen < 0) { 08490 ast_log(LOG_WARNING, "Datalen < 0?\n"); 08491 ast_mutex_unlock(&iaxsl[fr->callno]); 08492 return 1; 08493 } 08494 if (f.datalen) 08495 f.data = thread->buf + sizeof(*mh); 08496 else 08497 f.data = NULL; 08498 #ifdef IAXTESTS 08499 if (test_resync) { 08500 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff); 08501 } else 08502 #endif /* IAXTESTS */ 08503 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts); 08504 /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */ 08505 } 08506 /* Don't pass any packets until we're started */ 08507 if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 08508 ast_mutex_unlock(&iaxsl[fr->callno]); 08509 return 1; 08510 } 08511 /* Common things */ 08512 f.src = "IAX2"; 08513 f.mallocd = 0; 08514 f.offset = 0; 08515 f.len = 0; 08516 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) { 08517 f.samples = ast_codec_get_samples(&f); 08518 /* We need to byteswap incoming slinear samples from network byte order */ 08519 if (f.subclass == AST_FORMAT_SLINEAR) 08520 ast_frame_byteswap_be(&f); 08521 } else 08522 f.samples = 0; 08523 iax_frame_wrap(fr, &f); 08524 08525 /* If this is our most recent packet, use it as our basis for timestamping */ 08526 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 08527 /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/ 08528 fr->outoforder = 0; 08529 } else { 08530 if (option_debug && iaxdebug && iaxs[fr->callno]) 08531 ast_log(LOG_DEBUG, "Received out of order packet... (type=%d, subclass %d, ts = %d, last = %d)\n", f.frametype, f.subclass, fr->ts, iaxs[fr->callno]->last); 08532 fr->outoforder = -1; 08533 } 08534 fr->cacheable = ((f.frametype == AST_FRAME_VOICE) || (f.frametype == AST_FRAME_VIDEO)); 08535 duped_fr = iaxfrdup2(fr); 08536 if (duped_fr) { 08537 schedule_delivery(duped_fr, updatehistory, 0, &fr->ts); 08538 } 08539 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 08540 iaxs[fr->callno]->last = fr->ts; 08541 #if 1 08542 if (option_debug && iaxdebug) 08543 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 08544 #endif 08545 } 08546 08547 /* Always run again */ 08548 ast_mutex_unlock(&iaxsl[fr->callno]); 08549 return 1; 08550 }
| static int socket_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | cbdata | |||
| ) | [static] |
Definition at line 6906 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), iax2_registry::callno, ast_iax2_full_hdr::csub, defer_full_frame(), errno, iax2_thread::ffinfo, find_idle_thread(), handle_error(), IAX_FLAG_FULL, IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, inaddrcmp(), len, LOG_DEBUG, LOG_WARNING, option_debug, ast_iax2_full_hdr::scallno, signal_condition(), t, thread, and ast_iax2_full_hdr::type.
Referenced by network_thread(), peer_set_srcaddr(), and set_config().
06907 { 06908 struct iax2_thread *thread; 06909 socklen_t len; 06910 time_t t; 06911 static time_t last_errtime = 0; 06912 struct ast_iax2_full_hdr *fh; 06913 06914 if (!(thread = find_idle_thread())) { 06915 time(&t); 06916 if (t != last_errtime && option_debug) 06917 ast_log(LOG_DEBUG, "Out of idle IAX2 threads for I/O, pausing!\n"); 06918 last_errtime = t; 06919 usleep(1); 06920 return 1; 06921 } 06922 06923 len = sizeof(thread->iosin); 06924 thread->iofd = fd; 06925 thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len); 06926 thread->buf_size = sizeof(thread->readbuf); 06927 thread->buf = thread->readbuf; 06928 if (thread->buf_len < 0) { 06929 if (errno != ECONNREFUSED && errno != EAGAIN) 06930 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); 06931 handle_error(); 06932 thread->iostate = IAX_IOSTATE_IDLE; 06933 signal_condition(&thread->lock, &thread->cond); 06934 return 1; 06935 } 06936 if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */ 06937 thread->iostate = IAX_IOSTATE_IDLE; 06938 signal_condition(&thread->lock, &thread->cond); 06939 return 1; 06940 } 06941 06942 /* Determine if this frame is a full frame; if so, and any thread is currently 06943 processing a full frame for the same callno from this peer, then drop this 06944 frame (and the peer will retransmit it) */ 06945 fh = (struct ast_iax2_full_hdr *) thread->buf; 06946 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 06947 struct iax2_thread *cur = NULL; 06948 uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL; 06949 06950 AST_LIST_LOCK(&active_list); 06951 AST_LIST_TRAVERSE(&active_list, cur, list) { 06952 if ((cur->ffinfo.callno == callno) && 06953 !inaddrcmp(&cur->ffinfo.sin, &thread->iosin)) 06954 break; 06955 } 06956 if (cur) { 06957 /* we found another thread processing a full frame for this call, 06958 so queue it up for processing later. */ 06959 defer_full_frame(thread, cur); 06960 AST_LIST_UNLOCK(&active_list); 06961 thread->iostate = IAX_IOSTATE_IDLE; 06962 signal_condition(&thread->lock, &thread->cond); 06963 return 1; 06964 } else { 06965 /* this thread is going to process this frame, so mark it */ 06966 thread->ffinfo.callno = callno; 06967 memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin)); 06968 thread->ffinfo.type = fh->type; 06969 thread->ffinfo.csub = fh->csub; 06970 } 06971 AST_LIST_UNLOCK(&active_list); 06972 } 06973 06974 /* Mark as ready and send on its way */ 06975 thread->iostate = IAX_IOSTATE_READY; 06976 #ifdef DEBUG_SCHED_MULTITHREAD 06977 ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc)); 06978 #endif 06979 signal_condition(&thread->lock, &thread->cond); 06980 06981 return 1; 06982 }
| static void spawn_dp_lookup | ( | int | callno, | |
| const char * | context, | |||
| const char * | callednum, | |||
| const char * | callerid | |||
| ) | [static] |
Definition at line 6693 of file chan_iax2.c.
References ast_calloc, ast_log(), ast_pthread_create, ast_strdup, dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, dp_lookup_thread(), and LOG_WARNING.
Referenced by socket_process().
06694 { 06695 pthread_t newthread; 06696 struct dpreq_data *dpr; 06697 pthread_attr_t attr; 06698 06699 if (!(dpr = ast_calloc(1, sizeof(*dpr)))) 06700 return; 06701 06702 pthread_attr_init(&attr); 06703 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 06704 06705 dpr->callno = callno; 06706 ast_copy_string(dpr->context, context, sizeof(dpr->context)); 06707 ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum)); 06708 if (callerid) 06709 dpr->callerid = ast_strdup(callerid); 06710 if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) { 06711 ast_log(LOG_WARNING, "Unable to start lookup thread!\n"); 06712 } 06713 06714 pthread_attr_destroy(&attr); 06715 }
| static int start_network_thread | ( | void | ) | [static] |
Definition at line 9152 of file chan_iax2.c.
References ast_calloc, ast_cond_init(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_pthread_create, ast_pthread_create_background, ast_verbose(), free, iax2_process_thread(), IAX_TYPE_POOL, iaxthreadcount, LOG_WARNING, network_thread(), option_verbose, sched_thread(), thread, and VERBOSE_PREFIX_2.
Referenced by load_module().
09153 { 09154 pthread_attr_t attr; 09155 int threadcount = 0; 09156 int x; 09157 for (x = 0; x < iaxthreadcount; x++) { 09158 struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread)); 09159 if (thread) { 09160 thread->type = IAX_TYPE_POOL; 09161 thread->threadnum = ++threadcount; 09162 ast_mutex_init(&thread->lock); 09163 ast_cond_init(&thread->cond, NULL); 09164 pthread_attr_init(&attr); 09165 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 09166 if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) { 09167 ast_log(LOG_WARNING, "Failed to create new thread!\n"); 09168 free(thread); 09169 thread = NULL; 09170 } 09171 AST_LIST_LOCK(&idle_list); 09172 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 09173 AST_LIST_UNLOCK(&idle_list); 09174 } 09175 } 09176 ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL); 09177 ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); 09178 if (option_verbose > 1) 09179 ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount); 09180 return 0; 09181 }
| static void stop_stuff | ( | int | callno | ) | [static] |
Definition at line 6375 of file chan_iax2.c.
References iax2_destroy_helper(), and iaxs.
Referenced by socket_process().
06376 { 06377 iax2_destroy_helper(iaxs[callno]); 06378 }
| static void store_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1245 of file chan_iax2.c.
References ast_log(), iax_peercallno_pvts, LOG_ERROR, and chan_iax2_pvt::peercallno.
Referenced by __find_callno(), complete_transfer(), and socket_process().
01246 { 01247 if (!pvt->peercallno) { 01248 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01249 return; 01250 } 01251 01252 ao2_link(iax_peercallno_pvts, pvt); 01253 }
| static int timing_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | cbdata | |||
| ) | [static] |
Definition at line 6562 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_inet_ntoa(), AST_IO_PRI, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, iax2_trunk_expired(), iax2_trunk_peer::lock, LOG_DEBUG, LOG_WARNING, MAX_TRUNKDATA, iax2_trunk_peer::next, option_debug, send_trunk(), tpeers, iax2_trunk_peer::trunkdataalloc, and iax2_trunk_peer::trunkdatalen.
Referenced by network_thread().
06563 { 06564 char buf[1024]; 06565 int res; 06566 struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL; 06567 int processed = 0; 06568 int totalcalls = 0; 06569 #ifdef ZT_TIMERACK 06570 int x = 1; 06571 #endif 06572 struct timeval now; 06573 if (iaxtrunkdebug) 06574 ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA); 06575 gettimeofday(&now, NULL); 06576 if (events & AST_IO_PRI) { 06577 #ifdef ZT_TIMERACK 06578 /* Great, this is a timing interface, just call the ioctl */ 06579 if (ioctl(fd, ZT_TIMERACK, &x)) { 06580 ast_log(LOG_WARNING, "Unable to acknowledge zap timer. IAX trunking will fail!\n"); 06581 usleep(1); 06582 return -1; 06583 } 06584 #endif 06585 } else { 06586 /* Read and ignore from the pseudo channel for timing */ 06587 res = read(fd, buf, sizeof(buf)); 06588 if (res < 1) { 06589 ast_log(LOG_WARNING, "Unable to read from timing fd\n"); 06590 return 1; 06591 } 06592 } 06593 /* For each peer that supports trunking... */ 06594 ast_mutex_lock(&tpeerlock); 06595 tpeer = tpeers; 06596 while(tpeer) { 06597 processed++; 06598 res = 0; 06599 ast_mutex_lock(&tpeer->lock); 06600 /* We can drop a single tpeer per pass. That makes all this logic 06601 substantially easier */ 06602 if (!drop && iax2_trunk_expired(tpeer, &now)) { 06603 /* Take it out of the list, but don't free it yet, because it 06604 could be in use */ 06605 if (prev) 06606 prev->next = tpeer->next; 06607 else 06608 tpeers = tpeer->next; 06609 drop = tpeer; 06610 } else { 06611 res = send_trunk(tpeer, &now); 06612 if (iaxtrunkdebug) 06613 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); 06614 } 06615 totalcalls += res; 06616 res = 0; 06617 ast_mutex_unlock(&tpeer->lock); 06618 prev = tpeer; 06619 tpeer = tpeer->next; 06620 } 06621 ast_mutex_unlock(&tpeerlock); 06622 if (drop) { 06623 ast_mutex_lock(&drop->lock); 06624 /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 06625 because by the time they could get tpeerlock, we've already grabbed it */ 06626 if (option_debug) 06627 ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port)); 06628 if (drop->trunkdata) { 06629 free(drop->trunkdata); 06630 drop->trunkdata = NULL; 06631 } 06632 ast_mutex_unlock(&drop->lock); 06633 ast_mutex_destroy(&drop->lock); 06634 free(drop); 06635 06636 } 06637 if (iaxtrunkdebug) 06638 ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls); 06639 iaxtrunkdebug =0; 06640 return 1; 06641 }
| static int transmit_trunk | ( | struct iax_frame * | f, | |
| struct sockaddr_in * | sin, | |||
| int | sockfd | |||
| ) | [static] |
Definition at line 2071 of file chan_iax2.c.
References ast_log(), iax_frame::data, iax_frame::datalen, errno, handle_error(), LOG_DEBUG, and option_debug.
Referenced by send_trunk().
02072 { 02073 int res; 02074 res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin, 02075 sizeof(*sin)); 02076 if (res < 0) { 02077 if (option_debug) 02078 ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno)); 02079 handle_error(); 02080 } else 02081 res = 0; 02082 return res; 02083 }
| static int try_firmware | ( | char * | s | ) | [static] |
Definition at line 1759 of file chan_iax2.c.
References ast_calloc, ast_log(), ast_random(), ast_strlen_zero(), MD5Context::buf, 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, len, LOG_WARNING, ast_iax2_firmware_header::magic, MD5Final(), MD5Init(), MD5Update(), iax_firmware::mmaplen, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.
Referenced by reload_firmware().
01760 { 01761 struct stat stbuf; 01762 struct iax_firmware *cur; 01763 int ifd; 01764 int fd; 01765 int res; 01766 01767 struct ast_iax2_firmware_header *fwh, fwh2; 01768 struct MD5Context md5; 01769 unsigned char sum[16]; 01770 unsigned char buf[1024]; 01771 int len, chunk; 01772 char *s2; 01773 char *last; 01774 s2 = alloca(strlen(s) + 100); 01775 if (!s2) { 01776 ast_log(LOG_WARNING, "Alloca failed!\n"); 01777 return -1; 01778 } 01779 last = strrchr(s, '/'); 01780 if (last) 01781 last++; 01782 else 01783 last = s; 01784 snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random()); 01785 res = stat(s, &stbuf); 01786 if (res < 0) { 01787 ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno)); 01788 return -1; 01789 } 01790 /* Make sure it's not a directory */ 01791 if (S_ISDIR(stbuf.st_mode)) 01792 return -1; 01793 ifd = open(s, O_RDONLY); 01794 if (ifd < 0) { 01795 ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno)); 01796 return -1; 01797 } 01798 fd = open(s2, O_RDWR | O_CREAT | O_EXCL, 0600); 01799 if (fd < 0) { 01800 ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno)); 01801 close(ifd); 01802 return -1; 01803 } 01804 /* Unlink our newly created file */ 01805 unlink(s2); 01806 01807 /* Now copy the firmware into it */ 01808 len = stbuf.st_size; 01809 while(len) { 01810 chunk = len; 01811 if (chunk > sizeof(buf)) 01812 chunk = sizeof(buf); 01813 res = read(ifd, buf, chunk); 01814 if (res != chunk) { 01815 ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 01816 close(ifd); 01817 close(fd); 01818 return -1; 01819 } 01820 res = write(fd, buf, chunk); 01821 if (res != chunk) { 01822 ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 01823 close(ifd); 01824 close(fd); 01825 return -1; 01826 } 01827 len -= chunk; 01828 } 01829 close(ifd); 01830 /* Return to the beginning */ 01831 lseek(fd, 0, SEEK_SET); 01832 if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) { 01833 ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s); 01834 close(fd); 01835 return -1; 01836 } 01837 if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) { 01838 ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s); 01839 close(fd); 01840 return -1; 01841 } 01842 if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) { 01843 ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s); 01844 close(fd); 01845 return -1; 01846 } 01847 if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) { 01848 ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s); 01849 close(fd); 01850 return -1; 01851 } 01852 fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 01853 if (fwh == (void *) -1) { 01854 ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno)); 01855 close(fd); 01856 return -1; 01857 } 01858 MD5Init(&md5); 01859 MD5Update(&md5, fwh->data, ntohl(fwh->datalen)); 01860 MD5Final(sum, &md5); 01861 if (memcmp(sum, fwh->chksum, sizeof(sum))) { 01862 ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s); 01863 munmap((void*)fwh, stbuf.st_size); 01864 close(fd); 01865 return -1; 01866 } 01867 cur = waresl.wares; 01868 while(cur) { 01869 if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) { 01870 /* Found a candidate */ 01871 if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version))) 01872 /* The version we have on loaded is older, load this one instead */ 01873 break; 01874 /* This version is no newer than what we have. Don't worry about it. 01875 We'll consider it a proper load anyhow though */ 01876 munmap((void*)fwh, stbuf.st_size); 01877 close(fd); 01878 return 0; 01879 } 01880 cur = cur->next; 01881 } 01882 if (!cur) { 01883 /* Allocate a new one and link it */ 01884 if ((cur = ast_calloc(1, sizeof(*cur)))) { 01885 cur->fd = -1; 01886 cur->next = waresl.wares; 01887 waresl.wares = cur; 01888 } 01889 } 01890 if (cur) { 01891 if (cur->fwh) { 01892 munmap((void*)cur->fwh, cur->mmaplen); 01893 } 01894 if (cur->fd > -1) 01895 close(cur->fd); 01896 cur->fwh = fwh; 01897 cur->fd = fd; 01898 cur->mmaplen = stbuf.st_size; 01899 cur->dead = 0; 01900 } 01901 return 0; 01902 }
| static int try_transfer | ( | struct chan_iax2_pvt * | pvt, | |
| struct iax_ies * | ies | |||
| ) | [static] |
Definition at line 5777 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(), 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().
05778 { 05779 int newcall = 0; 05780 char newip[256]; 05781 struct iax_ie_data ied; 05782 struct sockaddr_in new; 05783 05784 05785 memset(&ied, 0, sizeof(ied)); 05786 if (ies->apparent_addr) 05787 bcopy(ies->apparent_addr, &new, sizeof(new)); 05788 if (ies->callno) 05789 newcall = ies->callno; 05790 if (!newcall || !new.sin_addr.s_addr || !new.sin_port) { 05791 ast_log(LOG_WARNING, "Invalid transfer request\n"); 05792 return -1; 05793 } 05794 pvt->transfercallno = newcall; 05795 memcpy(&pvt->transfer, &new, sizeof(pvt->transfer)); 05796 inet_aton(newip, &pvt->transfer.sin_addr); 05797 pvt->transfer.sin_family = AF_INET; 05798 pvt->transferring = TRANSFER_BEGIN; 05799 pvt->transferid = ies->transferid; 05800 if (ies->transferid) 05801 iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid); 05802 send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos); 05803 return 0; 05804 }
| static int uncompress_subclass | ( | unsigned char | csub | ) | [static] |
Definition at line 1090 of file chan_iax2.c.
References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.
Referenced by decode_frame(), and socket_process().
01091 { 01092 /* If the SC_LOG flag is set, return 2^csub otherwise csub */ 01093 if (csub & IAX_FLAG_SC_LOG) { 01094 /* special case for 'compressed' -1 */ 01095 if (csub == 0xff) 01096 return -1; 01097 else 01098 return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT); 01099 } 01100 else 01101 return csub; 01102 }
| static void unlink_peer | ( | struct iax2_peer * | peer | ) | [static] |
Definition at line 6049 of file chan_iax2.c.
References ao2_unlink(), ast_sched_del(), iax2_peer::expire, peer_unref(), peers, and iax2_peer::pokeexpire.
Referenced by __expire_registry(), build_peer(), and prune_peers().
06050 { 06051 if (peer->expire > -1) { 06052 if (!ast_sched_del(sched, peer->expire)) { 06053 peer->expire = -1; 06054 peer_unref(peer); 06055 } 06056 } 06057 06058 if (peer->pokeexpire > -1) { 06059 if (!ast_sched_del(sched, peer->pokeexpire)) { 06060 peer->pokeexpire = -1; 06061 peer_unref(peer); 06062 } 06063 } 06064 06065 ao2_unlink(peers, peer); 06066 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 11077 of file chan_iax2.c.
References __unload_module(), ast_custom_function_unregister(), and iaxpeer_function.
11078 { 11079 ast_custom_function_unregister(&iaxpeer_function); 11080 return __unload_module(); 11081 }
| static void unlock_both | ( | unsigned short | callno0, | |
| unsigned short | callno1 | |||
| ) | [static] |
Definition at line 3490 of file chan_iax2.c.
References ast_mutex_unlock(), and iaxsl.
Referenced by iax2_bridge().
03491 { 03492 ast_mutex_unlock(&iaxsl[callno1]); 03493 ast_mutex_unlock(&iaxsl[callno0]); 03494 }
| static void unwrap_timestamp | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 2516 of file chan_iax2.c.
References ast_log(), iax_frame::callno, iaxs, chan_iax2_pvt::last, LOG_DEBUG, option_debug, and iax_frame::ts.
Referenced by schedule_delivery().
02517 { 02518 int x; 02519 02520 if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) { 02521 x = fr->ts - iaxs[fr->callno]->last; 02522 if (x < -50000) { 02523 /* Sudden big jump backwards in timestamp: 02524 What likely happened here is that miniframe timestamp has circled but we haven't 02525 gotten the update from the main packet. We'll just pretend that we did, and 02526 update the timestamp appropriately. */ 02527 fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF); 02528 if (option_debug && iaxdebug) 02529 ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n"); 02530 } 02531 if (x > 50000) { 02532 /* Sudden apparent big jump forwards in timestamp: 02533 What's likely happened is this is an old miniframe belonging to the previous 02534 top-16-bit timestamp that has turned up out of order. 02535 Adjust the timestamp appropriately. */ 02536 fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF); 02537 if (option_debug && iaxdebug) 02538 ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n"); 02539 } 02540 } 02541 }
| static void update_jbsched | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 2545 of file chan_iax2.c.
References AST_SCHED_DEL, chan_iax2_pvt::callno, CALLNO_TO_PTR, get_from_jb(), iax2_sched_add(), chan_iax2_pvt::jb, jb_next(), chan_iax2_pvt::jbid, and chan_iax2_pvt::rxcore.
Referenced by __get_from_jb(), and schedule_delivery().
02546 { 02547 int when; 02548 02549 when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore); 02550 02551 when = jb_next(pvt->jb) - when; 02552 02553 AST_SCHED_DEL(sched, pvt->jbid); 02554 02555 if(when <= 0) { 02556 /* XXX should really just empty until when > 0.. */ 02557 when = 1; 02558 } 02559 02560 pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno)); 02561 }
| static void update_max_nontrunk | ( | void | ) | [static] |
Definition at line 1458 of file chan_iax2.c.
References ast_log(), iaxs, LOG_DEBUG, maxnontrunkcall, option_debug, and TRUNK_CALL_START.
Referenced by __find_callno(), and make_trunk().
01459 { 01460 int max = 1; 01461 int x; 01462 /* XXX Prolly don't need locks here XXX */ 01463 for (x=1;x<TRUNK_CALL_START - 1; x++) { 01464 if (iaxs[x]) 01465 max = x + 1; 01466 } 01467 maxnontrunkcall = max; 01468 if (option_debug && iaxdebug) 01469 ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max); 01470 }
| static void update_max_trunk | ( | void | ) | [static] |
Definition at line 1265 of file chan_iax2.c.
References ARRAY_LEN, ast_log(), iaxs, LOG_DEBUG, maxtrunkcall, option_debug, and TRUNK_CALL_START.
Referenced by iax2_destroy(), and make_trunk().
01266 { 01267 int max = TRUNK_CALL_START; 01268 int x; 01269 01270 /* XXX Prolly don't need locks here XXX */ 01271 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01272 if (iaxs[x]) { 01273 max = x + 1; 01274 } 01275 } 01276 01277 maxtrunkcall = max; 01278 if (option_debug && iaxdebug) 01279 ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max); 01280 }
| static int update_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 2142 of file chan_iax2.c.
References 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, iaxs, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, iax_frame::mydcx, and iax_frame::semirand.
Referenced by __attempt_transmit().
02143 { 02144 /* Called with iaxsl lock held, and iaxs[callno] non-NULL */ 02145 struct ast_iax2_full_hdr *fh = f->data; 02146 struct ast_frame af; 02147 02148 /* if frame is encrypted. decrypt before updating it. */ 02149 if (f->encmethods) { 02150 decode_frame(&f->mydcx, fh, &af, &f->datalen); 02151 } 02152 /* Mark this as a retransmission */ 02153 fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno); 02154 /* Update iseqno */ 02155 f->iseqno = iaxs[f->callno]->iseqno; 02156 fh->iseqno = f->iseqno; 02157 02158 /* Now re-encrypt the frame */ 02159 if (f->encmethods) { 02160 encrypt_frame(&f->ecx, fh, f->semirand, &f->datalen); 02161 } 02162 return 0; 02163 }
| static int update_registry | ( | struct sockaddr_in * | sin, | |
| int | callno, | |||
| char * | devtype, | |||
| int | fd, | |||
| unsigned short | refresh | |||
| ) | [static] |
Definition at line 6160 of file chan_iax2.c.
References iax2_peer::addr, ast_app_inboxcount(), ast_db_del(), ast_db_put(), ast_device_state_changed(), 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_verbose(), iax_ie_data::buf, 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, iaxs, iaxsl, inaddrcmp(), LOG_NOTICE, LOG_WARNING, manager_event(), option_verbose, peer_ref(), peer_unref(), iax_ie_data::pos, realtime_update_peer(), register_peer_exten(), send_command_final(), iax2_peer::sockfd, and VERBOSE_PREFIX_3.
Referenced by socket_process().
06161 { 06162 /* Called from IAX thread only, with proper iaxsl lock */ 06163 struct iax_ie_data ied; 06164 struct iax2_peer *p; 06165 int msgcount; 06166 char data[80]; 06167 int version; 06168 const char *peer_name; 06169 int res = -1; 06170 06171 memset(&ied, 0, sizeof(ied)); 06172 06173 peer_name = ast_strdupa(iaxs[callno]->peer); 06174 06175 /* SLD: Another find_peer call during registration - this time when we are really updating our registration */ 06176 ast_mutex_unlock(&iaxsl[callno]); 06177 if (!(p = find_peer(peer_name, 1))) { 06178 ast_mutex_lock(&iaxsl[callno]); 06179 ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name); 06180 return -1; 06181 } 06182 ast_mutex_lock(&iaxsl[callno]); 06183 if (!iaxs[callno]) 06184 goto return_unref; 06185 06186 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) { 06187 if (sin->sin_addr.s_addr) { 06188 time_t nowtime; 06189 time(&nowtime); 06190 realtime_update_peer(peer_name, sin, nowtime); 06191 } else { 06192 realtime_update_peer(peer_name, sin, 0); 06193 } 06194 } 06195 if (inaddrcmp(&p->addr, sin)) { 06196 if (iax2_regfunk) 06197 iax2_regfunk(p->name, 1); 06198 /* Stash the IP address from which they registered */ 06199 memcpy(&p->addr, sin, sizeof(p->addr)); 06200 snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry); 06201 if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) { 06202 ast_db_put("IAX/Registry", p->name, data); 06203 if (option_verbose > 2) 06204 ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 06205 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 06206 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name); 06207 register_peer_exten(p, 1); 06208 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 06209 } else if (!ast_test_flag(p, IAX_TEMPONLY)) { 06210 if (option_verbose > 2) 06211 ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 06212 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED"); 06213 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name); 06214 register_peer_exten(p, 0); 06215 ast_db_del("IAX/Registry", p->name); 06216 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 06217 } 06218 /* Update the host */ 06219 /* Verify that the host is really there */ 06220 iax2_poke_peer(p, callno); 06221 } 06222 06223 /* Make sure our call still exists, an INVAL at the right point may make it go away */ 06224 if (!iaxs[callno]) { 06225 res = 0; 06226 goto return_unref; 06227 } 06228 06229 /* Store socket fd */ 06230 p->sockfd = fd; 06231 /* Setup the expiry */ 06232 if (p->expire > -1) { 06233 if (!ast_sched_del(sched, p->expire)) { 06234 p->expire = -1; 06235 peer_unref(p); 06236 } 06237 } 06238 /* treat an unspecified refresh interval as the minimum */ 06239 if (!refresh) 06240 refresh = min_reg_expire; 06241 if (refresh > max_reg_expire) { 06242 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 06243 p->name, max_reg_expire, refresh); 06244 p->expiry = max_reg_expire; 06245 } else if (refresh < min_reg_expire) { 06246 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 06247 p->name, min_reg_expire, refresh); 06248 p->expiry = min_reg_expire; 06249 } else { 06250 p->expiry = refresh; 06251 } 06252 if (p->expiry && sin->sin_addr.s_addr) { 06253 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 06254 if (p->expire == -1) 06255 peer_unref(p); 06256 } 06257 iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name); 06258 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag)); 06259 if (sin->sin_addr.s_addr) { 06260 iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry); 06261 iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr); 06262 if (!ast_strlen_zero(p->mailbox)) { 06263 int new, old; 06264 ast_app_inboxcount(p->mailbox, &new, &old); 06265 if (new > 255) 06266 new = 255; 06267 if (old > 255) 06268 old = 255; 06269 msgcount = (old << 8) | new; 06270 iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount); 06271 } 06272 if (ast_test_flag(p, IAX_HASCALLERID)) { 06273 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num); 06274 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name); 06275 } 06276 } 06277 version = iax_check_version(devtype); 06278 if (version) 06279 iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version); 06280 06281 res = 0; 06282 06283 return_unref: 06284 peer_unref(p); 06285 06286 return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1); 06287 }
| static int user_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1137 of file chan_iax2.c.
Referenced by load_module().
01138 { 01139 struct iax2_user *user = obj, *user2 = arg; 01140 01141 return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0; 01142 }
| static int user_delme_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 9792 of file chan_iax2.c.
References ast_set_flag, and IAX_DELME.
Referenced by delete_users().
09793 { 09794 struct iax2_user *user = obj; 09795 09796 ast_set_flag(user, IAX_DELME); 09797 09798 return 0; 09799 }
| static void user_destructor | ( | void * | obj | ) | [static] |
Definition at line 9556 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().
09557 { 09558 struct iax2_user *user = obj; 09559 09560 ast_free_ha(user->ha); 09561 free_context(user->contexts); 09562 if(user->vars) { 09563 ast_variables_destroy(user->vars); 09564 user->vars = NULL; 09565 } 09566 ast_string_field_free_memory(user); 09567 }
| static int user_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1127 of file chan_iax2.c.
References ast_str_hash().
Referenced by load_module().
01128 { 01129 const struct iax2_user *user = obj; 01130 01131 return ast_str_hash(user->name); 01132 }
Definition at line 1176 of file chan_iax2.c.
References ao2_ref().
01177 { 01178 ao2_ref(user, +1); 01179 return user; 01180 }
Definition at line 1182 of file chan_iax2.c.
References ao2_ref().
Referenced by authenticate_request(), authenticate_verify(), build_user(), check_access(), iax2_destroy_helper(), iax2_show_users(), prune_users(), and set_config().
01183 { 01184 ao2_ref(user, -1); 01185 return NULL; 01186 }
| static void vnak_retransmit | ( | int | callno, | |
| int | last | |||
| ) | [static] |
Definition at line 6476 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax_frame::callno, f, iaxq, iaxs, iax_frame::oseqno, iax_frame::retries, and send_packet().
Referenced by socket_process().
06477 { 06478 struct iax_frame *f; 06479 06480 AST_LIST_LOCK(&iaxq.queue); 06481 AST_LIST_TRAVERSE(&iaxq.queue, f, list) { 06482 /* Send a copy immediately */ 06483 if ((f->callno == callno) && iaxs[f->callno] && 06484 ((unsigned char ) (f->oseqno - last) < 128) && 06485 (f->retries >= 0)) { 06486 send_packet(f); 06487 } 06488 } 06489 AST_LIST_UNLOCK(&iaxq.queue); 06490 }
char accountcode[AST_MAX_ACCOUNT_CODE] [static] |
Definition at line 218 of file chan_iax2.c.
Referenced by __oh323_new(), ast_cdr_setaccount(), ast_channel_alloc(), begin_dial(), check_user_full(), disa_exec(), features_call(), gtalk_new(), local_call(), sip_new(), tds_log(), wait_for_answer(), and zt_new().
int adsi = 0 [static] |
Definition at line 222 of file chan_iax2.c.
int amaflags = 0 [static] |
Definition at line 221 of file chan_iax2.c.
int authdebug = 1 [static] |
Definition at line 158 of file chan_iax2.c.
int autokill = 0 [static] |
Definition at line 159 of file chan_iax2.c.
struct ast_cli_entry cli_iax2[] [static] |
struct ast_cli_entry cli_iax2_jb_debug_deprecated [static] |
Initial value:
{
{ "iax2", "jb", "debug", NULL },
iax2_do_jb_debug, NULL,
NULL }
Definition at line 10873 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_no_debug_deprecated [static] |
Initial value:
{
{ "iax2", "no", "debug", NULL },
iax2_no_debug, NULL,
NULL }
Definition at line 10878 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_no_jb_debug_deprecated [static] |
Initial value:
{
{ "iax2", "no", "jb", "debug", NULL },
iax2_no_jb_debug, NULL,
NULL }
Definition at line 10888 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_no_trunk_debug_deprecated [static] |
Initial value:
{
{ "iax2", "no", "trunk", "debug", NULL },
iax2_no_trunk_debug, NULL,
NULL }
Definition at line 10883 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_trunk_debug_deprecated [static] |
Initial value:
{
{ "iax2", "trunk", "debug", NULL },
iax2_do_trunk_debug, NULL,
NULL }
Definition at line 10868 of file chan_iax2.c.
char context[80] = "default" [static] |
Definition at line 145 of file chan_iax2.c.
char debug_jb_usage[] [static] |
Initial value:
"Usage: iax2 set debug jb\n" " Enables jitterbuffer debugging information\n"
Definition at line 10842 of file chan_iax2.c.
char debug_trunk_usage[] [static] |
Initial value:
"Usage: iax2 set debug trunk\n" " Requests current status of IAX trunking\n"
Definition at line 10834 of file chan_iax2.c.
char debug_usage[] [static] |
Initial value:
"Usage: iax2 set debug\n" " Enables dumping of IAX packets for debugging purposes\n"
Definition at line 10826 of file chan_iax2.c.
int defaultsockfd = -1 [static] |
Definition at line 175 of file chan_iax2.c.
int delayreject = 0 [static] |
Definition at line 223 of file chan_iax2.c.
struct iax2_dpcache * dpcache [static] |
Referenced by find_cache(), and iax2_show_cache().
int global_rtautoclear = 120 [static] |
Definition at line 277 of file chan_iax2.c.
struct ast_flags globalflags = { 0 } [static] |
Definition at line 226 of file chan_iax2.c.
Referenced by find_or_create(), find_user(), find_user_realtime(), forward_message(), load_config(), make_email_file(), notify_new_message(), populate_defaults(), sendmail(), and vm_execmain().
int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static] |
Definition at line 204 of file chan_iax2.c.
int iax2_encryption = 0 [static] |
Definition at line 224 of file chan_iax2.c.
| enum { ... } iax2_flags |
| int(* iax2_regfunk)(const char *username, int onoff) = NULL |
Referenced by __expire_registry(), reg_source_db(), and update_registry().
char iax2_reload_usage[] [static] |
Initial value:
"Usage: iax2 reload\n" " Reloads IAX configuration from iax.conf\n"
Definition at line 10784 of file chan_iax2.c.
| enum { ... } iax2_state |
struct ast_switch iax2_switch [static] |
struct ast_channel_tech iax2_tech [static] |
Definition at line 872 of file chan_iax2.c.
Referenced by __unload_module(), ast_iax2_new(), function_iaxpeer(), iax2_bridge(), iax2_prov_app(), and load_module().
char iax2_test_losspct_usage[] [static] |
Initial value:
"Usage: iax2 test losspct <percentage>\n" " For testing, throws away <percentage> percent of incoming packets\n"
Definition at line 10850 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 827 of file chan_iax2.c.
Referenced by __find_callno(), __unload_module(), load_module(), remove_by_peercallno(), and store_by_peercallno().
int iaxactivethreadcount = 0 [static] |
Definition at line 453 of file chan_iax2.c.
Referenced by __unload_module(), iax2_process_thread(), and iax2_process_thread_cleanup().
int iaxcompat = 0 [static] |
Definition at line 160 of file chan_iax2.c.
int iaxdebug = 0 [static] |
Definition at line 206 of file chan_iax2.c.
int iaxdefaultdpcache = 10 * 60 [static] |
Definition at line 162 of file chan_iax2.c.
int iaxdefaulttimeout = 5 [static] |
Definition at line 164 of file chan_iax2.c.
int iaxdynamicthreadcount = 0 [static] |
Definition at line 452 of file chan_iax2.c.
Referenced by find_idle_thread(), and iax2_process_thread().
int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static] |
struct ast_iax2_queue iaxq [static] |
struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static] |
Definition at line 814 of file chan_iax2.c.
Referenced by __attempt_transmit(), __auth_reject(), __auto_congest(), __auto_hangup(), __do_deliver(), __find_callno(), __get_from_jb(), __send_lagrq(), __send_ping(), __unload_module(), ast_cli_netstats(), ast_iax2_new(), auth_fail(), auth_reject(), authenticate_reply(), authenticate_request(), auto_hangup(), cache_get_callno_locked(), calc_timestamp(), check_access(), complete_transfer(), decrypt_frame(), delete_users(), dp_lookup(), find_cache(), fix_peerts(), function_iaxpeer(), iax2_ack_registry(), iax2_bridge(), iax2_call(), iax2_destroy(), iax2_do_register(), iax2_dprequest(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_poke_peer(), iax2_predestroy(), iax2_prov_app(), iax2_provision(), iax2_queue_control_data(), iax2_queue_frame(), iax2_queue_hangup(), iax2_request(), iax2_show_channels(), iax2_start_transfer(), iax2_vnak(), iax2_write(), iax_showframe(), load_module(), make_trunk(), network_thread(), register_verify(), registry_authrequest(), registry_rerequest(), save_rr(), schedule_delivery(), send_command_final(), send_command_locked(), send_packet(), socket_process(), stop_stuff(), unwrap_timestamp(), update_max_nontrunk(), update_max_trunk(), update_packet(), update_registry(), and vnak_retransmit().
ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static] |
Definition at line 815 of file chan_iax2.c.
Referenced by __attempt_transmit(), __auth_reject(), __auto_congest(), __auto_hangup(), __find_callno(), __get_from_jb(), __iax2_poke_noanswer(), __send_lagrq(), __send_ping(), __unload_module(), ast_cli_netstats(), ast_iax2_new(), auth_reject(), authenticate_reply(), auto_hangup(), cache_get_callno_locked(), delete_users(), dp_lookup(), find_cache(), iax2_bridge(), iax2_call(), iax2_destroy(), iax2_do_register(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_poke_peer(), iax2_provision(), iax2_queue_control_data(), iax2_queue_frame(), iax2_queue_hangup(), iax2_request(), iax2_show_channels(), iax2_write(), load_module(), lock_both(), make_trunk(), network_thread(), peer_destructor(), register_verify(), registry_authrequest(), send_command_locked(), socket_process(), unlock_both(), and update_registry().
int iaxthreadcount = DEFAULT_THREAD_COUNT [static] |
Definition at line 450 of file chan_iax2.c.
Referenced by iax2_show_threads(), set_config(), and start_network_thread().
int iaxtrunkdebug = 0 [static] |
Definition at line 208 of file chan_iax2.c.
struct io_context* io [static] |
Definition at line 201 of file chan_iax2.c.
int lagrq_time = 10 [static] |
Definition at line 153 of file chan_iax2.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 147 of file chan_iax2.c.
Definition at line 816 of file chan_iax2.c.
Referenced by __find_callno(), iax2_destroy(), and make_trunk().
int max_reg_expire [static] |
Definition at line 169 of file chan_iax2.c.
int max_retries = 4 [static] |
Definition at line 151 of file chan_iax2.c.
int maxauthreq = 3 [static] |
Definition at line 150 of file chan_iax2.c.
int maxjitterbuffer = 1000 [static] |
Definition at line 154 of file chan_iax2.c.
int maxjitterinterps = 10 [static] |
Definition at line 156 of file chan_iax2.c.
int maxnontrunkcall = 1 [static] |
Definition at line 834 of file chan_iax2.c.
Referenced by __find_callno(), and update_max_nontrunk().
int maxtrunkcall = TRUNK_CALL_START [static] |
int min_reg_expire [static] |
Definition at line 168 of file chan_iax2.c.
char mohinterpret[MAX_MUSICCLASS] [static] |
Definition at line 219 of file chan_iax2.c.
char mohsuggest[MAX_MUSICCLASS] [static] |
Definition at line 220 of file chan_iax2.c.
Referenced by check_user_full(), create_addr_from_peer(), and sip_alloc().
struct ast_netsock_list* netsock [static] |
Definition at line 173 of file chan_iax2.c.
pthread_t netthreadid = AST_PTHREADT_NULL [static] |
Definition at line 228 of file chan_iax2.c.
char no_debug_jb_usage[] [static] |
Initial value:
"Usage: iax2 set debug jb off\n" " Disables jitterbuffer debugging information\n"
Definition at line 10846 of file chan_iax2.c.
char no_debug_trunk_usage[] [static] |
Initial value:
"Usage: iax2 set debug trunk off\n" " Requests current status of IAX trunking\n"
Definition at line 10838 of file chan_iax2.c.
char no_debug_usage[] [static] |
Initial value:
"Usage: iax2 set debug off\n" " Disables dumping of IAX packets for debugging purposes\n"
Definition at line 10830 of file chan_iax2.c.
struct ast_netsock_list* outsock [static] |
used if sourceaddress specified and bindaddr == INADDR_ANY
Definition at line 174 of file chan_iax2.c.
char* papp = "IAX2Provision" [static] |
char* pdescrip [static] |
Initial value:
" 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 8801 of file chan_iax2.c.
Referenced by load_module().
struct ao2_container* peers [static] |
Definition at line 652 of file chan_iax2.c.
Referenced by __iax2_show_peers(), __unload_module(), abort_request(), authenticate_reply(), build_peer(), build_transactions(), cancel_request(), chanavail_exec(), check_request(), complete_iax2_show_peer(), complete_peer_helper(), delete_users(), destroy_trans(), discover_transactions(), dundi_flush(), dundi_ie_append_eid_appropriately(), dundi_lookup_thread(), dundi_precache_internal(), dundi_precache_thread(), dundi_query_thread(), dundi_rexmit(), dundi_show_entityid(), dundi_show_mappings(), dundi_show_peer(), dundi_show_peers(), dundi_show_requests(), dundi_show_trans(), find_peer(), handle_command_response(), iax2_getpeername(), iax2_getpeertrunk(), load_module(), mark_mappings(), mark_peers(), network_thread(), optimize_transactions(), poke_all_peers(), precache_transactions(), prune_mappings(), prune_peers(), query_transactions(), realtime_peer(), register_request(), set_config(), socket_read(), unlink_peer(), and unregister_request().
int ping_time = 21 [static] |
Definition at line 152 of file chan_iax2.c.
struct ast_codec_pref prefs [static] |
Definition at line 141 of file chan_iax2.c.
Referenced by ast_best_codec(), build_peer(), build_user(), check_access(), create_addr(), new_iax(), and set_config().
char prune_realtime_usage[] [static] |
Initial value:
"Usage: iax2 prune realtime [<peername>|all]\n" " Prunes object(s) from the cache\n"
Definition at line 10780 of file chan_iax2.c.
char* psyn = "Provision a calling IAXy with a given template" [static] |
char regcontext[AST_MAX_CONTEXT] = "" [static] |
Definition at line 148 of file chan_iax2.c.
int resyncthreshold = 1000 [static] |
Definition at line 155 of file chan_iax2.c.
struct sched_context* sched [static] |
Definition at line 202 of file chan_iax2.c.
ast_cond_t sched_cond [static] |
Definition at line 231 of file chan_iax2.c.
pthread_t schedthreadid = AST_PTHREADT_NULL [static] |
Definition at line 229 of file chan_iax2.c.
char show_cache_usage[] [static] |
Initial value:
"Usage: iax2 show cache\n" " Display currently cached IAX Dialplan results.\n"
Definition at line 10772 of file chan_iax2.c.
char show_channels_usage[] [static] |
Initial value:
"Usage: iax2 show channels\n" " Lists all currently active IAX channels.\n"
Definition at line 10800 of file chan_iax2.c.
char show_firmware_usage[] [static] |
Initial value:
"Usage: iax2 show firmware\n" " Lists all known IAX firmware images.\n"
Definition at line 10818 of file chan_iax2.c.
char show_netstats_usage[] [static] |
Initial value:
"Usage: iax2 show netstats\n" " Lists network status for all currently active IAX channels.\n"
Definition at line 10804 of file chan_iax2.c.
char show_peer_usage[] [static] |
Initial value:
"Usage: iax2 show peer <name>\n" " Display details on specific IAX peer\n"
Definition at line 10776 of file chan_iax2.c.
char show_peers_usage[] [static] |
Initial value:
"Usage: iax2 show peers [registered] [like <pattern>]\n" " Lists all known IAX2 peers.\n" " Optional 'registered' argument lists only peers with known addresses.\n" " Optional regular expression pattern is used to filter the peer list.\n"
Definition at line 10812 of file chan_iax2.c.
char show_prov_usage[] [static] |
Definition at line 10788 of file chan_iax2.c.
char show_reg_usage[] [static] |
Initial value:
"Usage: iax2 show registry\n" " Lists all registration requests and status.\n"
Definition at line 10822 of file chan_iax2.c.
char show_stats_usage[] [static] |
Initial value:
"Usage: iax2 show stats\n" " Display statistics on IAX channel driver.\n"
Definition at line 10768 of file chan_iax2.c.
char show_threads_usage[] [static] |
Initial value:
"Usage: iax2 show threads\n" " Lists status of IAX helper threads\n"
Definition at line 10808 of file chan_iax2.c.
char show_users_usage[] [static] |
Initial value:
"Usage: iax2 show users [like <pattern>]\n" " Lists all known IAX2 users.\n" " Optional regular expression pattern is used to filter the user list.\n"
Definition at line 10795 of file chan_iax2.c.
const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)" [static] |
Definition at line 143 of file chan_iax2.c.
int test_losspct = 0 [static] |
Definition at line 210 of file chan_iax2.c.
int timingfd = -1 [static] |
Definition at line 171 of file chan_iax2.c.
unsigned int tos = 0 [static] |
Definition at line 166 of file chan_iax2.c.
struct iax2_trunk_peer * tpeers [static] |
Referenced by find_tpeer(), and timing_read().
int trunkfreq = 20 [static] |
Definition at line 157 of file chan_iax2.c.
struct ao2_container* users [static] |
Definition at line 655 of file chan_iax2.c.
Referenced by __unload_module(), ast_get_manager_by_name_locked(), authenticate_request(), authenticate_verify(), build_user(), check_access(), complete_voicemail_show_users(), delete_users(), find_or_create(), find_user(), handle_showmanager(), handle_showmanagers(), handle_voicemail_show_users(), iax2_destroy_helper(), iax2_show_users(), init_manager(), load_config(), load_module(), prune_users(), realtime_user(), reset_user_pw(), and set_config().
struct ast_firmware_list waresl [static] |
Referenced by __unload_module(), iax2_show_firmware(), iax_check_version(), iax_firmware_append(), load_module(), reload_firmware(), and try_firmware().
1.5.8