Tue Nov 4 13:20:28 2008

Asterisk developer's documentation


chan_iax2.c File Reference

Implementation of Inter-Asterisk eXchange Version 2. More...

#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_channelast_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, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx)
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_contextbuild_context (char *context)
static void build_enc_keys (const unsigned char *digest, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx)
static struct iax2_peerbuild_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly)
 Create peer structure based on configuration.
static struct iax2_userbuild_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_dpcachefind_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_threadfind_idle_thread (void)
static struct iax2_peerfind_peer (const char *name, int realtime)
static struct iax2_trunk_peerfind_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_frameiax2_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_channeliax2_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_frameiaxfrdup2 (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_pvtnew_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_peerpeer_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_peerpeer_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_peerrealtime_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_userrealtime_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_useruser_ref (struct iax2_user *user)
static struct iax2_useruser_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_dpcachedpcache
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_containeriax_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
ast_custom_function iaxpeer_function
static struct ast_iax2_queue iaxq
static struct chan_iax2_pvtiaxs [IAX_MAX_CALLS]
static ast_mutex_t iaxsl [ARRAY_LEN(iaxs)]
static int iaxthreadcount = DEFAULT_THREAD_COUNT
static int iaxtrunkdebug = 0
static struct io_contextio
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_listnetsock
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_listoutsock
static char * papp = "IAX2Provision"
static char * pdescrip
static struct ao2_containerpeers
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_contextsched
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_peertpeers
static int trunkfreq = 20
static struct ao2_containerusers
static struct ast_firmware_list waresl


Detailed Description

Implementation of Inter-Asterisk eXchange Version 2.

Author:
Mark Spencer <markster@digium.com>
See also

Definition in file chan_iax2.c.


Define Documentation

#define CACHE_FLAG_CANEXIST   (1 << 2)

Extension can exist

Definition at line 662 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 658 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 672 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 660 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 664 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 666 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

Definition at line 668 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 670 of file chan_iax2.c.

Referenced by complete_dpreply(), and iax2_show_cache().

#define CALLNO_TO_PTR (  )     ((void *)(unsigned long)(a))

Definition at line 123 of file chan_iax2.c.

Referenced by ast_iax2_new(), iax2_call(), and update_jbsched().

#define DEBUG_SCHED_MULTITHREAD

Definition at line 111 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 131 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 129 of file chan_iax2.c.

#define DEFAULT_FREQ_NOTOK   10 * 1000

Definition at line 196 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 195 of file chan_iax2.c.

Referenced by build_peer(), and handle_response_peerpoke().

#define DEFAULT_MAX_THREAD_COUNT   100

Definition at line 126 of file chan_iax2.c.

#define DEFAULT_MAXMS   2000

Definition at line 194 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

Definition at line 127 of file chan_iax2.c.

Referenced by __find_callno(), and complete_transfer().

#define DEFAULT_THREAD_COUNT   10

Definition at line 125 of file chan_iax2.c.

#define DEFAULT_TRUNKDATA   640 * 10

40ms, uncompressed linear * 10 channels

Definition at line 439 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 136 of file chan_iax2.c.

#define IAX2_TRUNK_PREFACE   (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr))

Definition at line 360 of file chan_iax2.c.

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF

Definition at line 177 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 185 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 190 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 179 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 693 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 695 of file chan_iax2.c.

#define IAX_IOSTATE_READY   1

Definition at line 694 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 696 of file chan_iax2.c.

Referenced by __schedule_action().

#define IAX_TYPE_DYNAMIC   2

Definition at line 699 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

Definition at line 698 of file chan_iax2.c.

Referenced by start_network_thread().

#define IPTOS_MINCOST   0x02

Definition at line 114 of file chan_iax2.c.

#define MAX_JITTER_BUFFER   50

Definition at line 436 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 644 of file chan_iax2.c.

Referenced by load_module(), and set_config().

#define MAX_RETRY_TIME   10000

Definition at line 434 of file chan_iax2.c.

Referenced by __attempt_transmit(), and iax2_send().

#define MAX_TIMESTAMP_SKEW   160

maximum difference between actual and predicted ts for sending

Definition at line 442 of file chan_iax2.c.

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 440 of file chan_iax2.c.

Referenced by iax2_trunk_queue(), and timing_read().

#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS

Definition at line 649 of file chan_iax2.c.

Referenced by load_module().

#define MEMORY_SIZE   100

Definition at line 128 of file chan_iax2.c.

#define MIN_JITTER_BUFFER   10

Definition at line 437 of file chan_iax2.c.

#define MIN_RETRY_TIME   100

Definition at line 433 of file chan_iax2.c.

Referenced by iax2_send().

#define MIN_REUSE_TIME   60

Definition at line 133 of file chan_iax2.c.

Referenced by __find_callno(), and make_trunk().

#define NEW_ALLOW   1

Definition at line 1426 of file chan_iax2.c.

Referenced by __find_callno(), and socket_process().

#define NEW_FORCE   2

Definition at line 1427 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

Definition at line 1425 of file chan_iax2.c.

Referenced by socket_process().

#define PTR_TO_CALLNO (  )     ((unsigned short)(unsigned long)(a))

Definition at line 122 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 107 of file chan_iax2.c.

#define schedule_action ( func,
data   )     __schedule_action(func, data, __PRETTY_FUNCTION__)

Definition at line 980 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 826 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 445 of file chan_iax2.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
IAX_STATE_STARTED 
IAX_STATE_AUTHENTICATED 
IAX_STATE_TBD 
IAX_STATE_UNCHANGED 

Definition at line 230 of file chan_iax2.c.

00230      {
00231    IAX_STATE_STARTED =     (1 << 0),
00232    IAX_STATE_AUTHENTICATED =  (1 << 1),
00233    IAX_STATE_TBD =      (1 << 2),
00234    IAX_STATE_UNCHANGED =      (1 << 3),
00235 } iax2_state;

anonymous enum

Enumerator:
IAX_HASCALLERID  CallerID has been specified
IAX_DELME  Needs to be deleted
IAX_TEMPONLY  Temporary (realtime)
IAX_TRUNK  Treat as a trunk
IAX_NOTRANSFER  Don't native bridge
IAX_USEJITTERBUF  Use jitter buffer
IAX_DYNAMIC  dynamic peer
IAX_SENDANI  Send ANI along with CallerID
IAX_ALREADYGONE  Already disconnected
IAX_PROVISION  This is a provisioning request
IAX_QUELCH  Whether or not we quelch audio
IAX_ENCRYPTED  Whether we should assume encrypted tx/rx
IAX_KEYPOPULATED  Whether we have a key populated
IAX_CODEC_USER_FIRST  are we willing to let the other guy choose the codec?
IAX_CODEC_NOPREFS  Force old behaviour by turning off prefs
IAX_CODEC_NOCAP  only consider requested format and ignore capabilities
IAX_RTCACHEFRIENDS  let realtime stay till your reload
IAX_RTUPDATE  Send a realtime update
IAX_RTAUTOCLEAR  erase me on expire
IAX_FORCEJITTERBUF  Force jitterbuffer, even when bridged to a channel that can take jitter
IAX_RTIGNOREREGEXPIRE  When using realtime, ignore registration expiration
IAX_TRUNKTIMESTAMPS  Send trunk timestamps
IAX_TRANSFERMEDIA  When doing IAX2 transfers, transfer media only
IAX_MAXAUTHREQ  Maximum outstanding AUTHREQ restriction is in place
IAX_DELAYPBXSTART  Don't start a PBX on the channel until the peer sends us a response, so that we've achieved a three-way handshake with them before sending voice or anything else
IAX_ALLOWFWDOWNLOAD  Allow the FWDOWNL command?

Definition at line 242 of file chan_iax2.c.

00242      {
00243    IAX_HASCALLERID =    (1 << 0),   /*!< CallerID has been specified */
00244    IAX_DELME =    (1 << 1),   /*!< Needs to be deleted */
00245    IAX_TEMPONLY =    (1 << 2),   /*!< Temporary (realtime) */
00246    IAX_TRUNK =    (1 << 3),   /*!< Treat as a trunk */
00247    IAX_NOTRANSFER =  (1 << 4),   /*!< Don't native bridge */
00248    IAX_USEJITTERBUF =   (1 << 5),   /*!< Use jitter buffer */
00249    IAX_DYNAMIC =     (1 << 6),   /*!< dynamic peer */
00250    IAX_SENDANI =     (1 << 7),   /*!< Send ANI along with CallerID */
00251         /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */
00252    IAX_ALREADYGONE = (1 << 9),   /*!< Already disconnected */
00253    IAX_PROVISION =      (1 << 10),  /*!< This is a provisioning request */
00254    IAX_QUELCH =      (1 << 11),  /*!< Whether or not we quelch audio */
00255    IAX_ENCRYPTED =      (1 << 12),  /*!< Whether we should assume encrypted tx/rx */
00256    IAX_KEYPOPULATED =   (1 << 13),  /*!< Whether we have a key populated */
00257    IAX_CODEC_USER_FIRST =  (1 << 14),  /*!< are we willing to let the other guy choose the codec? */
00258    IAX_CODEC_NOPREFS =     (1 << 15),  /*!< Force old behaviour by turning off prefs */
00259    IAX_CODEC_NOCAP =    (1 << 16),  /*!< only consider requested format and ignore capabilities*/
00260    IAX_RTCACHEFRIENDS =    (1 << 17),  /*!< let realtime stay till your reload */
00261    IAX_RTUPDATE =       (1 << 18),  /*!< Send a realtime update */
00262    IAX_RTAUTOCLEAR =    (1 << 19),  /*!< erase me on expire */ 
00263    IAX_FORCEJITTERBUF = (1 << 20),  /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */ 
00264    IAX_RTIGNOREREGEXPIRE = (1 << 21),  /*!< When using realtime, ignore registration expiration */
00265    IAX_TRUNKTIMESTAMPS =   (1 << 22),  /*!< Send trunk timestamps */
00266    IAX_TRANSFERMEDIA =  (1 << 23),      /*!< When doing IAX2 transfers, transfer media only */
00267    IAX_MAXAUTHREQ =        (1 << 24),      /*!< Maximum outstanding AUTHREQ restriction is in place */
00268    IAX_DELAYPBXSTART =  (1 << 25),  /*!< Don't start a PBX on the channel until the peer sends us a
00269                        response, so that we've achieved a three-way handshake with
00270                        them before sending voice or anything else*/
00271    IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */
00272 } iax2_flags;

enum iax_reg_state

Enumerator:
REG_STATE_UNREGISTERED 
REG_STATE_REGSENT 
REG_STATE_AUTHSENT 
REG_STATE_REGISTERED 
REG_STATE_REJECTED 
REG_STATE_TIMEOUT 
REG_STATE_NOAUTH 

Definition at line 391 of file chan_iax2.c.

enum iax_transfer_state

Enumerator:
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 401 of file chan_iax2.c.


Function Documentation

static void __attempt_transmit ( const void *  data  )  [static]

Definition at line 2146 of file chan_iax2.c.

References AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, chan_iax2_pvt::error, f, 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, ast_format::name, chan_iax2_pvt::owner, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), send_packet(), ast_frame::subclass, update_packet(), and iax2_registry::us.

Referenced by attempt_transmit().

02147 {
02148    /* Attempt to transmit the frame to the remote peer...
02149       Called without iaxsl held. */
02150    struct iax_frame *f = (struct iax_frame *)data;
02151    int freeme=0;
02152    int callno = f->callno;
02153    /* Make sure this call is still active */
02154    if (callno) 
02155       ast_mutex_lock(&iaxsl[callno]);
02156    if (callno && iaxs[callno]) {
02157       if ((f->retries < 0) /* Already ACK'd */ ||
02158           (f->retries >= max_retries) /* Too many attempts */) {
02159             /* Record an error if we've transmitted too many times */
02160             if (f->retries >= max_retries) {
02161                if (f->transfer) {
02162                   /* Transfer timeout */
02163                   send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
02164                } else if (f->final) {
02165                   if (f->final) 
02166                      iax2_destroy(callno);
02167                } else {
02168                   if (iaxs[callno]->owner)
02169                      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);
02170                   iaxs[callno]->error = ETIMEDOUT;
02171                   if (iaxs[callno]->owner) {
02172                      struct ast_frame fr = { 0, };
02173                      /* Hangup the fd */
02174                      fr.frametype = AST_FRAME_CONTROL;
02175                      fr.subclass = AST_CONTROL_HANGUP;
02176                      iax2_queue_frame(callno, &fr); // XXX
02177                      /* Remember, owner could disappear */
02178                      if (iaxs[callno] && iaxs[callno]->owner)
02179                         iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
02180                   } else {
02181                      if (iaxs[callno]->reg) {
02182                         memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us));
02183                         iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT;
02184                         iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE;
02185                      }
02186                      iax2_destroy(callno);
02187                   }
02188                }
02189 
02190             }
02191             freeme++;
02192       } else {
02193          /* Update it if it needs it */
02194          update_packet(f);
02195          /* Attempt transmission */
02196          send_packet(f);
02197          f->retries++;
02198          /* Try again later after 10 times as long */
02199          f->retrytime *= 10;
02200          if (f->retrytime > MAX_RETRY_TIME)
02201             f->retrytime = MAX_RETRY_TIME;
02202          /* Transfer messages max out at one second */
02203          if (f->transfer && (f->retrytime > 1000))
02204             f->retrytime = 1000;
02205          f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
02206       }
02207    } else {
02208       /* Make sure it gets freed */
02209       f->retries = -1;
02210       freeme++;
02211    }
02212    if (callno)
02213       ast_mutex_unlock(&iaxsl[callno]);
02214    /* Do not try again */
02215    if (freeme) {
02216       /* Don't attempt delivery, just remove it from the queue */
02217       AST_LIST_LOCK(&iaxq.queue);
02218       AST_LIST_REMOVE(&iaxq.queue, f, list);
02219       iaxq.count--;
02220       AST_LIST_UNLOCK(&iaxq.queue);
02221       f->retrans = -1;
02222       /* Free the IAX frame */
02223       iax2_frame_free(f);
02224    }
02225 }

static void __auth_reject ( const void *  nothing  )  [static]

Definition at line 6344 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_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, and send_command_final().

Referenced by auth_reject().

06345 {
06346    /* Called from IAX thread only, without iaxs lock */
06347    int callno = (int)(long)(nothing);
06348    struct iax_ie_data ied;
06349    ast_mutex_lock(&iaxsl[callno]);
06350    if (iaxs[callno]) {
06351       memset(&ied, 0, sizeof(ied));
06352       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
06353          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
06354          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
06355       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
06356          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
06357          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
06358       }
06359       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
06360    }
06361    ast_mutex_unlock(&iaxsl[callno]);
06362 }

static void __auto_congest ( const void *  nothing  )  [static]

Definition at line 3101 of file chan_iax2.c.

References AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), f, iax2_queue_frame(), iaxs, iaxsl, chan_iax2_pvt::initid, LOG_NOTICE, and PTR_TO_CALLNO.

Referenced by auto_congest().

03102 {
03103    int callno = PTR_TO_CALLNO(nothing);
03104    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
03105    ast_mutex_lock(&iaxsl[callno]);
03106    if (iaxs[callno]) {
03107       iaxs[callno]->initid = -1;
03108       iax2_queue_frame(callno, &f);
03109       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
03110    }
03111    ast_mutex_unlock(&iaxsl[callno]);
03112 }

static void __auto_hangup ( const void *  nothing  )  [static]

Definition at line 6393 of file chan_iax2.c.

References AST_CAUSE_NO_USER_RESPONSE, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), IAX_COMMAND_HANGUP, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, and send_command_final().

Referenced by auto_hangup().

06394 {
06395    /* Called from IAX thread only, without iaxs lock */
06396    int callno = (int)(long)(nothing);
06397    struct iax_ie_data ied;
06398    ast_mutex_lock(&iaxsl[callno]);
06399    if (iaxs[callno]) {
06400       memset(&ied, 0, sizeof(ied));
06401       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
06402       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
06403       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
06404    }
06405    ast_mutex_unlock(&iaxsl[callno]);
06406 }

static int __do_deliver ( void *  data  )  [static]

Note:
This function assumes that iaxsl[callno] is locked when called.

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 2013 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().

02014 {
02015    /* Just deliver the packet by using queueing.  This is called by
02016      the IAX thread with the iaxsl lock held. */
02017    struct iax_frame *fr = data;
02018    fr->retrans = -1;
02019    ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO);
02020    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
02021       iax2_queue_frame(fr->callno, &fr->af);
02022    /* Free our iax frame */
02023    iax2_frame_free(fr);
02024    /* And don't run again */
02025    return 0;
02026 }

static void __expire_registry ( const void *  data  )  [static]

Definition at line 6032 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, globalflags, iax2_regfunk, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, manager_event(), option_debug, peer_unref(), realtime_update_peer(), register_peer_exten(), and unlink_peer().

Referenced by expire_registry().

06033 {
06034    struct iax2_peer *peer = (struct iax2_peer *) data;
06035 
06036    if (!peer)
06037       return;
06038 
06039    peer->expire = -1;
06040 
06041    if (option_debug)
06042       ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name);
06043    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
06044       realtime_update_peer(peer->name, &peer->addr, 0);
06045    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
06046    /* Reset the address */
06047    memset(&peer->addr, 0, sizeof(peer->addr));
06048    /* Reset expiry value */
06049    peer->expiry = min_reg_expire;
06050    if (!ast_test_flag(peer, IAX_TEMPONLY))
06051       ast_db_del("IAX/Registry", peer->name);
06052    register_peer_exten(peer, 0);
06053    ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
06054    if (iax2_regfunk)
06055       iax2_regfunk(peer->name, 0);
06056 
06057    if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
06058       unlink_peer(peer);
06059 
06060    peer_unref(peer);
06061 }

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]

Note:
Calling this function while holding another pvt lock can cause a deadlock.

Definition at line 1512 of file chan_iax2.c.

References chan_iax2_pvt::addr, 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, globalflags, iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, iax_peercallno_pvts, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, iaxsl, LOG_DEBUG, LOG_WARNING, match(), maxnontrunkcall, maxtrunkcall, MIN_REUSE_TIME, NEW_ALLOW, new_iax(), option_debug, chan_iax2_pvt::peercallno, sched, send_lagrq(), send_ping(), store_by_peercallno(), TRUNK_CALL_START, and update_max_nontrunk().

Referenced by find_callno(), and find_callno_locked().

01513 {
01514    int res = 0;
01515    int x;
01516    struct timeval now;
01517    char host[80];
01518 
01519    if (new <= NEW_ALLOW) {
01520       if (callno) {
01521          struct chan_iax2_pvt *pvt;
01522          struct chan_iax2_pvt tmp_pvt = {
01523             .callno = dcallno,
01524             .peercallno = callno,
01525             /* hack!! */
01526             .frames_received = check_dcallno,
01527          };
01528  
01529          memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr));
01530  
01531          if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
01532             if (return_locked) {
01533                ast_mutex_lock(&iaxsl[pvt->callno]);
01534             }
01535             res = pvt->callno;
01536             ao2_ref(pvt, -1);
01537             pvt = NULL;
01538             return res;
01539          }
01540       }
01541 
01542       /* Look for an existing connection first */
01543       for (x = 1; !res && x < maxnontrunkcall; x++) {
01544          ast_mutex_lock(&iaxsl[x]);
01545          if (iaxs[x]) {
01546             /* Look for an exact match */
01547             if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) {
01548                res = x;
01549             }
01550          }
01551          if (!res || !return_locked)
01552             ast_mutex_unlock(&iaxsl[x]);
01553       }
01554       for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) {
01555          ast_mutex_lock(&iaxsl[x]);
01556          if (iaxs[x]) {
01557             /* Look for an exact match */
01558             if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) {
01559                res = x;
01560             }
01561          }
01562          if (!res || !return_locked)
01563             ast_mutex_unlock(&iaxsl[x]);
01564       }
01565    }
01566    if (!res && (new >= NEW_ALLOW)) {
01567       int start, found = 0;
01568 
01569       /* It may seem odd that we look through the peer list for a name for
01570        * this *incoming* call.  Well, it is weird.  However, users don't
01571        * have an IP address/port number that we can match against.  So,
01572        * this is just checking for a peer that has that IP/port and
01573        * assuming that we have a user of the same name.  This isn't always
01574        * correct, but it will be changed if needed after authentication. */
01575       if (!iax2_getpeername(*sin, host, sizeof(host)))
01576          snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
01577 
01578       now = ast_tvnow();
01579       start = 2 + (ast_random() % (TRUNK_CALL_START - 1));
01580       for (x = start; 1; x++) {
01581          if (x == TRUNK_CALL_START) {
01582             x = 1;
01583             continue;
01584          }
01585 
01586          /* Find first unused call number that hasn't been used in a while */
01587          ast_mutex_lock(&iaxsl[x]);
01588          if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01589             found = 1;
01590             break;
01591          }
01592          ast_mutex_unlock(&iaxsl[x]);
01593          
01594          if (x == start - 1) {
01595             break;
01596          }
01597       }
01598       /* We've still got lock held if we found a spot */
01599       if (x == start - 1 && !found) {
01600          ast_log(LOG_WARNING, "No more space\n");
01601          return 0;
01602       }
01603       iaxs[x] = new_iax(sin, host);
01604       update_max_nontrunk();
01605       if (iaxs[x]) {
01606          if (option_debug && iaxdebug)
01607             ast_log(LOG_DEBUG, "Creating new call structure %d\n", x);
01608          iaxs[x]->sockfd = sockfd;
01609          iaxs[x]->addr.sin_port = sin->sin_port;
01610          iaxs[x]->addr.sin_family = sin->sin_family;
01611          iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr;
01612          iaxs[x]->peercallno = callno;
01613          iaxs[x]->callno = x;
01614          iaxs[x]->pingtime = DEFAULT_RETRY_TIME;
01615          iaxs[x]->expiry = min_reg_expire;
01616          iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01617          iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01618          iaxs[x]->amaflags = amaflags;
01619          ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
01620          
01621          ast_string_field_set(iaxs[x], accountcode, accountcode);
01622          ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
01623          ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
01624 
01625          if (iaxs[x]->peercallno) {
01626             store_by_peercallno(iaxs[x]);
01627          }
01628       } else {
01629          ast_log(LOG_WARNING, "Out of resources\n");
01630          ast_mutex_unlock(&iaxsl[x]);
01631          return 0;
01632       }
01633       if (!return_locked)
01634          ast_mutex_unlock(&iaxsl[x]);
01635       res = x;
01636    }
01637    return res;
01638 }

static void __get_from_jb ( const void *  p  )  [static]

Definition at line 2543 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(), 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().

02544 {
02545    int callno = PTR_TO_CALLNO(p);
02546    struct chan_iax2_pvt *pvt = NULL;
02547    struct iax_frame *fr;
02548    jb_frame frame;
02549    int ret;
02550    long now;
02551    long next;
02552    struct timeval tv;
02553    
02554    /* Make sure we have a valid private structure before going on */
02555    ast_mutex_lock(&iaxsl[callno]);
02556    pvt = iaxs[callno];
02557    if (!pvt) {
02558       /* No go! */
02559       ast_mutex_unlock(&iaxsl[callno]);
02560       return;
02561    }
02562 
02563    pvt->jbid = -1;
02564    
02565    gettimeofday(&tv,NULL);
02566    /* round up a millisecond since ast_sched_runq does; */
02567    /* prevents us from spinning while waiting for our now */
02568    /* to catch up with runq's now */
02569    tv.tv_usec += 1000;
02570    
02571    now = ast_tvdiff_ms(tv, pvt->rxcore);
02572    
02573    if(now >= (next = jb_next(pvt->jb))) {
02574       ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
02575       switch(ret) {
02576       case JB_OK:
02577          fr = frame.data;
02578          __do_deliver(fr);
02579          /* __do_deliver() can cause the call to disappear */
02580          pvt = iaxs[callno];
02581          break;
02582       case JB_INTERP:
02583       {
02584          struct ast_frame af = { 0, };
02585          
02586          /* create an interpolation frame */
02587          af.frametype = AST_FRAME_VOICE;
02588          af.subclass = pvt->voiceformat;
02589          af.samples  = frame.ms * 8;
02590          af.src  = "IAX2 JB interpolation";
02591          af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
02592          af.offset = AST_FRIENDLY_OFFSET;
02593          
02594          /* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
02595           * which we'd need to malloc, and then it would free it.  That seems like a drag */
02596          if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
02597             iax2_queue_frame(callno, &af);
02598             /* iax2_queue_frame() could cause the call to disappear */
02599             pvt = iaxs[callno];
02600          }
02601       }
02602          break;
02603       case JB_DROP:
02604          iax2_frame_free(frame.data);
02605          break;
02606       case JB_NOFRAME:
02607       case JB_EMPTY:
02608          /* do nothing */
02609          break;
02610       default:
02611          /* shouldn't happen */
02612          break;
02613       }
02614    }
02615    if (pvt)
02616       update_jbsched(pvt);
02617    ast_mutex_unlock(&iaxsl[callno]);
02618 }

static void __iax2_do_register_s ( const void *  data  )  [static]

Definition at line 5725 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05726 {
05727    struct iax2_registry *reg = (struct iax2_registry *)data;
05728    reg->expire = -1;
05729    iax2_do_register(reg);
05730 }

static void __iax2_poke_noanswer ( const void *  data  )  [static]

Definition at line 8826 of file chan_iax2.c.

References ast_device_state_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_peer::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, iax2_peer::pokefreqnotok, and sched.

Referenced by iax2_poke_noanswer().

08827 {
08828    struct iax2_peer *peer = (struct iax2_peer *)data;
08829    int callno;
08830 
08831    if (peer->lastms > -1) {
08832       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08833       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08834       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08835    }
08836    if ((callno = peer->callno) > 0) {
08837       ast_mutex_lock(&iaxsl[callno]);
08838       iax2_destroy(callno);
08839       ast_mutex_unlock(&iaxsl[callno]);
08840    }
08841    peer->callno = 0;
08842    peer->lastms = -1;
08843    /* Try again quickly */
08844    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
08845    if (peer->pokeexpire == -1)
08846       peer_unref(peer);
08847 }

static void __iax2_poke_peer_s ( const void *  data  )  [static]

Definition at line 6456 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06457 {
06458    struct iax2_peer *peer = (struct iax2_peer *)data;
06459    iax2_poke_peer(peer, 0);
06460    peer_unref(peer);
06461 }

static int __iax2_show_peers ( int  manager,
int  fd,
struct mansession s,
int  argc,
char *  argv[] 
) [static]

Definition at line 4515 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, RESULT_SUCCESS, and s.

Referenced by iax2_show_peers(), and manager_iax2_show_peers().

04516 {
04517    regex_t regexbuf;
04518    int havepattern = 0;
04519    int total_peers = 0;
04520    int online_peers = 0;
04521    int offline_peers = 0;
04522    int unmonitored_peers = 0;
04523    struct ao2_iterator i;
04524 
04525 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
04526 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
04527 
04528    struct iax2_peer *peer = NULL;
04529    char name[256];
04530    int registeredonly=0;
04531    char *term = manager ? "\r\n" : "\n";
04532 
04533    switch (argc) {
04534    case 6:
04535       if (!strcasecmp(argv[3], "registered"))
04536          registeredonly = 1;
04537       else
04538          return RESULT_SHOWUSAGE;
04539       if (!strcasecmp(argv[4], "like")) {
04540          if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
04541             return RESULT_SHOWUSAGE;
04542          havepattern = 1;
04543       } else
04544          return RESULT_SHOWUSAGE;
04545       break;
04546    case 5:
04547       if (!strcasecmp(argv[3], "like")) {
04548          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04549             return RESULT_SHOWUSAGE;
04550          havepattern = 1;
04551       } else
04552          return RESULT_SHOWUSAGE;
04553       break;
04554    case 4:
04555       if (!strcasecmp(argv[3], "registered"))
04556          registeredonly = 1;
04557       else
04558          return RESULT_SHOWUSAGE;
04559       break;
04560    case 3:
04561       break;
04562    default:
04563       return RESULT_SHOWUSAGE;
04564    }
04565 
04566 
04567    if (s)
04568       astman_append(s, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04569    else
04570       ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04571 
04572    i = ao2_iterator_init(peers, 0);
04573    for (peer = ao2_iterator_next(&i); peer; 
04574       peer_unref(peer), peer = ao2_iterator_next(&i)) {
04575       char nm[20];
04576       char status[20];
04577       char srch[2000];
04578       int retstatus;
04579 
04580       if (registeredonly && !peer->addr.sin_addr.s_addr)
04581          continue;
04582       if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0))
04583          continue;
04584 
04585       if (!ast_strlen_zero(peer->username))
04586          snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
04587       else
04588          ast_copy_string(name, peer->name, sizeof(name));
04589       
04590       retstatus = peer_status(peer, status, sizeof(status));
04591       if (retstatus > 0)
04592          online_peers++;
04593       else if (!retstatus)
04594          offline_peers++;
04595       else
04596          unmonitored_peers++;
04597       
04598       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
04599       
04600       snprintf(srch, sizeof(srch), FORMAT, name, 
04601           peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04602           ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04603           nm,
04604           ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04605           peer->encmethods ? "(E)" : "   ", status, term);
04606       
04607       if (s)
04608          astman_append(s, FORMAT, name, 
04609                   peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)",
04610                   ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04611                   nm,
04612                   ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04613                   peer->encmethods ? "(E)" : "   ", status, term);
04614       else
04615          ast_cli(fd, FORMAT, name, 
04616             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04617             ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04618             nm,
04619             ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04620             peer->encmethods ? "(E)" : "   ", status, term);
04621       total_peers++;
04622    }
04623 
04624    if (s)
04625       astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04626    else
04627       ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04628 
04629    if (havepattern)
04630       regfree(&regexbuf);
04631 
04632    return RESULT_SUCCESS;
04633 #undef FORMAT
04634 #undef FORMAT2
04635 }

static int __schedule_action ( void(*)(const void *data)  func,
const void *  data,
const char *  funcname 
) [static]

Definition at line 955 of file chan_iax2.c.

References ast_log(), find_idle_thread(), IAX_IOSTATE_SCHEDREADY, LOG_DEBUG, option_debug, signal_condition(), t, and thread.

00956 {
00957    struct iax2_thread *thread = NULL;
00958    static time_t lasterror;
00959    static time_t t;
00960 
00961    thread = find_idle_thread();
00962 
00963    if (thread != NULL) {
00964       thread->schedfunc = func;
00965       thread->scheddata = data;
00966       thread->iostate = IAX_IOSTATE_SCHEDREADY;
00967 #ifdef DEBUG_SCHED_MULTITHREAD
00968       ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc));
00969 #endif
00970       signal_condition(&thread->lock, &thread->cond);
00971       return 0;
00972    }
00973    time(&t);
00974    if (t != lasterror && option_debug) 
00975       ast_log(LOG_DEBUG, "Out of idle IAX2 threads for scheduling!\n");
00976    lasterror = t;
00977 
00978    return -1;
00979 }

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 5016 of file chan_iax2.c.

References f, and iax2_send().

Referenced by send_command(), send_command_final(), send_command_immediate(), and send_command_transfer().

05018 {
05019    struct ast_frame f = { 0, };
05020 
05021    f.frametype = type;
05022    f.subclass = command;
05023    f.datalen = datalen;
05024    f.src = __FUNCTION__;
05025    f.data = (void *) data;
05026 
05027    return iax2_send(i, &f, ts, seqno, now, transfer, final);
05028 }

static void __send_lagrq ( const void *  data  )  [static]

Definition at line 1035 of file chan_iax2.c.

References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_sched_add(), IAX_COMMAND_LAGRQ, iaxsl, sched, send_command(), and send_lagrq().

Referenced by send_lagrq().

01036 {
01037    int callno = (long) data;
01038 
01039    ast_mutex_lock(&iaxsl[callno]);
01040 
01041    while (iaxs[callno] && iaxs[callno]->lagid > -1) {
01042       if (iaxs[callno]->peercallno) {
01043          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
01044       }
01045       iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
01046       break;
01047    }
01048 
01049    ast_mutex_unlock(&iaxsl[callno]);
01050 }

static void __send_ping ( const void *  data  )  [static]

Definition at line 995 of file chan_iax2.c.

References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_sched_add(), IAX_COMMAND_PING, iaxsl, sched, send_command(), and send_ping().

Referenced by send_ping().

00996 {
00997    int callno = (long) data;
00998 
00999    ast_mutex_lock(&iaxsl[callno]);
01000 
01001    while (iaxs[callno] && iaxs[callno]->pingid != -1) {
01002       if (iaxs[callno]->peercallno) {
01003          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
01004       }
01005       iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
01006       break;
01007    }
01008 
01009    ast_mutex_unlock(&iaxsl[callno]);
01010 }

static int __unload_module ( void   )  [static]

Definition at line 10953 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, netsock, outsock, peers, reload_firmware(), sched, sched_context_destroy(), thread, users, and waresl.

Referenced by load_module(), and unload_module().

10954 {
10955    struct iax2_thread *thread = NULL;
10956    int x;
10957 
10958    /* Make sure threads do not hold shared resources when they are canceled */
10959    
10960    /* Grab the sched lock resource to keep it away from threads about to die */
10961    /* Cancel the network thread, close the net socket */
10962    if (netthreadid != AST_PTHREADT_NULL) {
10963       AST_LIST_LOCK(&iaxq.queue);
10964       ast_mutex_lock(&sched_lock);
10965       pthread_cancel(netthreadid);
10966       ast_cond_signal(&sched_cond);
10967       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
10968       AST_LIST_UNLOCK(&iaxq.queue);
10969       pthread_join(netthreadid, NULL);
10970    }
10971    if (schedthreadid != AST_PTHREADT_NULL) {
10972       ast_mutex_lock(&sched_lock);  
10973       pthread_cancel(schedthreadid);
10974       ast_cond_signal(&sched_cond);
10975       ast_mutex_unlock(&sched_lock);   
10976       pthread_join(schedthreadid, NULL);
10977    }
10978    
10979    /* Call for all threads to halt */
10980    AST_LIST_LOCK(&idle_list);
10981    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
10982       AST_LIST_REMOVE_CURRENT(&idle_list, list);
10983       pthread_cancel(thread->threadid);
10984    }
10985    AST_LIST_TRAVERSE_SAFE_END
10986    AST_LIST_UNLOCK(&idle_list);
10987 
10988    AST_LIST_LOCK(&active_list);
10989    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
10990       AST_LIST_REMOVE_CURRENT(&active_list, list);
10991       pthread_cancel(thread->threadid);
10992    }
10993    AST_LIST_TRAVERSE_SAFE_END
10994    AST_LIST_UNLOCK(&active_list);
10995 
10996    AST_LIST_LOCK(&dynamic_list);
10997         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
10998       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
10999       pthread_cancel(thread->threadid);
11000         }
11001    AST_LIST_TRAVERSE_SAFE_END
11002         AST_LIST_UNLOCK(&dynamic_list);
11003 
11004    AST_LIST_HEAD_DESTROY(&iaxq.queue);
11005 
11006    /* Wait for threads to exit */
11007    while(0 < iaxactivethreadcount)
11008       usleep(10000);
11009    
11010    ast_netsock_release(netsock);
11011    ast_netsock_release(outsock);
11012    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
11013       if (iaxs[x]) {
11014          iax2_destroy(x);
11015       }
11016    }
11017    ast_manager_unregister( "IAXpeers" );
11018    ast_manager_unregister( "IAXnetstats" );
11019    ast_unregister_application(papp);
11020    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
11021    ast_unregister_switch(&iax2_switch);
11022    ast_channel_unregister(&iax2_tech);
11023    delete_users();
11024    iax_provision_unload();
11025    sched_context_destroy(sched);
11026    reload_firmware(1);
11027 
11028    ast_mutex_destroy(&waresl.lock);
11029 
11030    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11031       ast_mutex_destroy(&iaxsl[x]);
11032    }
11033 
11034    ao2_ref(peers, -1);
11035    ao2_ref(users, -1);
11036    ao2_ref(iax_peercallno_pvts, -1);
11037 
11038    return 0;
11039 }

static int apply_context ( struct iax2_context con,
const char *  context 
) [static]

Definition at line 5069 of file chan_iax2.c.

References iax2_context::context, and iax2_context::next.

Referenced by check_access().

05070 {
05071    while(con) {
05072       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
05073          return -1;
05074       con = con->next;
05075    }
05076    return 0;
05077 }

static int ast_cli_netstats ( struct mansession s,
int  fd,
int  limit_fmt 
) [static]

Definition at line 4843 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, chan_iax2_pvt::remote_rr, and s.

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

04844 {
04845    int x;
04846    int numchans = 0;
04847    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04848       ast_mutex_lock(&iaxsl[x]);
04849       if (iaxs[x]) {
04850          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04851          char *fmt;
04852          jb_info jbinfo;
04853          
04854          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04855             jb_getinfo(iaxs[x]->jb, &jbinfo);
04856             localjitter = jbinfo.jitter;
04857             localdelay = jbinfo.current - jbinfo.min;
04858             locallost = jbinfo.frames_lost;
04859             locallosspct = jbinfo.losspct/1000;
04860             localdropped = jbinfo.frames_dropped;
04861             localooo = jbinfo.frames_ooo;
04862          } else {
04863             localjitter = -1;
04864             localdelay = 0;
04865             locallost = -1;
04866             locallosspct = -1;
04867             localdropped = 0;
04868             localooo = -1;
04869          }
04870          if (limit_fmt)
04871             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04872          else
04873             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04874          if (s)
04875             
04876             astman_append(s, fmt,
04877                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04878                      iaxs[x]->pingtime,
04879                      localjitter, 
04880                      localdelay,
04881                      locallost,
04882                      locallosspct,
04883                      localdropped,
04884                      localooo,
04885                      iaxs[x]->frames_received/1000,
04886                      iaxs[x]->remote_rr.jitter,
04887                      iaxs[x]->remote_rr.delay,
04888                      iaxs[x]->remote_rr.losscnt,
04889                      iaxs[x]->remote_rr.losspct,
04890                      iaxs[x]->remote_rr.dropped,
04891                      iaxs[x]->remote_rr.ooo,
04892                      iaxs[x]->remote_rr.packets/1000);
04893          else
04894             ast_cli(fd, fmt,
04895                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04896                iaxs[x]->pingtime,
04897                localjitter, 
04898                localdelay,
04899                locallost,
04900                locallosspct,
04901                localdropped,
04902                localooo,
04903                iaxs[x]->frames_received/1000,
04904                iaxs[x]->remote_rr.jitter,
04905                iaxs[x]->remote_rr.delay,
04906                iaxs[x]->remote_rr.losscnt,
04907                iaxs[x]->remote_rr.losspct,
04908                iaxs[x]->remote_rr.dropped,
04909                iaxs[x]->remote_rr.ooo,
04910                iaxs[x]->remote_rr.packets/1000
04911                );
04912          numchans++;
04913       }
04914       ast_mutex_unlock(&iaxsl[x]);
04915    }
04916    return numchans;
04917 }

static struct ast_channel* ast_iax2_new ( int  callno,
int  state,
int  capability 
) [static]

Create new call, interface with the PBX core.

Definition at line 3721 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().

03722 {
03723    struct ast_channel *tmp;
03724    struct chan_iax2_pvt *i;
03725    struct ast_variable *v = NULL;
03726 
03727    if (!(i = iaxs[callno])) {
03728       ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
03729       return NULL;
03730    }
03731 
03732    /* Don't hold call lock */
03733    ast_mutex_unlock(&iaxsl[callno]);
03734    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);
03735    ast_mutex_lock(&iaxsl[callno]);
03736    if (!iaxs[callno]) {
03737       if (tmp) {
03738          ast_channel_free(tmp);
03739       }
03740       ast_mutex_unlock(&iaxsl[callno]);
03741       return NULL;
03742    }
03743 
03744    if (!tmp)
03745       return NULL;
03746    tmp->tech = &iax2_tech;
03747    /* We can support any format by default, until we get restricted */
03748    tmp->nativeformats = capability;
03749    tmp->readformat = ast_best_codec(capability);
03750    tmp->writeformat = ast_best_codec(capability);
03751    tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
03752 
03753    /* Don't use ast_set_callerid() here because it will
03754     * generate a NewCallerID event before the NewChannel event */
03755    if (!ast_strlen_zero(i->ani))
03756       tmp->cid.cid_ani = ast_strdup(i->ani);
03757    else
03758       tmp->cid.cid_ani = ast_strdup(i->cid_num);
03759    tmp->cid.cid_dnid = ast_strdup(i->dnid);
03760    tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
03761    tmp->cid.cid_pres = i->calling_pres;
03762    tmp->cid.cid_ton = i->calling_ton;
03763    tmp->cid.cid_tns = i->calling_tns;
03764    if (!ast_strlen_zero(i->language))
03765       ast_string_field_set(tmp, language, i->language);
03766    if (!ast_strlen_zero(i->accountcode))
03767       ast_string_field_set(tmp, accountcode, i->accountcode);
03768    if (i->amaflags)
03769       tmp->amaflags = i->amaflags;
03770    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
03771    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
03772    if (i->adsi)
03773       tmp->adsicpe = i->peeradsicpe;
03774    else
03775       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
03776    i->owner = tmp;
03777    i->capability = capability;
03778 
03779    for (v = i->vars ; v ; v = v->next)
03780       pbx_builtin_setvar_helper(tmp, v->name, v->value);
03781 
03782    if (state != AST_STATE_DOWN) {
03783       if (ast_pbx_start(tmp)) {
03784          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
03785          ast_hangup(tmp);
03786          i->owner = NULL;
03787          return NULL;
03788       }
03789    }
03790 
03791    ast_module_ref(ast_module_info->self);
03792    
03793    return tmp;
03794 }

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 2227 of file chan_iax2.c.

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02228 {
02229 #ifdef SCHED_MULTITHREADED
02230    if (schedule_action(__attempt_transmit, data))
02231 #endif      
02232       __attempt_transmit(data);
02233    return 0;
02234 }

static int auth_fail ( int  callno,
int  failcode 
) [static]

Definition at line 6378 of file chan_iax2.c.

References AST_SCHED_DEL, auth_reject(), chan_iax2_pvt::authfail, chan_iax2_pvt::authid, iax2_sched_add(), iaxs, and sched.

Referenced by socket_process().

06379 {
06380    /* Schedule sending the authentication failure in one second, to prevent
06381       guessing */
06382    if (iaxs[callno]) {
06383       iaxs[callno]->authfail = failcode;
06384       if (delayreject) {
06385          AST_SCHED_DEL(sched, iaxs[callno]->authid);
06386          iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06387       } else
06388          auth_reject((void *)(long)callno);
06389    }
06390    return 0;
06391 }

static int auth_reject ( const void *  data  )  [static]

Definition at line 6364 of file chan_iax2.c.

References __auth_reject(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::authid, iaxs, iaxsl, and schedule_action.

Referenced by auth_fail().

06365 {
06366    int callno = (int)(long)(data);
06367    ast_mutex_lock(&iaxsl[callno]);
06368    if (iaxs[callno])
06369       iaxs[callno]->authid = -1;
06370    ast_mutex_unlock(&iaxsl[callno]);
06371 #ifdef SCHED_MULTITHREADED
06372    if (schedule_action(__auth_reject, data))
06373 #endif      
06374       __auth_reject(data);
06375    return 0;
06376 }

static int authenticate ( const char *  challenge,
const char *  secret,
const char *  keyn,
int  authmethods,
struct iax_ie_data ied,
struct sockaddr_in *  sin,
aes_encrypt_ctx ecx,
aes_decrypt_ctx dcx 
) [static]

Definition at line 5594 of file chan_iax2.c.

References ast_inet_ntoa(), ast_key_get, AST_KEY_PRIVATE, ast_log(), ast_sign, ast_strlen_zero(), build_enc_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, md5(), MD5Final(), MD5Init(), and MD5Update().

05595 {
05596    int res = -1;
05597    int x;
05598    if (!ast_strlen_zero(keyn)) {
05599       if (!(authmethods & IAX_AUTH_RSA)) {
05600          if (ast_strlen_zero(secret)) 
05601             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));
05602       } else if (ast_strlen_zero(challenge)) {
05603          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
05604       } else {
05605          char sig[256];
05606          struct ast_key *key;
05607          key = ast_key_get(keyn, AST_KEY_PRIVATE);
05608          if (!key) {
05609             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
05610          } else {
05611             if (ast_sign(key, (char*)challenge, sig)) {
05612                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
05613                res = -1;
05614             } else {
05615                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
05616                res = 0;
05617             }
05618          }
05619       }
05620    } 
05621    /* Fall back */
05622    if (res && !ast_strlen_zero(secret)) {
05623       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
05624          struct MD5Context md5;
05625          unsigned char digest[16];
05626          char digres[128];
05627          MD5Init(&md5);
05628          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
05629          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
05630          MD5Final(digest, &md5);
05631          /* If they support md5, authenticate with it.  */
05632          for (x=0;x<16;x++)
05633             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
05634          if (ecx && dcx)
05635             build_enc_keys(digest, ecx, dcx);
05636          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
05637          res = 0;
05638       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
05639          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
05640          res = 0;
05641       } else
05642          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
05643    }
05644    return res;
05645 }

static int authenticate_reply ( struct chan_iax2_pvt p,
struct sockaddr_in *  sin,
struct iax_ies ies,
const char *  override,
const char *  okey 
) [static]

Note:
This function calls realtime_peer -> reg_source_db -> iax2_poke_peer -> find_callno, so do not call this function with a pvt lock held.

Definition at line 5651 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(), iax2_peer::authmethods, chan_iax2_pvt::callno, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, iaxs, iaxsl, ies, iax2_peer::mask, merge_encryption(), peer_unref(), peers, realtime_peer(), and send_command().

Referenced by socket_process().

05652 {
05653    struct iax2_peer *peer = NULL;
05654    /* Start pessimistic */
05655    int res = -1;
05656    int authmethods = 0;
05657    struct iax_ie_data ied;
05658    uint16_t callno = p->callno;
05659 
05660    memset(&ied, 0, sizeof(ied));
05661    
05662    if (ies->username)
05663       ast_string_field_set(p, username, ies->username);
05664    if (ies->challenge)
05665       ast_string_field_set(p, challenge, ies->challenge);
05666    if (ies->authmethods)
05667       authmethods = ies->authmethods;
05668    if (authmethods & IAX_AUTH_MD5)
05669       merge_encryption(p, ies->encmethods);
05670    else
05671       p->encmethods = 0;
05672 
05673    /* Check for override RSA authentication first */
05674    if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) {
05675       /* Normal password authentication */
05676       res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05677    } else {
05678       struct ao2_iterator i = ao2_iterator_init(peers, 0);
05679       while ((peer = ao2_iterator_next(&i))) {
05680          if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
05681              /* No peer specified at our end, or this is the peer */
05682              && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
05683              /* No username specified in peer rule, or this is the right username */
05684              && (!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)))
05685              /* No specified host, or this is our host */
05686             ) {
05687             res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05688             if (!res) {
05689                peer_unref(peer);
05690                break;
05691             }
05692          }
05693          peer_unref(peer);
05694       }
05695       if (!peer) {
05696          /* We checked our list and didn't find one.  It's unlikely, but possible, 
05697             that we're trying to authenticate *to* a realtime peer */
05698          const char *peer_name = ast_strdupa(p->peer);
05699          ast_mutex_unlock(&iaxsl[callno]);
05700          if ((peer = realtime_peer(peer_name, NULL))) {
05701             ast_mutex_lock(&iaxsl[callno]);
05702             if (!(p = iaxs[callno])) {
05703                peer_unref(peer);
05704                return -1;
05705             }
05706             res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05707             peer_unref(peer);
05708          }
05709          if (!peer) {
05710             ast_mutex_lock(&iaxsl[callno]);
05711             if (!(p = iaxs[callno]))
05712                return -1;
05713          }
05714       }
05715    }
05716    if (ies->encmethods)
05717       ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
05718    if (!res)
05719       res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);
05720    return res;
05721 }

static int authenticate_request ( int  call_num  )  [static]

Precondition:
iaxsl[call_num] is locked
Note:
Since this function calls send_command_final(), the pvt struct for the given call number may disappear while executing this function.

Definition at line 5329 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, 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, send_command(), send_command_final(), user_unref(), and users.

Referenced by socket_process().

05330 {
05331    struct iax_ie_data ied;
05332    int res = -1, authreq_restrict = 0;
05333    char challenge[10];
05334    struct chan_iax2_pvt *p = iaxs[call_num];
05335 
05336    memset(&ied, 0, sizeof(ied));
05337 
05338    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
05339    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05340       struct iax2_user *user, tmp_user = {
05341          .name = p->username, 
05342       };
05343 
05344       user = ao2_find(users, &tmp_user, OBJ_POINTER);
05345       if (user) {
05346          if (user->curauthreq == user->maxauthreq)
05347             authreq_restrict = 1;
05348          else
05349             user->curauthreq++;
05350          user = user_unref(user);
05351       }
05352    }
05353 
05354    /* If the AUTHREQ limit test failed, send back an error */
05355    if (authreq_restrict) {
05356       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
05357       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
05358       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
05359       return 0;
05360    }
05361 
05362    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
05363    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
05364       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
05365       ast_string_field_set(p, challenge, challenge);
05366       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
05367       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
05368    }
05369    if (p->encmethods)
05370       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
05371 
05372    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
05373 
05374    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
05375 
05376    if (p->encmethods)
05377       ast_set_flag(p, IAX_ENCRYPTED);
05378 
05379    return res;
05380 }

static int authenticate_verify ( struct chan_iax2_pvt p,
struct iax_ies ies 
) [static]

Definition at line 5382 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, ies, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), secret, chan_iax2_pvt::state, strsep(), user_unref(), and users.

Referenced by socket_process().

05383 {
05384    char requeststr[256];
05385    char md5secret[256] = "";
05386    char secret[256] = "";
05387    char rsasecret[256] = "";
05388    int res = -1; 
05389    int x;
05390    struct iax2_user *user, tmp_user = {
05391       .name = p->username, 
05392    };
05393 
05394    user = ao2_find(users, &tmp_user, OBJ_POINTER);
05395    if (user) {
05396       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05397          ast_atomic_fetchadd_int(&user->curauthreq, -1);
05398          ast_clear_flag(p, IAX_MAXAUTHREQ);
05399       }
05400       ast_string_field_set(p, host, user->name);
05401       user = user_unref(user);
05402    }
05403 
05404    if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
05405       return res;
05406    if (ies->password)
05407       ast_copy_string(secret, ies->password, sizeof(secret));
05408    if (ies->md5_result)
05409       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05410    if (ies->rsa_result)
05411       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05412    if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) {
05413       struct ast_key *key;
05414       char *keyn;
05415       char tmpkey[256];
05416       char *stringp=NULL;
05417       ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey));
05418       stringp=tmpkey;
05419       keyn = strsep(&stringp, ":");
05420       while(keyn) {
05421          key = ast_key_get(keyn, AST_KEY_PUBLIC);
05422          if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
05423             res = 0;
05424             break;
05425          } else if (!key)
05426             ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
05427          keyn = strsep(&stringp, ":");
05428       }
05429    } else if (p->authmethods & IAX_AUTH_MD5) {
05430       struct MD5Context md5;
05431       unsigned char digest[16];
05432       char *tmppw, *stringp;
05433       
05434       tmppw = ast_strdupa(p->secret);
05435       stringp = tmppw;
05436       while((tmppw = strsep(&stringp, ";"))) {
05437          MD5Init(&md5);
05438          MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge));
05439          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05440          MD5Final(digest, &md5);
05441          /* If they support md5, authenticate with it.  */
05442          for (x=0;x<16;x++)
05443             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05444          if (!strcasecmp(requeststr, md5secret)) {
05445             res = 0;
05446             break;
05447          }
05448       }
05449    } else if (p->authmethods & IAX_AUTH_PLAINTEXT) {
05450       if (!strcmp(secret, p->secret))
05451          res = 0;
05452    }
05453    return res;
05454 }

static int auto_congest ( const void *  data  )  [static]

Definition at line 3114 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

03115 {
03116 #ifdef SCHED_MULTITHREADED
03117    if (schedule_action(__auto_congest, data))
03118 #endif      
03119       __auto_congest(data);
03120    return 0;
03121 }

static int auto_hangup ( const void *  data  )  [static]

Definition at line 6408 of file chan_iax2.c.

References __auto_hangup(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::autoid, iaxs, iaxsl, and schedule_action.

Referenced by iax2_dprequest(), and iax2_provision().

06409 {
06410    int callno = (int)(long)(data);
06411    ast_mutex_lock(&iaxsl[callno]);
06412    if (iaxs[callno]) {
06413       iaxs[callno]->autoid = -1;
06414    }
06415    ast_mutex_unlock(&iaxsl[callno]);
06416 #ifdef SCHED_MULTITHREADED
06417    if (schedule_action(__auto_hangup, data))
06418 #endif      
06419       __auto_hangup(data);
06420    return 0;
06421 }

static struct iax2_context* build_context ( char *  context  )  [static]

Definition at line 9147 of file chan_iax2.c.

References ast_calloc.

Referenced by build_user().

09148 {
09149    struct iax2_context *con;
09150 
09151    if ((con = ast_calloc(1, sizeof(*con))))
09152       ast_copy_string(con->context, context, sizeof(con->context));
09153    
09154    return con;
09155 }

static void build_enc_keys ( const unsigned char *  digest,
aes_encrypt_ctx ecx,
aes_decrypt_ctx dcx 
) [static]

Definition at line 4101 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

04102 {
04103    aes_encrypt_key128(digest, ecx);
04104    aes_decrypt_key128(digest, dcx);
04105 }

static struct iax2_peer * build_peer ( const char *  name,
struct ast_variable v,
struct ast_variable alt,
int  temponly 
) [static]

Create peer structure based on configuration.

Definition at line 9293 of file chan_iax2.c.

References 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(), cid_name, cid_num, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, get_auth_methods(), get_encrypt_methods(), globalflags, 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, ast_variable::name, ast_variable::next, peer_destructor(), peer_set_srcaddr(), peer_unref(), peers, prefs, sched, secret, unlink_peer(), and ast_variable::value.

09294 {
09295    struct iax2_peer *peer = NULL;
09296    struct ast_ha *oldha = NULL;
09297    int maskfound=0;
09298    int found=0;
09299    int firstpass=1;
09300    struct iax2_peer tmp_peer = {
09301       .name = name,
09302    };
09303 
09304    if (!temponly) {
09305       peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
09306       if (peer && !ast_test_flag(peer, IAX_DELME))
09307          firstpass = 0;
09308    }
09309 
09310    if (peer) {
09311       found++;
09312       if (firstpass) {
09313          oldha = peer->ha;
09314          peer->ha = NULL;
09315       }
09316       unlink_peer(peer);
09317    } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) {
09318       peer->expire = -1;
09319       peer->pokeexpire = -1;
09320       peer->sockfd = defaultsockfd;
09321       if (ast_string_field_init(peer, 32))
09322          peer = peer_unref(peer);
09323    }
09324 
09325    if (peer) {
09326       if (firstpass) {
09327          ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
09328          peer->encmethods = iax2_encryption;
09329          peer->adsi = adsi;
09330          ast_string_field_set(peer,secret,"");
09331          if (!found) {
09332             ast_string_field_set(peer, name, name);
09333             peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
09334             peer->expiry = min_reg_expire;
09335          }
09336          peer->prefs = prefs;
09337          peer->capability = iax2_capability;
09338          peer->smoothing = 0;
09339          peer->pokefreqok = DEFAULT_FREQ_OK;
09340          peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
09341          ast_string_field_set(peer,context,"");
09342          ast_string_field_set(peer,peercontext,"");
09343          ast_clear_flag(peer, IAX_HASCALLERID);
09344          ast_string_field_set(peer, cid_name, "");
09345          ast_string_field_set(peer, cid_num, "");
09346       }
09347 
09348       if (!v) {
09349          v = alt;
09350          alt = NULL;
09351       }
09352       while(v) {
09353          if (!strcasecmp(v->name, "secret")) {
09354             ast_string_field_set(peer, secret, v->value);
09355          } else if (!strcasecmp(v->name, "mailbox")) {
09356             ast_string_field_set(peer, mailbox, v->value);
09357          } else if (!strcasecmp(v->name, "mohinterpret")) {
09358             ast_string_field_set(peer, mohinterpret, v->value);
09359          } else if (!strcasecmp(v->name, "mohsuggest")) {
09360             ast_string_field_set(peer, mohsuggest, v->value);
09361          } else if (!strcasecmp(v->name, "dbsecret")) {
09362             ast_string_field_set(peer, dbsecret, v->value);
09363          } else if (!strcasecmp(v->name, "trunk")) {
09364             ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK);   
09365             if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) {
09366                ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without zaptel timing\n", peer->name);
09367                ast_clear_flag(peer, IAX_TRUNK);
09368             }
09369          } else if (!strcasecmp(v->name, "auth")) {
09370             peer->authmethods = get_auth_methods(v->value);
09371          } else if (!strcasecmp(v->name, "encryption")) {
09372             peer->encmethods = get_encrypt_methods(v->value);
09373          } else if (!strcasecmp(v->name, "notransfer")) {
09374             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09375             ast_clear_flag(peer, IAX_TRANSFERMEDIA);  
09376             ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 
09377          } else if (!strcasecmp(v->name, "transfer")) {
09378             if (!strcasecmp(v->value, "mediaonly")) {
09379                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
09380             } else if (ast_true(v->value)) {
09381                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09382             } else 
09383                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09384          } else if (!strcasecmp(v->name, "jitterbuffer")) {
09385             ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF);  
09386          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
09387             ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF);   
09388          } else if (!strcasecmp(v->name, "host")) {
09389             if (!strcasecmp(v->value, "dynamic")) {
09390                /* They'll register with us */
09391                ast_set_flag(peer, IAX_DYNAMIC); 
09392                if (!found) {
09393                   /* Initialize stuff iff we're not found, otherwise
09394                      we keep going with what we had */
09395                   memset(&peer->addr.sin_addr, 0, 4);
09396                   if (peer->addr.sin_port) {
09397                      /* If we've already got a port, make it the default rather than absolute */
09398                      peer->defaddr.sin_port = peer->addr.sin_port;
09399                      peer->addr.sin_port = 0;
09400                   }
09401                }
09402             } else {
09403                /* Non-dynamic.  Make sure we become that way if we're not */
09404                AST_SCHED_DEL(sched, peer->expire);
09405                ast_clear_flag(peer, IAX_DYNAMIC);
09406                if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr))
09407                   return peer_unref(peer);
09408                if (!peer->addr.sin_port)
09409                   peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
09410             }
09411             if (!maskfound)
09412                inet_aton("255.255.255.255", &peer->mask);
09413          } else if (!strcasecmp(v->name, "defaultip")) {
09414             if (ast_get_ip(&peer->defaddr, v->value))
09415                return peer_unref(peer);
09416          } else if (!strcasecmp(v->name, "sourceaddress")) {
09417             peer_set_srcaddr(peer, v->value);
09418          } else if (!strcasecmp(v->name, "permit") ||
09419                   !strcasecmp(v->name, "deny")) {
09420             peer->ha = ast_append_ha(v->name, v->value, peer->ha);
09421          } else if (!strcasecmp(v->name, "mask")) {
09422             maskfound++;
09423             inet_aton(v->value, &peer->mask);
09424          } else if (!strcasecmp(v->name, "context")) {
09425             ast_string_field_set(peer, context, v->value);
09426          } else if (!strcasecmp(v->name, "regexten")) {
09427             ast_string_field_set(peer, regexten, v->value);
09428          } else if (!strcasecmp(v->name, "peercontext")) {
09429             ast_string_field_set(peer, peercontext, v->value);
09430          } else if (!strcasecmp(v->name, "port")) {
09431             if (ast_test_flag(peer, IAX_DYNAMIC))
09432                peer->defaddr.sin_port = htons(atoi(v->value));
09433             else
09434                peer->addr.sin_port = htons(atoi(v->value));
09435          } else if (!strcasecmp(v->name, "username")) {
09436             ast_string_field_set(peer, username, v->value);
09437          } else if (!strcasecmp(v->name, "allow")) {
09438             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1);
09439          } else if (!strcasecmp(v->name, "disallow")) {
09440             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0);
09441          } else if (!strcasecmp(v->name, "callerid")) {
09442             if (!ast_strlen_zero(v->value)) {
09443                char name2[80];
09444                char num2[80];
09445                ast_callerid_split(v->value, name2, 80, num2, 80);
09446                ast_string_field_set(peer, cid_name, name2);
09447                ast_string_field_set(peer, cid_num, num2);
09448                ast_set_flag(peer, IAX_HASCALLERID);
09449             } else {
09450                ast_clear_flag(peer, IAX_HASCALLERID);
09451                ast_string_field_set(peer, cid_name, "");
09452                ast_string_field_set(peer, cid_num, "");
09453             }
09454          } else if (!strcasecmp(v->name, "fullname")) {
09455             if (!ast_strlen_zero(v->value)) {
09456                ast_string_field_set(peer, cid_name, v->value);
09457                ast_set_flag(peer, IAX_HASCALLERID);
09458             } else {
09459                ast_string_field_set(peer, cid_name, "");
09460                if (ast_strlen_zero(peer->cid_num))
09461                   ast_clear_flag(peer, IAX_HASCALLERID);
09462             }
09463          } else if (!strcasecmp(v->name, "cid_number")) {
09464             if (!ast_strlen_zero(v->value)) {
09465                ast_string_field_set(peer, cid_num, v->value);
09466                ast_set_flag(peer, IAX_HASCALLERID);
09467             } else {
09468                ast_string_field_set(peer, cid_num, "");
09469                if (ast_strlen_zero(peer->cid_name))
09470                   ast_clear_flag(peer, IAX_HASCALLERID);
09471             }
09472          } else if (!strcasecmp(v->name, "sendani")) {
09473             ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 
09474          } else if (!strcasecmp(v->name, "inkeys")) {
09475             ast_string_field_set(peer, inkeys, v->value);
09476          } else if (!strcasecmp(v->name, "outkey")) {
09477             ast_string_field_set(peer, outkey, v->value);
09478          } else if (!strcasecmp(v->name, "qualify")) {
09479             if (!strcasecmp(v->value, "no")) {
09480                peer->maxms = 0;
09481             } else if (!strcasecmp(v->value, "yes")) {
09482                peer->maxms = DEFAULT_MAXMS;
09483             } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
09484                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);
09485                peer->maxms = 0;
09486             }
09487          } else if (!strcasecmp(v->name, "qualifysmoothing")) {
09488             peer->smoothing = ast_true(v->value);
09489          } else if (!strcasecmp(v->name, "qualifyfreqok")) {
09490             if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) {
09491                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);
09492             }
09493          } else if (!strcasecmp(v->name, "qualifyfreqnotok")) {
09494             if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) {
09495                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);
09496             } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok);
09497          } else if (!strcasecmp(v->name, "timezone")) {
09498             ast_string_field_set(peer, zonetag, v->value);
09499          } else if (!strcasecmp(v->name, "adsi")) {
09500             peer->adsi = ast_true(v->value);
09501          }/* else if (strcasecmp(v->name,"type")) */
09502          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09503          v = v->next;
09504          if (!v) {
09505             v = alt;
09506             alt = NULL;
09507          }
09508       }
09509       if (!peer->authmethods)
09510          peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09511       ast_clear_flag(peer, IAX_DELME); 
09512       /* Make sure these are IPv4 addresses */
09513       peer->addr.sin_family = AF_INET;
09514    }
09515    if (oldha)
09516       ast_free_ha(oldha);
09517    return peer;
09518 }

static struct iax2_user * build_user ( const char *  name,
struct ast_variable v,
struct ast_variable alt,
int  temponly 
) [static]

Create in-memory user structure from configuration.

Definition at line 9534 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(), globalflags, 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_user::prefs, prefs, secret, user_destructor(), user_unref(), users, ast_variable::value, and iax2_user::vars.

09535 {
09536    struct iax2_user *user = NULL;
09537    struct iax2_context *con, *conl = NULL;
09538    struct ast_ha *oldha = NULL;
09539    struct iax2_context *oldcon = NULL;
09540    int format;
09541    int firstpass=1;
09542    int oldcurauthreq = 0;
09543    char *varname = NULL, *varval = NULL;
09544    struct ast_variable *tmpvar = NULL;
09545    struct iax2_user tmp_user = {
09546       .name = name,
09547    };
09548 
09549    if (!temponly) {
09550       user = ao2_find(users, &tmp_user, OBJ_POINTER);
09551       if (user && !ast_test_flag(user, IAX_DELME))
09552          firstpass = 0;
09553    }
09554 
09555    if (user) {
09556       if (firstpass) {
09557          oldcurauthreq = user->curauthreq;
09558          oldha = user->ha;
09559          oldcon = user->contexts;
09560          user->ha = NULL;
09561          user->contexts = NULL;
09562       }
09563       /* Already in the list, remove it and it will be added back (or FREE'd) */
09564       ao2_unlink(users, user);
09565    } else {
09566       user = ao2_alloc(sizeof(*user), user_destructor);
09567    }
09568    
09569    if (user) {
09570       if (firstpass) {
09571          ast_string_field_free_memory(user);
09572          memset(user, 0, sizeof(struct iax2_user));
09573          if (ast_string_field_init(user, 32)) {
09574             user = user_unref(user);
09575             goto cleanup;
09576          }
09577          user->maxauthreq = maxauthreq;
09578          user->curauthreq = oldcurauthreq;
09579          user->prefs = prefs;
09580          user->capability = iax2_capability;
09581          user->encmethods = iax2_encryption;
09582          user->adsi = adsi;
09583          ast_string_field_set(user, name, name);
09584          ast_string_field_set(user, language, language);
09585          ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP);   
09586          ast_clear_flag(user, IAX_HASCALLERID);
09587          ast_string_field_set(user, cid_name, "");
09588          ast_string_field_set(user, cid_num, "");
09589       }
09590       if (!v) {
09591          v = alt;
09592          alt = NULL;
09593       }
09594       while(v) {
09595          if (!strcasecmp(v->name, "context")) {
09596             con = build_context(v->value);
09597             if (con) {
09598                if (conl)
09599                   conl->next = con;
09600                else
09601                   user->contexts = con;
09602                conl = con;
09603             }
09604          } else if (!strcasecmp(v->name, "permit") ||
09605                   !strcasecmp(v->name, "deny")) {
09606             user->ha = ast_append_ha(v->name, v->value, user->ha);
09607          } else if (!strcasecmp(v->name, "setvar")) {
09608             varname = ast_strdupa(v->value);
09609             if (varname && (varval = strchr(varname,'='))) {
09610                *varval = '\0';
09611                varval++;
09612                if((tmpvar = ast_variable_new(varname, varval))) {
09613                   tmpvar->next = user->vars; 
09614                   user->vars = tmpvar;
09615                }
09616             }
09617          } else if (!strcasecmp(v->name, "allow")) {
09618             ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
09619          } else if (!strcasecmp(v->name, "disallow")) {
09620             ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0);
09621          } else if (!strcasecmp(v->name, "trunk")) {
09622             ast_set2_flag(user, ast_true(v->value), IAX_TRUNK);   
09623             if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) {
09624                ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without zaptel timing\n", user->name);
09625                ast_clear_flag(user, IAX_TRUNK);
09626             }
09627          } else if (!strcasecmp(v->name, "auth")) {
09628             user->authmethods = get_auth_methods(v->value);
09629          } else if (!strcasecmp(v->name, "encryption")) {
09630             user->encmethods = get_encrypt_methods(v->value);
09631          } else if (!strcasecmp(v->name, "notransfer")) {
09632             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09633             ast_clear_flag(user, IAX_TRANSFERMEDIA);  
09634             ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 
09635          } else if (!strcasecmp(v->name, "transfer")) {
09636             if (!strcasecmp(v->value, "mediaonly")) {
09637                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
09638             } else if (ast_true(v->value)) {
09639                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09640             } else 
09641                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09642          } else if (!strcasecmp(v->name, "codecpriority")) {
09643             if(!strcasecmp(v->value, "caller"))
09644                ast_set_flag(user, IAX_CODEC_USER_FIRST);
09645             else if(!strcasecmp(v->value, "disabled"))
09646                ast_set_flag(user, IAX_CODEC_NOPREFS);
09647             else if(!strcasecmp(v->value, "reqonly")) {
09648                ast_set_flag(user, IAX_CODEC_NOCAP);
09649                ast_set_flag(user, IAX_CODEC_NOPREFS);
09650             }
09651          } else if (!strcasecmp(v->name, "jitterbuffer")) {
09652             ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF);
09653          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
09654             ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF);
09655          } else if (!strcasecmp(v->name, "dbsecret")) {
09656             ast_string_field_set(user, dbsecret, v->value);
09657          } else if (!strcasecmp(v->name, "secret")) {
09658             if (!ast_strlen_zero(user->secret)) {
09659                char *old = ast_strdupa(user->secret);
09660 
09661                ast_string_field_build(user, secret, "%s;%s", old, v->value);
09662             } else
09663                ast_string_field_set(user, secret, v->value);
09664          } else if (!strcasecmp(v->name, "callerid")) {
09665             if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) {
09666                char name2[80];
09667                char num2[80];
09668                ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
09669                ast_string_field_set(user, cid_name, name2);
09670                ast_string_field_set(user, cid_num, num2);
09671                ast_set_flag(user, IAX_HASCALLERID);
09672             } else {
09673                ast_clear_flag(user, IAX_HASCALLERID);
09674                ast_string_field_set(user, cid_name, "");
09675                ast_string_field_set(user, cid_num, "");
09676             }
09677          } else if (!strcasecmp(v->name, "fullname")) {
09678             if (!ast_strlen_zero(v->value)) {
09679                ast_string_field_set(user, cid_name, v->value);
09680                ast_set_flag(user, IAX_HASCALLERID);
09681             } else {
09682                ast_string_field_set(user, cid_name, "");
09683                if (ast_strlen_zero(user->cid_num))
09684                   ast_clear_flag(user, IAX_HASCALLERID);
09685             }
09686          } else if (!strcasecmp(v->name, "cid_number")) {
09687             if (!ast_strlen_zero(v->value)) {
09688                ast_string_field_set(user, cid_num, v->value);
09689                ast_set_flag(user, IAX_HASCALLERID);
09690             } else {
09691                ast_string_field_set(user, cid_num, "");
09692                if (ast_strlen_zero(user->cid_name))
09693                   ast_clear_flag(user, IAX_HASCALLERID);
09694             }
09695          } else if (!strcasecmp(v->name, "accountcode")) {
09696             ast_string_field_set(user, accountcode, v->value);
09697          } else if (!strcasecmp(v->name, "mohinterpret")) {
09698             ast_string_field_set(user, mohinterpret, v->value);
09699          } else if (!strcasecmp(v->name, "mohsuggest")) {
09700             ast_string_field_set(user, mohsuggest, v->value);
09701          } else if (!strcasecmp(v->name, "language")) {
09702             ast_string_field_set(user, language, v->value);
09703          } else if (!strcasecmp(v->name, "amaflags")) {
09704             format = ast_cdr_amaflags2int(v->value);
09705             if (format < 0) {
09706                ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
09707             } else {
09708                user->amaflags = format;
09709             }
09710          } else if (!strcasecmp(v->name, "inkeys")) {
09711             ast_string_field_set(user, inkeys, v->value);
09712          } else if (!strcasecmp(v->name, "maxauthreq")) {
09713             user->maxauthreq = atoi(v->value);
09714             if (user->maxauthreq < 0)
09715                user->maxauthreq = 0;
09716          } else if (!strcasecmp(v->name, "adsi")) {
09717             user->adsi = ast_true(v->value);
09718          }/* else if (strcasecmp(v->name,"type")) */
09719          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09720          v = v->next;
09721          if (!v) {
09722             v = alt;
09723             alt = NULL;
09724          }
09725       }
09726       if (!user->authmethods) {
09727          if (!ast_strlen_zero(user->secret)) {
09728             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09729             if (!ast_strlen_zero(user->inkeys))
09730                user->authmethods |= IAX_AUTH_RSA;
09731          } else if (!ast_strlen_zero(user->inkeys)) {
09732             user->authmethods = IAX_AUTH_RSA;
09733          } else {
09734             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09735          }
09736       }
09737       ast_clear_flag(user, IAX_DELME);
09738    }
09739 cleanup:
09740    if (oldha)
09741       ast_free_ha(oldha);
09742    if (oldcon)
09743       free_context(oldcon);
09744    return user;
09745 }

static int cache_get_callno_locked ( const char *  data  )  [static]

Definition at line 10250 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(), chan_iax2_pvt::capability, create_addr(), 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, LOG_WARNING, NEW_FORCE, option_debug, parse_dial_string(), secret, and send_command().

Referenced by find_cache().

10251 {
10252    struct sockaddr_in sin;
10253    int x;
10254    int callno;
10255    struct iax_ie_data ied;
10256    struct create_addr_info cai;
10257    struct parsed_dial_string pds;
10258    char *tmpstr;
10259 
10260    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
10261       /* Look for an *exact match* call.  Once a call is negotiated, it can only
10262          look up entries for a single context */
10263       if (!ast_mutex_trylock(&iaxsl[x])) {
10264          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
10265             return x;
10266          ast_mutex_unlock(&iaxsl[x]);
10267       }
10268    }
10269 
10270    /* No match found, we need to create a new one */
10271 
10272    memset(&cai, 0, sizeof(cai));
10273    memset(&ied, 0, sizeof(ied));
10274    memset(&pds, 0, sizeof(pds));
10275 
10276    tmpstr = ast_strdupa(data);
10277    parse_dial_string(tmpstr, &pds);
10278 
10279    if (ast_strlen_zero(pds.peer)) {
10280       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data);
10281       return -1;
10282    }
10283 
10284    /* Populate our address from the given */
10285    if (create_addr(pds.peer, NULL, &sin, &cai))
10286       return -1;
10287 
10288    if (option_debug)
10289       ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
10290          pds.peer, pds.username, pds.password, pds.context);
10291 
10292    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
10293    if (callno < 1) {
10294       ast_log(LOG_WARNING, "Unable to create call\n");
10295       return -1;
10296    }
10297 
10298    ast_string_field_set(iaxs[callno], dproot, data);
10299    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
10300 
10301    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
10302    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
10303    /* the string format is slightly different from a standard dial string,
10304       because the context appears in the 'exten' position
10305    */
10306    if (pds.exten)
10307       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
10308    if (pds.username)
10309       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
10310    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
10311    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
10312    /* Keep password handy */
10313    if (pds.password)
10314       ast_string_field_set(iaxs[callno], secret, pds.password);
10315    if (pds.key)
10316       ast_string_field_set(iaxs[callno], outkey, pds.key);
10317    /* Start the call going */
10318    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
10319 
10320    return callno;
10321 }

static unsigned int calc_rxstamp ( struct chan_iax2_pvt p,
unsigned int  offset 
) [static]

Definition at line 3969 of file chan_iax2.c.

References ast_log(), ast_random(), ast_tvsub(), chan_iax2_pvt::callno, option_debug, and chan_iax2_pvt::rxcore.

03970 {
03971    /* Returns where in "receive time" we are.  That is, how many ms
03972       since we received (or would have received) the frame with timestamp 0 */
03973    int ms;
03974 #ifdef IAXTESTS
03975    int jit;
03976 #endif /* IAXTESTS */
03977    /* Setup rxcore if necessary */
03978    if (ast_tvzero(p->rxcore)) {
03979       p->rxcore = ast_tvnow();
03980       if (option_debug && iaxdebug)
03981          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
03982                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
03983       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
03984 #if 1
03985       if (option_debug && iaxdebug)
03986          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
03987                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
03988 #endif
03989    }
03990 
03991    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
03992 #ifdef IAXTESTS
03993    if (test_jit) {
03994       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
03995          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
03996          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
03997             jit = -jit;
03998          ms += jit;
03999       }
04000    }
04001    if (test_late) {
04002       ms += test_late;
04003       test_late = 0;
04004    }
04005 #endif /* IAXTESTS */
04006    return ms;
04007 }

static unsigned int calc_timestamp ( struct chan_iax2_pvt p,
unsigned int  ts,
struct ast_frame f 
) [static]

Definition at line 3840 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, f, iaxs, chan_iax2_pvt::lastsent, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, chan_iax2_pvt::offset, and option_debug.

Referenced by iax2_send(), and socket_process().

03841 {
03842    int ms;
03843    int voice = 0;
03844    int genuine = 0;
03845    int adjust;
03846    struct timeval *delivery = NULL;
03847 
03848 
03849    /* What sort of frame do we have?: voice is self-explanatory
03850       "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK
03851       non-genuine frames are CONTROL frames [ringing etc], DTMF
03852       The "genuine" distinction is needed because genuine frames must get a clock-based timestamp,
03853       the others need a timestamp slaved to the voice frames so that they go in sequence
03854    */
03855    if (f) {
03856       if (f->frametype == AST_FRAME_VOICE) {
03857          voice = 1;
03858          delivery = &f->delivery;
03859       } else if (f->frametype == AST_FRAME_IAX) {
03860          genuine = 1;
03861       } else if (f->frametype == AST_FRAME_CNG) {
03862          p->notsilenttx = 0;  
03863       }
03864    }
03865    if (ast_tvzero(p->offset)) {
03866       gettimeofday(&p->offset, NULL);
03867       /* Round to nearest 20ms for nice looking traces */
03868       p->offset.tv_usec -= p->offset.tv_usec % 20000;
03869    }
03870    /* If the timestamp is specified, just send it as is */
03871    if (ts)
03872       return ts;
03873    /* If we have a time that the frame arrived, always use it to make our timestamp */
03874    if (delivery && !ast_tvzero(*delivery)) {
03875       ms = ast_tvdiff_ms(*delivery, p->offset);
03876       if (option_debug > 2 && iaxdebug)
03877          ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno);
03878    } else {
03879       ms = ast_tvdiff_ms(ast_tvnow(), p->offset);
03880       if (ms < 0)
03881          ms = 0;
03882       if (voice) {
03883          /* On a voice frame, use predicted values if appropriate */
03884          if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
03885             /* Adjust our txcore, keeping voice and non-voice synchronized */
03886             /* AN EXPLANATION:
03887                When we send voice, we usually send "calculated" timestamps worked out
03888                on the basis of the number of samples sent. When we send other frames,
03889                we usually send timestamps worked out from the real clock.
03890                The problem is that they can tend to drift out of step because the 
03891                   source channel's clock and our clock may not be exactly at the same rate.
03892                We fix this by continuously "tweaking" p->offset.  p->offset is "time zero"
03893                for this call.  Moving it adjusts timestamps for non-voice frames.
03894                We make the adjustment in the style of a moving average.  Each time we
03895                adjust p->offset by 10% of the difference between our clock-derived
03896                timestamp and the predicted timestamp.  That's why you see "10000"
03897                below even though IAX2 timestamps are in milliseconds.
03898                The use of a moving average avoids offset moving too radically.
03899                Generally, "adjust" roams back and forth around 0, with offset hardly
03900                changing at all.  But if a consistent different starts to develop it
03901                will be eliminated over the course of 10 frames (200-300msecs) 
03902             */
03903             adjust = (ms - p->nextpred);
03904             if (adjust < 0)
03905                p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000));
03906             else if (adjust > 0)
03907                p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000));
03908 
03909             if (!p->nextpred) {
03910                p->nextpred = ms; /*f->samples / 8;*/
03911                if (p->nextpred <= p->lastsent)
03912                   p->nextpred = p->lastsent + 3;
03913             }
03914             ms = p->nextpred;
03915          } else {
03916                 /* in this case, just use the actual
03917             * time, since we're either way off
03918             * (shouldn't happen), or we're  ending a
03919             * silent period -- and seed the next
03920             * predicted time.  Also, round ms to the
03921             * next multiple of frame size (so our
03922             * silent periods are multiples of
03923             * frame size too) */
03924 
03925             if (option_debug && iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW )
03926                ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n",
03927                   abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW);
03928 
03929             if (f->samples >= 8) /* check to make sure we dont core dump */
03930             {
03931                int diff = ms % (f->samples / 8);
03932                if (diff)
03933                    ms += f->samples/8 - diff;
03934             }
03935 
03936             p->nextpred = ms;
03937             p->notsilenttx = 1;
03938          }
03939       } else if ( f->frametype == AST_FRAME_VIDEO ) {
03940          /*
03941          * IAX2 draft 03 says that timestamps MUST be in order.
03942          * It does not say anything about several frames having the same timestamp
03943          * When transporting video, we can have a frame that spans multiple iax packets
03944          * (so called slices), so it would make sense to use the same timestamp for all of
03945          * them
03946          * We do want to make sure that frames don't go backwards though
03947          */
03948          if ( (unsigned int)ms < p->lastsent )
03949             ms = p->lastsent;
03950       } else {
03951          /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless
03952             it's a genuine frame */
03953          if (genuine) {
03954             /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */
03955             if (ms <= p->lastsent)
03956                ms = p->lastsent + 3;
03957          } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) {
03958             /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */
03959             ms = p->lastsent + 3;
03960          }
03961       }
03962    }
03963    p->lastsent = ms;
03964    if (voice)
03965       p->nextpred = p->nextpred + f->samples / 8;
03966    return ms;
03967 }

static unsigned int calc_txpeerstamp ( struct iax2_trunk_peer tpeer,
int  sampms,
struct timeval *  tv 
) [static]

Definition at line 3796 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().

03797 {
03798    unsigned long int mssincetx; /* unsigned to handle overflows */
03799    long int ms, pred;
03800 
03801    tpeer->trunkact = *tv;
03802    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03803    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03804       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03805       tpeer->txtrunktime = *tv;
03806       tpeer->lastsent = 999999;
03807    }
03808    /* Update last transmit time now */
03809    tpeer->lasttxtime = *tv;
03810    
03811    /* Calculate ms offset */
03812    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03813    /* Predict from last value */
03814    pred = tpeer->lastsent + sampms;
03815    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03816       ms = pred;
03817    
03818    /* We never send the same timestamp twice, so fudge a little if we must */
03819    if (ms == tpeer->lastsent)
03820       ms = tpeer->lastsent + 1;
03821    tpeer->lastsent = ms;
03822    return ms;
03823 }

static int check_access ( int  callno,
struct sockaddr_in *  sin,
struct iax_ies ies 
) [static]

Definition at line 5080 of file chan_iax2.c.

References iax2_user::adsi, chan_iax2_pvt::adsi, chan_iax2_pvt::amaflags, iax2_user::amaflags, ao2_iterator_init(), ao2_iterator_next(), apply_context(), ast_apply_ha(), ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_inet_ntoa(), ast_log(), AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, ast_set2_flag, ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_variable_new(), iax2_user::authmethods, chan_iax2_pvt::authmethods, chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, iax2_user::capability, chan_iax2_pvt::capability, cid_name, cid_num, iax2_context::context, iax2_user::contexts, iax2_user::encmethods, chan_iax2_pvt::encmethods, exten, 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, ies, 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, realtime_user(), secret, user_unref(), users, ast_variable::value, chan_iax2_pvt::vars, and iax2_user::vars.

Referenced by socket_process().

05081 {
05082    /* Start pessimistic */
05083    int res = -1;
05084    int version = 2;
05085    struct iax2_user *user = NULL, *best = NULL;
05086    int bestscore = 0;
05087    int gotcapability = 0;
05088    struct ast_variable *v = NULL, *tmpvar = NULL;
05089    struct ao2_iterator i;
05090 
05091    if (!iaxs[callno])
05092       return res;
05093    if (ies->called_number)
05094       ast_string_field_set(iaxs[callno], exten, ies->called_number);
05095    if (ies->calling_number) {
05096       ast_shrink_phone_number(ies->calling_number);
05097       ast_string_field_set(iaxs[callno], cid_num, ies->calling_number);
05098    }
05099    if (ies->calling_name)
05100       ast_string_field_set(iaxs[callno], cid_name, ies->calling_name);
05101    if (ies->calling_ani)
05102       ast_string_field_set(iaxs[callno], ani, ies->calling_ani);
05103    if (ies->dnid)
05104       ast_string_field_set(iaxs[callno], dnid, ies->dnid);
05105    if (ies->rdnis)
05106       ast_string_field_set(iaxs[callno], rdnis, ies->rdnis);
05107    if (ies->called_context)
05108       ast_string_field_set(iaxs[callno], context, ies->called_context);
05109    if (ies->language)
05110       ast_string_field_set(iaxs[callno], language, ies->language);
05111    if (ies->username)
05112       ast_string_field_set(iaxs[callno], username, ies->username);
05113    if (ies->calling_ton > -1)
05114       iaxs[callno]->calling_ton = ies->calling_ton;
05115    if (ies->calling_tns > -1)
05116       iaxs[callno]->calling_tns = ies->calling_tns;
05117    if (ies->calling_pres > -1)
05118       iaxs[callno]->calling_pres = ies->calling_pres;
05119    if (ies->format)
05120       iaxs[callno]->peerformat = ies->format;
05121    if (ies->adsicpe)
05122       iaxs[callno]->peeradsicpe = ies->adsicpe;
05123    if (ies->capability) {
05124       gotcapability = 1;
05125       iaxs[callno]->peercapability = ies->capability;
05126    } 
05127    if (ies->version)
05128       version = ies->version;
05129 
05130    /* Use provided preferences until told otherwise for actual preferences */
05131    if(ies->codec_prefs) {
05132       ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
05133       ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
05134    }
05135 
05136    if (!gotcapability) 
05137       iaxs[callno]->peercapability = iaxs[callno]->peerformat;
05138    if (version > IAX_PROTO_VERSION) {
05139       ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 
05140          ast_inet_ntoa(sin->sin_addr), version);
05141       return res;
05142    }
05143    /* Search the userlist for a compatible entry, and fill in the rest */
05144    i = ao2_iterator_init(users, 0);
05145    while ((user = ao2_iterator_next(&i))) {
05146       if ((ast_strlen_zero(iaxs[callno]->username) ||          /* No username specified */
05147          !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */
05148          && ast_apply_ha(user->ha, sin)   /* Access is permitted from this IP */
05149          && (ast_strlen_zero(iaxs[callno]->context) ||         /* No context specified */
05150               apply_context(user->contexts, iaxs[callno]->context))) {        /* Context is permitted */
05151          if (!ast_strlen_zero(iaxs[callno]->username)) {
05152             /* Exact match, stop right now. */
05153             if (best)
05154                user_unref(best);
05155             best = user;
05156             break;
05157          } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) {
05158             /* No required authentication */
05159             if (user->ha) {
05160                /* There was host authentication and we passed, bonus! */
05161                if (bestscore < 4) {
05162                   bestscore = 4;
05163                   if (best)
05164                      user_unref(best);
05165                   best = user;
05166                   continue;
05167                }
05168             } else {
05169                /* No host access, but no secret, either, not bad */
05170                if (bestscore < 3) {
05171                   bestscore = 3;
05172                   if (best)
05173                      user_unref(best);
05174                   best = user;
05175                   continue;
05176                }
05177             }
05178          } else {
05179             if (user->ha) {
05180                /* Authentication, but host access too, eh, it's something.. */
05181                if (bestscore < 2) {
05182                   bestscore = 2;
05183                   if (best)
05184                      user_unref(best);
05185                   best = user;
05186                   continue;
05187                }
05188             } else {
05189                /* Authentication and no host access...  This is our baseline */
05190                if (bestscore < 1) {
05191                   bestscore = 1;
05192                   if (best)
05193                      user_unref(best);
05194                   best = user;
05195                   continue;
05196                }
05197             }
05198          }
05199       }
05200       user_unref(user);
05201    }
05202    user = best;
05203    if (!user && !ast_strlen_zero(iaxs[callno]->username)) {
05204       user = realtime_user(iaxs[callno]->username, sin);
05205       if (user && !ast_strlen_zero(iaxs[callno]->context) &&         /* No context specified */
05206           !apply_context(user->contexts, iaxs[callno]->context)) {      /* Context is permitted */
05207          user = user_unref(user);
05208       }
05209    }
05210    if (user) {
05211       /* We found our match (use the first) */
05212       /* copy vars */
05213       for (v = user->vars ; v ; v = v->next) {
05214          if((tmpvar = ast_variable_new(v->name, v->value))) {
05215             tmpvar->next = iaxs[callno]->vars; 
05216             iaxs[callno]->vars = tmpvar;
05217          }
05218       }
05219       /* If a max AUTHREQ restriction is in place, activate it */
05220       if (user->maxauthreq > 0)
05221          ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ);
05222       iaxs[callno]->prefs = user->prefs;
05223       ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST);
05224       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS);
05225       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP);
05226       iaxs[callno]->encmethods = user->encmethods;
05227       /* Store the requested username if not specified */
05228       if (ast_strlen_zero(iaxs[callno]->username))
05229          ast_string_field_set(iaxs[callno], username, user->name);
05230       /* Store whether this is a trunked call, too, of course, and move if appropriate */
05231       ast_copy_flags(iaxs[callno], user, IAX_TRUNK);
05232       iaxs[callno]->capability = user->capability;
05233       /* And use the default context */
05234       if (ast_strlen_zero(iaxs[callno]->context)) {
05235          if (user->contexts)
05236             ast_string_field_set(iaxs[callno], context, user->contexts->context);
05237          else
05238             ast_string_field_set(iaxs[callno], context, context);
05239       }
05240       /* And any input keys */
05241       ast_string_field_set(iaxs[callno], inkeys, user->inkeys);
05242       /* And the permitted authentication methods */
05243       iaxs[callno]->authmethods = user->authmethods;
05244       iaxs[callno]->adsi = user->adsi;
05245       /* If they have callerid, override the given caller id.  Always store the ANI */
05246       if (!ast_strlen_zero(iaxs[callno]->cid_num) || !ast_strlen_zero(iaxs[callno]->cid_name)) {
05247          if (ast_test_flag(user, IAX_HASCALLERID)) {
05248             iaxs[callno]->calling_tns = 0;
05249             iaxs[callno]->calling_ton = 0;
05250             ast_string_field_set(iaxs[callno], cid_num, user->cid_num);
05251             ast_string_field_set(iaxs[callno], cid_name, user->cid_name);
05252             iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
05253          }
05254          if (ast_strlen_zero(iaxs[callno]->ani))
05255             ast_string_field_set(iaxs[callno], ani, user->cid_num);
05256       } else {
05257          iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE;
05258       }
05259       if (!ast_strlen_zero(user->accountcode))
05260          ast_string_field_set(iaxs[callno], accountcode, user->accountcode);
05261       if (!ast_strlen_zero(user->mohinterpret))
05262          ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret);
05263       if (!ast_strlen_zero(user->mohsuggest))
05264          ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest);
05265       if (user->amaflags)
05266          iaxs[callno]->amaflags = user->amaflags;
05267       if (!ast_strlen_zero(user->language))
05268          ast_string_field_set(iaxs[callno], language, user->language);
05269       ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);   
05270       /* Keep this check last */
05271       if (!ast_strlen_zero(user->dbsecret)) {
05272          char *family, *key=NULL;
05273          char buf[80];
05274          family = ast_strdupa(user->dbsecret);
05275          key = strchr(family, '/');
05276          if (key) {
05277             *key = '\0';
05278             key++;
05279          }
05280          if (!key || ast_db_get(family, key, buf, sizeof(buf)))
05281             ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret);
05282          else
05283             ast_string_field_set(iaxs[callno], secret, buf);
05284       } else
05285          ast_string_field_set(iaxs[callno], secret, user->secret);
05286       res = 0;
05287       user = user_unref(user);
05288    }
05289    ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);  
05290    return res;
05291 }

static int check_provisioning ( struct sockaddr_in *  sin,
int  sockfd,
char *  si,
unsigned int  ver 
) [static]

Definition at line 6766 of file chan_iax2.c.

References ast_log(), iax2_provision(), iax_provision_version(), and option_debug.

Referenced by socket_process().

06767 {
06768    unsigned int ourver;
06769    char rsi[80];
06770    snprintf(rsi, sizeof(rsi), "si-%s", si);
06771    if (iax_provision_version(&ourver, rsi, 1))
06772       return 0;
06773    if (option_debug)
06774       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06775    if (ourver != ver) 
06776       iax2_provision(sin, sockfd, NULL, rsi, 1);
06777    return 0;
06778 }

static int check_srcaddr ( struct sockaddr *  sa,
socklen_t  salen 
) [static]

Check if address can be used as packet source.

Returns:
0 address available, 1 address unavailable, -1 error

Definition at line 9173 of file chan_iax2.c.

References ast_log(), errno, LOG_ERROR, and option_debug.

Referenced by peer_set_srcaddr().

09174 {
09175    int sd;
09176    int res;
09177    
09178    sd = socket(AF_INET, SOCK_DGRAM, 0);
09179    if (sd < 0) {
09180       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
09181       return -1;
09182    }
09183 
09184    res = bind(sd, sa, salen);
09185    if (res < 0) {
09186       if (option_debug)
09187          ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
09188       close(sd);
09189       return 1;
09190    }
09191 
09192    close(sd);
09193    return 0;
09194 }

static int complete_dpreply ( struct chan_iax2_pvt pvt,
struct iax_ies ies 
) [static]

Definition at line 5770 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, iax2_dpcache::callno, chan_iax2_pvt::dpentries, 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, ies, iax2_dpcache::orig, iax2_dpcache::peer, and iax2_dpcache::waiters.

Referenced by socket_process().

05771 {
05772    char exten[256] = "";
05773    int status = CACHE_FLAG_UNKNOWN;
05774    int expiry = iaxdefaultdpcache;
05775    int x;
05776    int matchmore = 0;
05777    struct iax2_dpcache *dp, *prev;
05778    
05779    if (ies->called_number)
05780       ast_copy_string(exten, ies->called_number, sizeof(exten));
05781 
05782    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
05783       status = CACHE_FLAG_EXISTS;
05784    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
05785       status = CACHE_FLAG_CANEXIST;
05786    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
05787       status = CACHE_FLAG_NONEXISTENT;
05788 
05789    if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
05790       /* Don't really do anything with this */
05791    }
05792    if (ies->refresh)
05793       expiry = ies->refresh;
05794    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
05795       matchmore = CACHE_FLAG_MATCHMORE;
05796    ast_mutex_lock(&dpcache_lock);
05797    prev = NULL;
05798    dp = pvt->dpentries;
05799    while(dp) {
05800       if (!strcmp(dp->exten, exten)) {
05801          /* Let them go */
05802          if (prev)
05803             prev->peer = dp->peer;
05804          else
05805             pvt->dpentries = dp->peer;
05806          dp->peer = NULL;
05807          dp->callno = 0;
05808          dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
05809          if (dp->flags & CACHE_FLAG_PENDING) {
05810             dp->flags &= ~CACHE_FLAG_PENDING;
05811             dp->flags |= status;
05812             dp->flags |= matchmore;
05813          }
05814          /* Wake up waiters */
05815          for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
05816             if (dp->waiters[x] > -1)
05817                write(dp->waiters[x], "asdf", 4);
05818       }
05819       prev = dp;
05820       dp = dp->peer;
05821    }
05822    ast_mutex_unlock(&dpcache_lock);
05823    return 0;
05824 }

static char* complete_iax2_show_peer ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 2389 of file chan_iax2.c.

References ao2_iterator_init(), ao2_iterator_next(), ast_strdup, peer_unref(), and peers.

02390 {
02391    int which = 0;
02392    struct iax2_peer *peer;
02393    char *res = NULL;
02394    int wordlen = strlen(word);
02395    struct ao2_iterator i;
02396 
02397    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02398    if (pos != 3)
02399       return NULL;
02400 
02401    i = ao2_iterator_init(peers, 0);
02402    while ((peer = ao2_iterator_next(&i))) {
02403       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02404          res = ast_strdup(peer->name);
02405          peer_unref(peer);
02406          break;
02407       }
02408       peer_unref(peer);
02409    }
02410 
02411    return res;
02412 }

static int complete_transfer ( int  callno,
struct iax_ies ies 
) [static]

Definition at line 5826 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, jb_frame::data, DEFAULT_RETRY_TIME, iax2_frame_free(), iaxq, iaxs, ies, 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().

05827 {
05828    int peercallno = 0;
05829    struct chan_iax2_pvt *pvt = iaxs[callno];
05830    struct iax_frame *cur;
05831    jb_frame frame;
05832 
05833    if (ies->callno)
05834       peercallno = ies->callno;
05835 
05836    if (peercallno < 1) {
05837       ast_log(LOG_WARNING, "Invalid transfer request\n");
05838       return -1;
05839    }
05840    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
05841    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
05842    /* Reset sequence numbers */
05843    pvt->oseqno = 0;
05844    pvt->rseqno = 0;
05845    pvt->iseqno = 0;
05846    pvt->aseqno = 0;
05847 
05848    if (pvt->peercallno) {
05849       remove_by_peercallno(pvt);
05850    }
05851    pvt->peercallno = peercallno;
05852    store_by_peercallno(pvt);
05853 
05854    pvt->transferring = TRANSFER_NONE;
05855    pvt->svoiceformat = -1;
05856    pvt->voiceformat = 0;
05857    pvt->svideoformat = -1;
05858    pvt->videoformat = 0;
05859    pvt->transfercallno = -1;
05860    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
05861    memset(&pvt->offset, 0, sizeof(pvt->offset));
05862    /* reset jitterbuffer */
05863    while(jb_getall(pvt->jb,&frame) == JB_OK)
05864       iax2_frame_free(frame.data);
05865    jb_reset(pvt->jb);
05866    pvt->lag = 0;
05867    pvt->last = 0;
05868    pvt->lastsent = 0;
05869    pvt->nextpred = 0;
05870    pvt->pingtime = DEFAULT_RETRY_TIME;
05871    AST_LIST_LOCK(&iaxq.queue);
05872    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
05873       /* We must cancel any packets that would have been transmitted
05874          because now we're talking to someone new.  It's okay, they
05875          were transmitted to someone that didn't care anyway. */
05876       if (callno == cur->callno) 
05877          cur->retries = -1;
05878    }
05879    AST_LIST_UNLOCK(&iaxq.queue);
05880    return 0; 
05881 }

static unsigned char compress_subclass ( int  subclass  )  [static]

Definition at line 1061 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().

01062 {
01063    int x;
01064    int power=-1;
01065    /* If it's 128 or smaller, just return it */
01066    if (subclass < IAX_FLAG_SC_LOG)
01067       return subclass;
01068    /* Otherwise find its power */
01069    for (x = 0; x < IAX_MAX_SHIFT; x++) {
01070       if (subclass & (1 << x)) {
01071          if (power > -1) {
01072             ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass);
01073             return 0;
01074          } else
01075             power = x;
01076       }
01077    }
01078    return power | IAX_FLAG_SC_LOG;
01079 }

static void construct_rr ( struct chan_iax2_pvt pvt,
struct iax_ie_data iep 
) [static]

Definition at line 6780 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().

06781 {
06782    jb_info stats;
06783    jb_getinfo(pvt->jb, &stats);
06784    
06785    memset(iep, 0, sizeof(*iep));
06786 
06787    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06788    if(stats.frames_in == 0) stats.frames_in = 1;
06789    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06790    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06791    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06792    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06793    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06794 }

static int create_addr ( const char *  peername,
struct ast_channel c,
struct sockaddr_in *  sin,
struct create_addr_info cai 
) [static]

Definition at line 3006 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ahp, 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_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.

03007 {
03008    struct ast_hostent ahp;
03009    struct hostent *hp;
03010    struct iax2_peer *peer;
03011    int res = -1;
03012    struct ast_codec_pref ourprefs;
03013 
03014    ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
03015    cai->sockfd = defaultsockfd;
03016    cai->maxtime = 0;
03017    sin->sin_family = AF_INET;
03018 
03019    if (!(peer = find_peer(peername, 1))) {
03020       cai->found = 0;
03021 
03022       hp = ast_gethostbyname(peername, &ahp);
03023       if (hp) {
03024          memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
03025          sin->sin_port = htons(IAX_DEFAULT_PORTNO);
03026          /* use global iax prefs for unknown peer/user */
03027          /* But move the calling channel's native codec to the top of the preference list */
03028          memcpy(&ourprefs, &prefs, sizeof(ourprefs));
03029          if (c)
03030             ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
03031          ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
03032          return 0;
03033       } else {
03034          ast_log(LOG_WARNING, "No such host: %s\n", peername);
03035          return -1;
03036       }
03037    }
03038 
03039    cai->found = 1;
03040    
03041    /* if the peer has no address (current or default), return failure */
03042    if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr))
03043       goto return_unref;
03044 
03045    /* if the peer is being monitored and is currently unreachable, return failure */
03046    if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
03047       goto return_unref;
03048 
03049    ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
03050    cai->maxtime = peer->maxms;
03051    cai->capability = peer->capability;
03052    cai->encmethods = peer->encmethods;
03053    cai->sockfd = peer->sockfd;
03054    cai->adsi = peer->adsi;
03055    memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
03056    /* Move the calling channel's native codec to the top of the preference list */
03057    if (c) {
03058       ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats);
03059       ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
03060    }
03061    ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
03062    ast_copy_string(cai->context, peer->context, sizeof(cai->context));
03063    ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
03064    ast_copy_string(cai->username, peer->username, sizeof(cai->username));
03065    ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
03066    ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
03067    ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
03068    ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
03069    if (ast_strlen_zero(peer->dbsecret)) {
03070       ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret));
03071    } else {
03072       char *family;
03073       char *key = NULL;
03074 
03075       family = ast_strdupa(peer->dbsecret);
03076       key = strchr(family, '/');
03077       if (key)
03078          *key++ = '\0';
03079       if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) {
03080          ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret);
03081          goto return_unref;
03082       }
03083    }
03084 
03085    if (peer->addr.sin_addr.s_addr) {
03086       sin->sin_addr = peer->addr.sin_addr;
03087       sin->sin_port = peer->addr.sin_port;
03088    } else {
03089       sin->sin_addr = peer->defaddr.sin_addr;
03090       sin->sin_port = peer->defaddr.sin_port;
03091    }
03092 
03093    res = 0;
03094 
03095 return_unref:
03096    peer_unref(peer);
03097 
03098    return res;
03099 }

static int decode_frame ( aes_decrypt_ctx dcx,
struct ast_iax2_full_hdr fh,
struct ast_frame f,
int *  datalen 
) [static]

Definition at line 4155 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, f, IAX_FLAG_FULL, memcpy_decrypt(), option_debug, ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::type, and uncompress_subclass().

Referenced by decrypt_frame().

04156 {
04157    int padding;
04158    unsigned char *workspace;
04159 
04160    workspace = alloca(*datalen);
04161    memset(f, 0, sizeof(*f));
04162    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04163       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04164       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
04165          return -1;
04166       /* Decrypt */
04167       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
04168 
04169       padding = 16 + (workspace[15] & 0xf);
04170       if (option_debug && iaxdebug)
04171          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
04172       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
04173          return -1;
04174 
04175       *datalen -= padding;
04176       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04177       f->frametype = fh->type;
04178       if (f->frametype == AST_FRAME_VIDEO) {
04179          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
04180       } else {
04181          f->subclass = uncompress_subclass(fh->csub);
04182       }
04183    } else {
04184       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04185       if (option_debug && iaxdebug)
04186          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
04187       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
04188          return -1;
04189       /* Decrypt */
04190       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
04191       padding = 16 + (workspace[15] & 0x0f);
04192       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
04193          return -1;
04194       *datalen -= padding;
04195       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04196    }
04197    return 0;
04198 }

static int decrypt_frame ( int  callno,
struct ast_iax2_full_hdr fh,
struct ast_frame f,
int *  datalen 
) [static]

Definition at line 4241 of file chan_iax2.c.

References ast_set_flag, ast_strdupa, ast_test_flag, build_enc_keys(), decode_frame(), f, IAX_KEYPOPULATED, iaxs, md5(), MD5Final(), MD5Init(), MD5Update(), secret, and strsep().

Referenced by socket_process().

04242 {
04243    int res=-1;
04244    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04245       /* Search for possible keys, given secrets */
04246       struct MD5Context md5;
04247       unsigned char digest[16];
04248       char *tmppw, *stringp;
04249       
04250       tmppw = ast_strdupa(iaxs[callno]->secret);
04251       stringp = tmppw;
04252       while ((tmppw = strsep(&stringp, ";"))) {
04253          MD5Init(&md5);
04254          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04255          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04256          MD5Final(digest, &md5);
04257          build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx);
04258          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04259          if (!res) {
04260             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04261             break;
04262          }
04263       }
04264    } else 
04265       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04266    return res;
04267 }

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 6842 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().

06843 {
06844    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06845    struct ast_iax2_full_hdr *fh, *cur_fh;
06846 
06847    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06848       return;
06849 
06850    pkt_buf->len = from_here->buf_len;
06851    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06852 
06853    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06854    ast_mutex_lock(&to_here->lock);
06855    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06856       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06857       if (fh->oseqno < cur_fh->oseqno) {
06858          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06859          break;
06860       }
06861    }
06862    AST_LIST_TRAVERSE_SAFE_END
06863 
06864    if (!cur_pkt_buf)
06865       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06866    
06867    ast_mutex_unlock(&to_here->lock);
06868 }

static void delete_users ( void   )  [static]

Definition at line 9765 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, sched, user_delme_cb(), and users.

09766 {
09767    struct iax2_registry *reg;
09768 
09769    ao2_callback(users, 0, user_delme_cb, NULL);
09770 
09771    AST_LIST_LOCK(&registrations);
09772    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09773       ast_sched_del(sched, reg->expire);
09774       if (reg->callno) {
09775          ast_mutex_lock(&iaxsl[reg->callno]);
09776          if (iaxs[reg->callno]) {
09777             iaxs[reg->callno]->reg = NULL;
09778             iax2_destroy(reg->callno);
09779          }
09780          ast_mutex_unlock(&iaxsl[reg->callno]);
09781       }
09782       if (reg->dnsmgr)
09783          ast_dnsmgr_release(reg->dnsmgr);
09784       free(reg);
09785    }
09786    AST_LIST_UNLOCK(&registrations);
09787 
09788    ao2_callback(peers, 0, peer_delme_cb, NULL);
09789 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1740 of file chan_iax2.c.

References ast_iax2_firmware_header::datalen, iax_firmware::fd, free, and iax_firmware::fwh.

Referenced by reload_firmware().

01741 {
01742    /* Close firmware */
01743    if (cur->fwh) {
01744       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01745    }
01746    close(cur->fd);
01747    free(cur);
01748 }

static void dp_lookup ( int  callno,
const char *  context,
const char *  callednum,
const char *  callerid,
int  skiplock 
) [static]

Definition at line 6614 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_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, and send_command().

Referenced by dp_lookup_thread(), and socket_process().

06615 {
06616    unsigned short dpstatus = 0;
06617    struct iax_ie_data ied1;
06618    int mm;
06619 
06620    memset(&ied1, 0, sizeof(ied1));
06621    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06622    /* Must be started */
06623    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06624       dpstatus = IAX_DPSTATUS_EXISTS;
06625    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06626       dpstatus = IAX_DPSTATUS_CANEXIST;
06627    } else {
06628       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06629    }
06630    if (ast_ignore_pattern(context, callednum))
06631       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06632    if (mm)
06633       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06634    if (!skiplock)
06635       ast_mutex_lock(&iaxsl[callno]);
06636    if (iaxs[callno]) {
06637       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06638       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06639       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06640       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06641    }
06642    if (!skiplock)
06643       ast_mutex_unlock(&iaxsl[callno]);
06644 }

static void* dp_lookup_thread ( void *  data  )  [static]

Definition at line 6646 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().

06647 {
06648    /* Look up for dpreq */
06649    struct dpreq_data *dpr = data;
06650    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06651    if (dpr->callerid)
06652       free(dpr->callerid);
06653    free(dpr);
06654    return NULL;
06655 }

static int encrypt_frame ( aes_encrypt_ctx ecx,
struct ast_iax2_full_hdr fh,
unsigned char *  poo,
int *  datalen 
) [static]

Definition at line 4200 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, memcpy_encrypt(), option_debug, ast_iax2_full_hdr::scallno, and ast_iax2_full_hdr::type.

Referenced by iax2_send().

04201 {
04202    int padding;
04203    unsigned char *workspace;
04204    workspace = alloca(*datalen + 32);
04205    if (!workspace)
04206       return -1;
04207    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04208       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04209       if (option_debug && iaxdebug)
04210          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
04211       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
04212       padding = 16 + (padding & 0xf);
04213       memcpy(workspace, poo, padding);
04214       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04215       workspace[15] &= 0xf0;
04216       workspace[15] |= (padding & 0xf);
04217       if (option_debug && iaxdebug)
04218          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]);
04219       *datalen += padding;
04220       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
04221       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
04222          memcpy(poo, workspace + *datalen - 32, 32);
04223    } else {
04224       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04225       if (option_debug && iaxdebug)
04226          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
04227       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
04228       padding = 16 + (padding & 0xf);
04229       memcpy(workspace, poo, padding);
04230       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04231       workspace[15] &= 0xf0;
04232       workspace[15] |= (padding & 0x0f);
04233       *datalen += padding;
04234       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
04235       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
04236          memcpy(poo, workspace + *datalen - 32, 32);
04237    }
04238    return 0;
04239 }

static int expire_registry ( const void *  data  )  [static]

Definition at line 6063 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

Referenced by iax2_prune_realtime(), reg_source_db(), and update_registry().

06064 {
06065 #ifdef SCHED_MULTITHREADED
06066    if (schedule_action(__expire_registry, data))
06067 #endif      
06068       __expire_registry(data);
06069    return 0;
06070 }

static struct iax2_dpcache* find_cache ( struct ast_channel chan,
const char *  data,
const char *  context,
const char *  exten,
int  priority 
) [static]

Definition at line 10323 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, 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().

10324 {
10325    struct iax2_dpcache *dp, *prev = NULL, *next;
10326    struct timeval tv;
10327    int x;
10328    int com[2];
10329    int timeout;
10330    int old=0;
10331    int outfd;
10332    int abort;
10333    int callno;
10334    struct ast_channel *c;
10335    struct ast_frame *f;
10336    gettimeofday(&tv, NULL);
10337    dp = dpcache;
10338    while(dp) {
10339       next = dp->next;
10340       /* Expire old caches */
10341       if (ast_tvcmp(tv, dp->expiry) > 0) {
10342             /* It's expired, let it disappear */
10343             if (prev)
10344                prev->next = dp->next;
10345             else
10346                dpcache = dp->next;
10347             if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) {
10348                /* Free memory and go again */
10349                free(dp);
10350             } else {
10351                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);
10352             }
10353             dp = next;
10354             continue;
10355       }
10356       /* We found an entry that matches us! */
10357       if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 
10358          break;
10359       prev = dp;
10360       dp = next;
10361    }
10362    if (!dp) {
10363       /* No matching entry.  Create a new one. */
10364       /* First, can we make a callno? */
10365       callno = cache_get_callno_locked(data);
10366       if (callno < 0) {
10367          ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data);
10368          return NULL;
10369       }
10370       if (!(dp = ast_calloc(1, sizeof(*dp)))) {
10371          ast_mutex_unlock(&iaxsl[callno]);
10372          return NULL;
10373       }
10374       ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext));
10375       ast_copy_string(dp->exten, exten, sizeof(dp->exten));
10376       gettimeofday(&dp->expiry, NULL);
10377       dp->orig = dp->expiry;
10378       /* Expires in 30 mins by default */
10379       dp->expiry.tv_sec += iaxdefaultdpcache;
10380       dp->next = dpcache;
10381       dp->flags = CACHE_FLAG_PENDING;
10382       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10383          dp->waiters[x] = -1;
10384       dpcache = dp;
10385       dp->peer = iaxs[callno]->dpentries;
10386       iaxs[callno]->dpentries = dp;
10387       /* Send the request if we're already up */
10388       if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
10389          iax2_dprequest(dp, callno);
10390       ast_mutex_unlock(&iaxsl[callno]);
10391    }
10392    /* By here we must have a dp */
10393    if (dp->flags & CACHE_FLAG_PENDING) {
10394       /* Okay, here it starts to get nasty.  We need a pipe now to wait
10395          for a reply to come back so long as it's pending */
10396       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) {
10397          /* Find an empty slot */
10398          if (dp->waiters[x] < 0)
10399             break;
10400       }
10401       if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) {
10402          ast_log(LOG_WARNING, "No more waiter positions available\n");
10403          return NULL;
10404       }
10405       if (pipe(com)) {
10406          ast_log(LOG_WARNING, "Unable to create pipe for comm\n");
10407          return NULL;
10408       }
10409       dp->waiters[x] = com[1];
10410       /* Okay, now we wait */
10411       timeout = iaxdefaulttimeout * 1000;
10412       /* Temporarily unlock */
10413       ast_mutex_unlock(&dpcache_lock);
10414       /* Defer any dtmf */
10415       if (chan)
10416          old = ast_channel_defer_dtmf(chan);
10417       abort = 0;
10418       while(timeout) {
10419          c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
10420          if (outfd > -1) {
10421             break;
10422          }
10423          if (c) {
10424             f = ast_read(c);
10425             if (f)
10426                ast_frfree(f);
10427             else {
10428                /* Got hung up on, abort! */
10429                break;
10430                abort = 1;
10431             }
10432          }
10433       }
10434       if (!timeout) {
10435          ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
10436       }
10437       ast_mutex_lock(&dpcache_lock);
10438       dp->waiters[x] = -1;
10439       close(com[1]);
10440       close(com[0]);
10441       if (abort) {
10442          /* Don't interpret anything, just abort.  Not sure what th epoint
10443            of undeferring dtmf on a hung up channel is but hey whatever */
10444          if (!old && chan)
10445             ast_channel_undefer_dtmf(chan);
10446          return NULL;
10447       }
10448       if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
10449          /* Now to do non-independent analysis the results of our wait */
10450          if (dp->flags & CACHE_FLAG_PENDING) {
10451             /* Still pending... It's a timeout.  Wake everybody up.  Consider it no longer
10452                pending.  Don't let it take as long to timeout. */
10453             dp->flags &= ~CACHE_FLAG_PENDING;
10454             dp->flags |= CACHE_FLAG_TIMEOUT;
10455             /* Expire after only 60 seconds now.  This is designed to help reduce backlog in heavily loaded
10456                systems without leaving it unavailable once the server comes back online */
10457             dp->expiry.tv_sec = dp->orig.tv_sec + 60;
10458             for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10459                if (dp->waiters[x] > -1)
10460                   write(dp->waiters[x], "asdf", 4);
10461          }
10462       }
10463       /* Our caller will obtain the rest */
10464       if (!old && chan)
10465          ast_channel_undefer_dtmf(chan);
10466    }
10467    return dp;  
10468 }

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 1640 of file chan_iax2.c.

References __find_callno().

Referenced by iax2_poke_peer(), and socket_process().

01640                                                                                                                                     {
01641 
01642    return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame);
01643 }

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 1645 of file chan_iax2.c.

References __find_callno().

Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_provision(), iax2_request(), and socket_process().

01645                                                                                                                                            {
01646 
01647    return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame);
01648 }

static struct iax2_thread* find_idle_thread ( void   )  [static]

Definition at line 906 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, free, iax2_process_thread(), IAX_TYPE_DYNAMIC, iaxdynamicthreadcount, iaxmaxthreadcount, and thread.

Referenced by __schedule_action(), and socket_read().

00907 {
00908    pthread_attr_t attr;
00909    struct iax2_thread *thread = NULL;
00910 
00911    /* Pop the head of the list off */
00912    AST_LIST_LOCK(&idle_list);
00913    thread = AST_LIST_REMOVE_HEAD(&idle_list, list);
00914    AST_LIST_UNLOCK(&idle_list);
00915 
00916    /* If no idle thread is available from the regular list, try dynamic */
00917    if (thread == NULL) {
00918       AST_LIST_LOCK(&dynamic_list);
00919       thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list);
00920       /* Make sure we absolutely have a thread... if not, try to make one if allowed */
00921       if (thread == NULL && iaxmaxthreadcount > iaxdynamicthreadcount) {
00922          /* We need to MAKE a thread! */
00923          if ((thread = ast_calloc(1, sizeof(*thread)))) {
00924             thread->threadnum = iaxdynamicthreadcount;
00925             thread->type = IAX_TYPE_DYNAMIC;
00926             ast_mutex_init(&thread->lock);
00927             ast_cond_init(&thread->cond, NULL);
00928             pthread_attr_init(&attr);
00929             pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
00930             if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
00931                free(thread);
00932                thread = NULL;
00933             } else {
00934                /* All went well and the thread is up, so increment our count */
00935                iaxdynamicthreadcount++;
00936                
00937                /* Wait for the thread to be ready before returning it to the caller */
00938                while (!thread->ready_for_signal)
00939                   usleep(1);
00940             }
00941          }
00942       }
00943       AST_LIST_UNLOCK(&dynamic_list);
00944    }
00945 
00946    /* this thread is not processing a full frame (since it is idle),
00947       so ensure that the field for the full frame call number is empty */
00948    if (thread)
00949       memset(&thread->ffinfo, 0, sizeof(thread->ffinfo));
00950 
00951    return thread;
00952 }

static struct iax2_peer* find_peer ( const char *  name,
int  realtime 
) [static]

Note:
This funtion calls realtime_peer -> reg_source_db -> iax2_poke_peer -> find_callno, so do not call it with a pvt lock held.

Definition at line 1139 of file chan_iax2.c.

References ao2_find(), peers, and realtime_peer().

01140 {
01141    struct iax2_peer *peer = NULL;
01142    struct iax2_peer tmp_peer = {
01143       .name = name,
01144    };
01145 
01146    peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
01147 
01148    /* Now go for realtime if applicable */
01149    if(!peer && realtime)
01150       peer = realtime_peer(name, NULL);
01151 
01152    return peer;
01153 }

static struct iax2_trunk_peer* find_tpeer ( struct sockaddr_in *  sin,
int  fd 
) [static]

Definition at line 4009 of file chan_iax2.c.

References iax2_trunk_peer::addr, ast_mutex_lock(), inaddrcmp(), iax2_trunk_peer::lock, iax2_trunk_peer::next, and tpeers.

Referenced by iax2_trunk_queue(), and socket_process().

04010 {
04011    struct iax2_trunk_peer *tpeer;
04012    
04013    /* Finds and locks trunk peer */
04014    ast_mutex_lock(&tpeerlock);
04015    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
04016       /* We don't lock here because tpeer->addr *never* changes */
04017       if (!inaddrcmp(&tpeer->addr, sin)) {
04018          ast_mutex_lock(&tpeer->lock);
04019          break;
04020       }
04021    }
04022    if (!tpeer) {
04023       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
04024          ast_mutex_init(&tpeer->lock);
04025          tpeer->lastsent = 9999;
04026          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
04027          tpeer->trunkact = ast_tvnow();
04028          ast_mutex_lock(&tpeer->lock);
04029          tpeer->next = tpeers;
04030          tpeer->sockfd = fd;
04031          tpeers = tpeer;
04032 #ifdef SO_NO_CHECK
04033          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
04034 #endif
04035          if (option_debug)
04036             ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
04037       }
04038    }
04039    ast_mutex_unlock(&tpeerlock);
04040    return tpeer;
04041 }

static unsigned int fix_peerts ( struct timeval *  tv,
int  callno,
unsigned int  ts 
) [static]

Definition at line 3825 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03826 {
03827    long ms; /* NOT unsigned */
03828    if (ast_tvzero(iaxs[callno]->rxcore)) {
03829       /* Initialize rxcore time if appropriate */
03830       gettimeofday(&iaxs[callno]->rxcore, NULL);
03831       /* Round to nearest 20ms so traces look pretty */
03832       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03833    }
03834    /* Calculate difference between trunk and channel */
03835    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03836    /* Return as the sum of trunk time and the difference between trunk and real time */
03837    return ms + ts;
03838 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8932 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

08933 {
08934    struct iax2_context *conl;
08935    while(con) {
08936       conl = con;
08937       con = con->next;
08938       free(conl);
08939    }
08940 }

static int function_iaxpeer ( struct ast_channel chan,
char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 10592 of file chan_iax2.c.

References iax2_peer::addr, ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strdupa, ast_test_flag, iax2_peer::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.

10593 {
10594    struct iax2_peer *peer;
10595    char *peername, *colname;
10596 
10597    peername = ast_strdupa(data);
10598 
10599    /* if our channel, return the IP address of the endpoint of current channel */
10600    if (!strcmp(peername,"CURRENTCHANNEL")) {
10601            unsigned short callno;
10602       if (chan->tech != &iax2_tech)
10603          return -1;
10604       callno = PTR_TO_CALLNO(chan->tech_pvt);   
10605       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
10606       return 0;
10607    }
10608 
10609    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
10610       *colname++ = '\0';
10611    else if ((colname = strchr(peername, '|')))
10612       *colname++ = '\0';
10613    else
10614       colname = "ip";
10615 
10616    if (!(peer = find_peer(peername, 1)))
10617       return -1;
10618 
10619    if (!strcasecmp(colname, "ip")) {
10620       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
10621    } else  if (!strcasecmp(colname, "status")) {
10622       peer_status(peer, buf, len); 
10623    } else  if (!strcasecmp(colname, "mailbox")) {
10624       ast_copy_string(buf, peer->mailbox, len);
10625    } else  if (!strcasecmp(colname, "context")) {
10626       ast_copy_string(buf, peer->context, len);
10627    } else  if (!strcasecmp(colname, "expire")) {
10628       snprintf(buf, len, "%d", peer->expire);
10629    } else  if (!strcasecmp(colname, "dynamic")) {
10630       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
10631    } else  if (!strcasecmp(colname, "callerid_name")) {
10632       ast_copy_string(buf, peer->cid_name, len);
10633    } else  if (!strcasecmp(colname, "callerid_num")) {
10634       ast_copy_string(buf, peer->cid_num, len);
10635    } else  if (!strcasecmp(colname, "codecs")) {
10636       ast_getformatname_multiple(buf, len -1, peer->capability);
10637    } else  if (!strncasecmp(colname, "codec[", 6)) {
10638       char *codecnum, *ptr;
10639       int index = 0, codec = 0;
10640       
10641       codecnum = strchr(colname, '[');
10642       *codecnum = '\0';
10643       codecnum++;
10644       if ((ptr = strchr(codecnum, ']'))) {
10645          *ptr = '\0';
10646       }
10647       index = atoi(codecnum);
10648       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
10649          ast_copy_string(buf, ast_getformatname(codec), len);
10650       }
10651    }
10652 
10653    peer_unref(peer);
10654 
10655    return 0;
10656 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 9157 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

09158 {
09159    int methods = 0;
09160    if (strstr(value, "rsa"))
09161       methods |= IAX_AUTH_RSA;
09162    if (strstr(value, "md5"))
09163       methods |= IAX_AUTH_MD5;
09164    if (strstr(value, "plaintext"))
09165       methods |= IAX_AUTH_PLAINTEXT;
09166    return methods;
09167 }

static int get_encrypt_methods ( const char *  s  )  [static]

Definition at line 1021 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

Referenced by build_peer(), build_user(), and set_config().

01022 {
01023    int e;
01024    if (!strcasecmp(s, "aes128"))
01025       e = IAX_ENCRYPT_AES128;
01026    else if (ast_true(s))
01027       e = IAX_ENCRYPT_AES128;
01028    else
01029       e = 0;
01030    return e;
01031 }

static int get_from_jb ( const void *  p  )  [static]

Definition at line 2620 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02621 {
02622 #ifdef SCHED_MULTITHREADED
02623    if (schedule_action(__get_from_jb, data))
02624 #endif      
02625       __get_from_jb(data);
02626    return 0;
02627 }

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

Definition at line 6812 of file chan_iax2.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), socket_process(), and thread.

06813 {
06814    struct iax2_pkt_buf *pkt_buf;
06815 
06816    ast_mutex_lock(&thread->lock);
06817 
06818    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06819       ast_mutex_unlock(&thread->lock);
06820 
06821       thread->buf = pkt_buf->buf;
06822       thread->buf_len = pkt_buf->len;
06823       thread->buf_size = pkt_buf->len + 1;
06824       
06825       socket_process(thread);
06826 
06827       thread->buf = NULL;
06828       ast_free(pkt_buf);
06829 
06830       ast_mutex_lock(&thread->lock);
06831    }
06832 
06833    ast_mutex_unlock(&thread->lock);
06834 }

static int handle_error ( void   )  [static]

Definition at line 2028 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().

02029 {
02030    /* XXX Ideally we should figure out why an error occured and then abort those
02031       rather than continuing to try.  Unfortunately, the published interface does
02032       not seem to work XXX */
02033 #if 0
02034    struct sockaddr_in *sin;
02035    int res;
02036    struct msghdr m;
02037    struct sock_extended_err e;
02038    m.msg_name = NULL;
02039    m.msg_namelen = 0;
02040    m.msg_iov = NULL;
02041    m.msg_control = &e;
02042    m.msg_controllen = sizeof(e);
02043    m.msg_flags = 0;
02044    res = recvmsg(netsocket, &m, MSG_ERRQUEUE);
02045    if (res < 0)
02046       ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno));
02047    else {
02048       if (m.msg_controllen) {
02049          sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e);
02050          if (sin) 
02051             ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr));
02052          else
02053             ast_log(LOG_WARNING, "No address detected??\n");
02054       } else {
02055          ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno));
02056       }
02057    }
02058 #endif
02059    return 0;
02060 }

static int iax2_ack_registry ( struct iax_ies ies,
struct sockaddr_in *  sin,
int  callno 
) [static]

Acknowledgment received for OUR registration.

Definition at line 5884 of file chan_iax2.c.

References iax2_registry::addr, ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), EVENT_FLAG_SYSTEM, iax2_registry::expire, iax2_do_register_s(), iax2_sched_add(), iaxs, ies, inaddrcmp(), LOG_WARNING, manager_event(), iax2_registry::messages, option_verbose, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGISTERED, iax2_registry::regstate, sched, iax2_registry::us, and VERBOSE_PREFIX_3.

Referenced by socket_process().

05885 {
05886    struct iax2_registry *reg;
05887    /* Start pessimistic */
05888    char peer[256] = "";
05889    char msgstatus[60];
05890    int refresh = 60;
05891    char ourip[256] = "<Unspecified>";
05892    struct sockaddr_in oldus;
05893    struct sockaddr_in us;
05894    int oldmsgs;
05895 
05896    memset(&us, 0, sizeof(us));
05897    if (ies->apparent_addr)
05898       bcopy(ies->apparent_addr, &us, sizeof(us));
05899    if (ies->username)
05900       ast_copy_string(peer, ies->username, sizeof(peer));
05901    if (ies->refresh)
05902       refresh = ies->refresh;
05903    if (ies->calling_number) {
05904       /* We don't do anything with it really, but maybe we should */
05905    }
05906    reg = iaxs[callno]->reg;
05907    if (!reg) {
05908       ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer);
05909       return -1;
05910    }
05911    memcpy(&oldus, &reg->us, sizeof(oldus));
05912    oldmsgs = reg->messages;
05913    if (inaddrcmp(&reg->addr, sin)) {
05914       ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr));
05915       return -1;
05916    }
05917    memcpy(&reg->us, &us, sizeof(reg->us));
05918    if (ies->msgcount >= 0)
05919       reg->messages = ies->msgcount & 0xffff;      /* only low 16 bits are used in the transmission of the IE */
05920    /* always refresh the registration at the interval requested by the server
05921       we are registering to
05922    */
05923    reg->refresh = refresh;
05924    AST_SCHED_DEL(sched, reg->expire);
05925    reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
05926    if (inaddrcmp(&oldus, &reg->us) || (reg->messages != oldmsgs)) {
05927       if (option_verbose > 2) {
05928          if (reg->messages > 255)
05929             snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8);
05930          else if (reg->messages > 1)
05931             snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages);
05932          else if (reg->messages > 0)
05933             snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n");
05934          else
05935             snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n");
05936          snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
05937          ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus);
05938       }
05939       manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr));
05940    }
05941    reg->regstate = REG_STATE_REGISTERED;
05942    return 0;
05943 }

static int iax2_answer ( struct ast_channel c  )  [static]

Definition at line 3625 of file chan_iax2.c.

References AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_log(), option_debug, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.

03626 {
03627    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03628    if (option_debug)
03629       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03630    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03631 }

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 3475 of file chan_iax2.c.

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), chan_iax2_pvt::bridgecallno, f, iax2_tech, iaxs, iaxsl, lock_both(), option_verbose, PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, tv, unlock_both(), and VERBOSE_PREFIX_3.

03476 {
03477    struct ast_channel *cs[3];
03478    struct ast_channel *who, *other;
03479    int to = -1;
03480    int res = -1;
03481    int transferstarted=0;
03482    struct ast_frame *f;
03483    unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt);
03484    unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt);
03485    struct timeval waittimer = {0, 0}, tv;
03486 
03487    lock_both(callno0, callno1);
03488    if (!iaxs[callno0] || !iaxs[callno1]) {
03489       unlock_both(callno0, callno1);
03490       return AST_BRIDGE_FAILED;
03491    }
03492    /* Put them in native bridge mode */
03493    if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) {
03494       iaxs[callno0]->bridgecallno = callno1;
03495       iaxs[callno1]->bridgecallno = callno0;
03496    }
03497    unlock_both(callno0, callno1);
03498 
03499    /* If not, try to bridge until we can execute a transfer, if we can */
03500    cs[0] = c0;
03501    cs[1] = c1;
03502    for (/* ever */;;) {
03503       /* Check in case we got masqueraded into */
03504       if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) {
03505          if (option_verbose > 2)
03506             ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n");
03507          /* Remove from native mode */
03508          if (c0->tech == &iax2_tech) {
03509             ast_mutex_lock(&iaxsl[callno0]);
03510             iaxs[callno0]->bridgecallno = 0;
03511             ast_mutex_unlock(&iaxsl[callno0]);
03512          }
03513          if (c1->tech == &iax2_tech) {
03514             ast_mutex_lock(&iaxsl[callno1]);
03515             iaxs[callno1]->bridgecallno = 0;
03516             ast_mutex_unlock(&iaxsl[callno1]);
03517          }
03518          return AST_BRIDGE_FAILED_NOWARN;
03519       }
03520       if (c0->nativeformats != c1->nativeformats) {
03521          if (option_verbose > 2) {
03522             char buf0[255];
03523             char buf1[255];
03524             ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats);
03525             ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats);
03526             ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1);
03527          }
03528          /* Remove from native mode */
03529          lock_both(callno0, callno1);
03530          if (iaxs[callno0])
03531             iaxs[callno0]->bridgecallno = 0;
03532          if (iaxs[callno1])
03533             iaxs[callno1]->bridgecallno = 0;
03534          unlock_both(callno0, callno1);
03535          return AST_BRIDGE_FAILED_NOWARN;
03536       }
03537       /* check if transfered and if we really want native bridging */
03538       if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) {
03539          /* Try the transfer */
03540          if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) ||
03541                      ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA)))
03542             ast_log(LOG_WARNING, "Unable to start the transfer\n");
03543          transferstarted = 1;
03544       }
03545       if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) {
03546          /* Call has been transferred.  We're no longer involved */
03547          gettimeofday(&tv, NULL);
03548          if (ast_tvzero(waittimer)) {
03549             waittimer = tv;
03550          } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) {
03551             c0->_softhangup |= AST_SOFTHANGUP_DEV;
03552             c1->_softhangup |= AST_SOFTHANGUP_DEV;
03553             *fo = NULL;
03554             *rc = c0;
03555             res = AST_BRIDGE_COMPLETE;
03556             break;
03557          }
03558       }
03559       to = 1000;
03560       who = ast_waitfor_n(cs, 2, &to);
03561       if (timeoutms > -1) {
03562          timeoutms -= (1000 - to);
03563          if (timeoutms < 0)
03564             timeoutms = 0;
03565       }
03566       if (!who) {
03567          if (!timeoutms) {
03568             res = AST_BRIDGE_RETRY;
03569             break;
03570          }
03571          if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03572             res = AST_BRIDGE_FAILED;
03573             break;
03574          }
03575          continue;
03576       }
03577       f = ast_read(who);
03578       if (!f) {
03579          *fo = NULL;
03580          *rc = who;
03581          res = AST_BRIDGE_COMPLETE;
03582          break;
03583       }
03584       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03585          *fo = f;
03586          *rc = who;
03587          res =  AST_BRIDGE_COMPLETE;
03588          break;
03589       }
03590       other = (who == c0) ? c1 : c0;  /* the 'other' channel */
03591       if ((f->frametype == AST_FRAME_VOICE) ||
03592           (f->frametype == AST_FRAME_TEXT) ||
03593           (f->frametype == AST_FRAME_VIDEO) || 
03594           (f->frametype == AST_FRAME_IMAGE) ||
03595           (f->frametype == AST_FRAME_DTMF)) {
03596          /* monitored dtmf take out of the bridge.
03597           * check if we monitor the specific source.
03598           */
03599          int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1;
03600          if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) {
03601             *rc = who;
03602             *fo = f;
03603             res = AST_BRIDGE_COMPLETE;
03604             /* Remove from native mode */
03605             break;
03606          }
03607          /* everything else goes to the other side */
03608          ast_write(other, f);
03609       }
03610       ast_frfree(f);
03611       /* Swap who gets priority */
03612       cs[2] = cs[0];
03613       cs[0] = cs[1];
03614       cs[1] = cs[2];
03615    }
03616    lock_both(callno0, callno1);
03617    if(iaxs[callno0])
03618       iaxs[callno0]->bridgecallno = 0;
03619    if(iaxs[callno1])
03620       iaxs[callno1]->bridgecallno = 0;
03621    unlock_both(callno0, callno1);
03622    return res;
03623 }

static int iax2_call ( struct ast_channel c,
char *  dest,
int  timeout 
) [static]

Definition at line 3220 of file chan_iax2.c.

References ast_channel::_state, 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(), 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, ast_channel::context, create_addr(), chan_iax2_pvt::encmethods, 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, LOG_WARNING, chan_iax2_pvt::maxtime, create_addr_info::maxtime, ast_channel::nativeformats, create_addr_info::outkey, parse_dial_string(), chan_iax2_pvt::pingtime, PTR_TO_CALLNO, sched, secret, send_command(), chan_iax2_pvt::sockfd, and ast_channel::tech_pvt.

03221 {
03222    struct sockaddr_in sin;
03223    char *l=NULL, *n=NULL, *tmpstr;
03224    struct iax_ie_data ied;
03225    char *defaultrdest = "s";
03226    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03227    struct parsed_dial_string pds;
03228    struct create_addr_info cai;
03229 
03230    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
03231       ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name);
03232       return -1;
03233    }
03234 
03235    memset(&cai, 0, sizeof(cai));
03236    cai.encmethods = iax2_encryption;
03237 
03238    memset(&pds, 0, sizeof(pds));
03239    tmpstr = ast_strdupa(dest);
03240    parse_dial_string(tmpstr, &pds);
03241 
03242    if (ast_strlen_zero(pds.peer)) {
03243       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest);
03244       return -1;
03245    }
03246 
03247    if (!pds.exten) {
03248       pds.exten = defaultrdest;
03249    }
03250 
03251    if (create_addr(pds.peer, c, &sin, &cai)) {
03252       ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
03253       return -1;
03254    }
03255 
03256    if (!pds.username && !ast_strlen_zero(cai.username))
03257       pds.username = cai.username;
03258    if (!pds.password && !ast_strlen_zero(cai.secret))
03259       pds.password = cai.secret;
03260    if (!pds.key && !ast_strlen_zero(cai.outkey))
03261       pds.key = cai.outkey;
03262    if (!pds.context && !ast_strlen_zero(cai.peercontext))
03263       pds.context = cai.peercontext;
03264 
03265    /* Keep track of the context for outgoing calls too */
03266    ast_copy_string(c->context, cai.context, sizeof(c->context));
03267 
03268    if (pds.port)
03269       sin.sin_port = htons(atoi(pds.port));
03270 
03271    l = c->cid.cid_num;
03272    n = c->cid.cid_name;
03273 
03274    /* Now build request */ 
03275    memset(&ied, 0, sizeof(ied));
03276 
03277    /* On new call, first IE MUST be IAX version of caller */
03278    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
03279    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten);
03280    if (pds.options && strchr(pds.options, 'a')) {
03281       /* Request auto answer */
03282       iax_ie_append(&ied, IAX_IE_AUTOANSWER);
03283    }
03284 
03285    iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs);
03286 
03287    if (l) {
03288       iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
03289       iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03290    } else {
03291       if (n)
03292          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03293       else
03294          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
03295    }
03296 
03297    iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
03298    iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
03299 
03300    if (n)
03301       iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
03302    if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
03303       iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
03304 
03305    if (!ast_strlen_zero(c->language))
03306       iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
03307    if (!ast_strlen_zero(c->cid.cid_dnid))
03308       iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid);
03309    if (!ast_strlen_zero(c->cid.cid_rdnis))
03310       iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis);
03311 
03312    if (pds.context)
03313       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context);
03314 
03315    if (pds.username)
03316       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
03317 
03318    if (cai.encmethods)
03319       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods);
03320 
03321    ast_mutex_lock(&iaxsl[callno]);
03322 
03323    if (!ast_strlen_zero(c->context))
03324       ast_string_field_set(iaxs[callno], context, c->context);
03325 
03326    if (pds.username)
03327       ast_string_field_set(iaxs[callno], username, pds.username);
03328 
03329    iaxs[callno]->encmethods = cai.encmethods;
03330 
03331    iaxs[callno]->adsi = cai.adsi;
03332    
03333    ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret);
03334    ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest);
03335 
03336    if (pds.key)
03337       ast_string_field_set(iaxs[callno], outkey, pds.key);
03338    if (pds.password)
03339       ast_string_field_set(iaxs[callno], secret, pds.password);
03340 
03341    iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats);
03342    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability);
03343    iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe);
03344    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone));
03345 
03346    if (iaxs[callno]->maxtime) {
03347       /* Initialize pingtime and auto-congest time */
03348       iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2;
03349       iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno));
03350    } else if (autokill) {
03351       iaxs[callno]->pingtime = autokill / 2;
03352       iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno));
03353    }
03354 
03355    /* send the command using the appropriate socket for this peer */
03356    iaxs[callno]->sockfd = cai.sockfd;
03357 
03358    /* Transmit the string in a "NEW" request */
03359    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
03360 
03361    ast_mutex_unlock(&iaxsl[callno]);
03362    ast_setstate(c, AST_STATE_RINGING);
03363    
03364    return 0;
03365 }

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 10494 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.

10495 {
10496    int res = 0;
10497    struct iax2_dpcache *dp;
10498 #if 0
10499    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10500 #endif
10501    if ((priority != 1) && (priority != 2))
10502       return 0;
10503    ast_mutex_lock(&dpcache_lock);
10504    dp = find_cache(chan, data, context, exten, priority);
10505    if (dp) {
10506       if (dp->flags & CACHE_FLAG_CANEXIST)
10507          res= 1;
10508    }
10509    ast_mutex_unlock(&dpcache_lock);
10510    if (!dp) {
10511       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10512    }
10513    return res;
10514 }

static unsigned int iax2_datetime ( const char *  tz  )  [static]

Definition at line 3123 of file chan_iax2.c.

References ast_localtime(), ast_strlen_zero(), and t.

Referenced by iax2_call(), and update_registry().

03124 {
03125    time_t t;
03126    struct tm tm;
03127    unsigned int tmp;
03128    time(&t);
03129    if (!ast_strlen_zero(tz))
03130       ast_localtime(&t, &tm, tz);
03131    else
03132       ast_localtime(&t, &tm, NULL);
03133    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
03134    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
03135    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
03136    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
03137    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
03138    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
03139    return tmp;
03140 }

static void iax2_destroy ( int  callno  )  [static]

Definition at line 1279 of file chan_iax2.c.

References ao2_ref(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, iaxsl, 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().

01280 {
01281    struct chan_iax2_pvt *pvt;
01282    struct ast_channel *owner;
01283 
01284 retry:
01285    pvt = iaxs[callno];
01286    gettimeofday(&lastused[callno], NULL);
01287    
01288    owner = pvt ? pvt->owner : NULL;
01289 
01290    if (owner) {
01291       if (ast_mutex_trylock(&owner->lock)) {
01292          if (option_debug > 2)
01293             ast_log(LOG_DEBUG, "Avoiding IAX destroy deadlock\n");
01294          DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01295          goto retry;
01296       }
01297    }
01298    if (!owner) {
01299       iaxs[callno] = NULL;
01300    }
01301 
01302    if (pvt) {
01303       if (!owner) {
01304          pvt->owner = NULL;
01305       } else {
01306          /* If there's an owner, prod it to give up */
01307          /* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup()
01308           * because we already hold the owner channel lock. */
01309          ast_queue_hangup(owner);
01310       }
01311 
01312       if (pvt->peercallno) {
01313          remove_by_peercallno(pvt);
01314       }
01315 
01316       if (!owner) {
01317          ao2_ref(pvt, -1);
01318          pvt = NULL;
01319       }
01320    }
01321 
01322    if (owner) {
01323       ast_mutex_unlock(&owner->lock);
01324    }
01325 
01326    if (callno & 0x4000) {
01327       update_max_trunk();
01328    }
01329 }

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1209 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, sched, user_unref(), and users.

Referenced by iax2_predestroy(), pvt_destructor(), and stop_stuff().

01210 {
01211    /* Decrement AUTHREQ count if needed */
01212    if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
01213       struct iax2_user *user;
01214       struct iax2_user tmp_user = {
01215          .name = pvt->username,
01216       };
01217 
01218       user = ao2_find(users, &tmp_user, OBJ_POINTER);
01219       if (user) {
01220          ast_atomic_fetchadd_int(&user->curauthreq, -1);
01221          user = user_unref(user);       
01222       }
01223 
01224       ast_clear_flag(pvt, IAX_MAXAUTHREQ);
01225    }
01226 
01227    /* No more pings or lagrq's */
01228    AST_SCHED_DEL(sched, pvt->pingid);
01229    AST_SCHED_DEL(sched, pvt->lagid);
01230    AST_SCHED_DEL(sched, pvt->autoid);
01231    AST_SCHED_DEL(sched, pvt->authid);
01232    AST_SCHED_DEL(sched, pvt->initid);
01233    AST_SCHED_DEL(sched, pvt->jbid);
01234 }

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

Definition at line 10681 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_WARNING, iax2_peer::maxms, option_debug, parse_dial_string(), and peer_unref().

10682 {
10683    struct parsed_dial_string pds;
10684    char *tmp = ast_strdupa(data);
10685    struct iax2_peer *p;
10686    int res = AST_DEVICE_INVALID;
10687 
10688    memset(&pds, 0, sizeof(pds));
10689    parse_dial_string(tmp, &pds);
10690 
10691    if (ast_strlen_zero(pds.peer)) {
10692       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
10693       return res;
10694    }
10695    
10696    if (option_debug > 2)
10697       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
10698 
10699    /* SLD: FIXME: second call to find_peer during registration */
10700    if (!(p = find_peer(pds.peer, 1)))
10701       return res;
10702 
10703    res = AST_DEVICE_UNAVAILABLE;
10704    if (option_debug > 2) 
10705       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
10706          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
10707    
10708    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
10709        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
10710       /* Peer is registered, or have default IP address
10711          and a valid registration */
10712       if (p->historicms == 0 || p->historicms <= p->maxms)
10713          /* let the core figure out whether it is in use or not */
10714          res = AST_DEVICE_UNKNOWN;  
10715    }
10716 
10717    peer_unref(p);
10718 
10719    return res;
10720 }

static int iax2_digit_begin ( struct ast_channel c,
char  digit 
) [static]

Definition at line 2739 of file chan_iax2.c.

References AST_FRAME_DTMF_BEGIN, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.

02740 {
02741    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02742 }

static int iax2_digit_end ( struct ast_channel c,
char  digit,
unsigned int  duration 
) [static]

Definition at line 2744 of file chan_iax2.c.

References AST_FRAME_DTMF_END, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.

02745 {
02746    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02747 }

static int iax2_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4931 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04932 {
04933    if (argc < 2 || argc > 3)
04934       return RESULT_SHOWUSAGE;
04935    iaxdebug = 1;
04936    ast_cli(fd, "IAX2 Debugging Enabled\n");
04937    return RESULT_SUCCESS;
04938 }

static int iax2_do_jb_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4949 of file chan_iax2.c.

References ast_cli(), jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04950 {
04951    if (argc < 3 || argc > 4)
04952       return RESULT_SHOWUSAGE;
04953    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04954    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04955    return RESULT_SUCCESS;
04956 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 8651 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, 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_WARNING, NEW_FORCE, option_debug, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), and iax2_registry::username.

Referenced by __iax2_do_register_s(), load_module(), and reload_config().

08652 {
08653    struct iax_ie_data ied;
08654    if (option_debug && iaxdebug)
08655       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
08656 
08657    if (reg->dnsmgr && 
08658        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
08659       /* Maybe the IP has changed, force DNS refresh */
08660       ast_dnsmgr_refresh(reg->dnsmgr);
08661    }
08662    
08663    /*
08664     * if IP has Changed, free allocated call to create a new one with new IP
08665     * call has the pointer to IP and must be updated to the new one
08666     */
08667    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
08668       ast_mutex_lock(&iaxsl[reg->callno]);
08669       iax2_destroy(reg->callno);
08670       ast_mutex_unlock(&iaxsl[reg->callno]);
08671       reg->callno = 0;
08672    }
08673    if (!reg->addr.sin_addr.s_addr) {
08674       if (option_debug && iaxdebug)
08675          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
08676       /* Setup the next registration attempt */
08677       AST_SCHED_DEL(sched, reg->expire);
08678       reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08679       return -1;
08680    }
08681 
08682    if (!reg->callno) {
08683       if (option_debug)
08684          ast_log(LOG_DEBUG, "Allocate call number\n");
08685       reg->callno = find_callno_locked(0, 0, &reg->addr, NEW_FORCE, defaultsockfd, 0);
08686       if (reg->callno < 1) {
08687          ast_log(LOG_WARNING, "Unable to create call for registration\n");
08688          return -1;
08689       } else if (option_debug)
08690          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
08691       iaxs[reg->callno]->reg = reg;
08692       ast_mutex_unlock(&iaxsl[reg->callno]);
08693    }
08694    /* Schedule the next registration attempt */
08695    AST_SCHED_DEL(sched, reg->expire);
08696    /* Setup the next registration a little early */
08697    reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08698    /* Send the request */
08699    memset(&ied, 0, sizeof(ied));
08700    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
08701    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
08702    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
08703    reg->regstate = REG_STATE_REGSENT;
08704    return 0;
08705 }

static int iax2_do_register_s ( const void *  data  )  [static]

Definition at line 5732 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05733 {
05734 #ifdef SCHED_MULTITHREADED
05735    if (schedule_action(__iax2_do_register_s, data))
05736 #endif      
05737       __iax2_do_register_s(data);
05738    return 0;
05739 }

static int iax2_do_trunk_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4940 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04941 {
04942    if (argc < 3 || argc > 4)
04943       return RESULT_SHOWUSAGE;
04944    iaxtrunkdebug = 1;
04945    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04946    return RESULT_SUCCESS;
04947 }

static void iax2_dprequest ( struct iax2_dpcache dp,
int  callno 
) [static]

Definition at line 6423 of file chan_iax2.c.

References AST_FRAME_IAX, AST_SCHED_DEL, auto_hangup(), chan_iax2_pvt::autoid, CACHE_FLAG_TRANSMITTED, iax2_dpcache::exten, iax2_dpcache::flags, iax2_sched_add(), IAX_COMMAND_DPREQ, iax_ie_append_str(), IAX_IE_CALLED_NUMBER, iaxs, sched, and send_command().

Referenced by find_cache(), and socket_process().

06424 {
06425    struct iax_ie_data ied;
06426    /* Auto-hangup with 30 seconds of inactivity */
06427    AST_SCHED_DEL(sched, iaxs[callno]->autoid);
06428    iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06429    memset(&ied, 0, sizeof(ied));
06430    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06431    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06432    dp->flags |= CACHE_FLAG_TRANSMITTED;
06433 }

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 10540 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.

10541 {
10542    char odata[256];
10543    char req[256];
10544    char *ncontext;
10545    struct iax2_dpcache *dp;
10546    struct ast_app *dial;
10547 #if 0
10548    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);
10549 #endif
10550    if (priority == 2) {
10551       /* Indicate status, can be overridden in dialplan */
10552       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
10553       if (dialstatus) {
10554          dial = pbx_findapp(dialstatus);
10555          if (dial) 
10556             pbx_exec(chan, dial, "");
10557       }
10558       return -1;
10559    } else if (priority != 1)
10560       return -1;
10561    ast_mutex_lock(&dpcache_lock);
10562    dp = find_cache(chan, data, context, exten, priority);
10563    if (dp) {
10564       if (dp->flags & CACHE_FLAG_EXISTS) {
10565          ast_copy_string(odata, data, sizeof(odata));
10566          ncontext = strchr(odata, '/');
10567          if (ncontext) {
10568             *ncontext = '\0';
10569             ncontext++;
10570             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
10571          } else {
10572             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
10573          }
10574          if (option_verbose > 2)
10575             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
10576       } else {
10577          ast_mutex_unlock(&dpcache_lock);
10578          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
10579          return -1;
10580       }
10581    }
10582    ast_mutex_unlock(&dpcache_lock);
10583    dial = pbx_findapp("Dial");
10584    if (dial) {
10585       return pbx_exec(chan, dial, req);
10586    } else {
10587       ast_log(LOG_WARNING, "No dial application registered\n");
10588    }
10589    return -1;
10590 }

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 10471 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.

10472 {
10473    struct iax2_dpcache *dp;
10474    int res = 0;
10475 #if 0
10476    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10477 #endif
10478    if ((priority != 1) && (priority != 2))
10479       return 0;
10480    ast_mutex_lock(&dpcache_lock);
10481    dp = find_cache(chan, data, context, exten, priority);
10482    if (dp) {
10483       if (dp->flags & CACHE_FLAG_EXISTS)
10484          res= 1;
10485    }
10486    ast_mutex_unlock(&dpcache_lock);
10487    if (!dp) {
10488       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10489    }
10490    return res;
10491 }

static int iax2_fixup ( struct ast_channel oldchannel,
struct ast_channel newchan 
) [static]

Definition at line 2766 of file chan_iax2.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iaxs, iaxsl, LOG_WARNING, chan_iax2_pvt::owner, PTR_TO_CALLNO, and ast_channel::tech_pvt.

02767 {
02768    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02769    ast_mutex_lock(&iaxsl[callno]);
02770    if (iaxs[callno])
02771       iaxs[callno]->owner = newchan;
02772    else
02773       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02774    ast_mutex_unlock(&iaxsl[callno]);
02775    return 0;
02776 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

Definition at line 1273 of file chan_iax2.c.

References AST_SCHED_DEL, iax_frame_free(), iax_frame::retrans, and sched.

Referenced by __attempt_transmit(), __do_deliver(), __get_from_jb(), complete_transfer(), pvt_destructor(), and schedule_delivery().

01274 {
01275    AST_SCHED_DEL(sched, fr->retrans);
01276    iax_frame_free(fr);
01277 }

static int iax2_getpeername ( struct sockaddr_in  sin,
char *  host,
int  len 
) [static]

Definition at line 1179 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().

01180 {
01181    struct iax2_peer *peer = NULL;
01182    int res = 0;
01183    struct ao2_iterator i;
01184 
01185    i = ao2_iterator_init(peers, 0);
01186    while ((peer = ao2_iterator_next(&i))) {
01187       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
01188           (peer->addr.sin_port == sin.sin_port)) {
01189          ast_copy_string(host, peer->name, len);
01190          peer_unref(peer);
01191          res = 1;
01192          break;
01193       }
01194       peer_unref(peer);
01195    }
01196 
01197    if (!peer) {
01198       peer = realtime_peer(NULL, &sin);
01199       if (peer) {
01200          ast_copy_string(host, peer->name, len);
01201          peer_unref(peer);
01202          res = 1;
01203       }
01204    }
01205 
01206    return res;
01207 }

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

Definition at line 3700 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().

03701 {
03702    struct iax2_peer *peer;
03703    int res = 0;
03704    struct ao2_iterator i;
03705 
03706    i = ao2_iterator_init(peers, 0);
03707    while ((peer = ao2_iterator_next(&i))) {
03708       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03709           (peer->addr.sin_port == sin.sin_port)) {
03710          res = ast_test_flag(peer, IAX_TRUNK);
03711          peer_unref(peer);
03712          break;
03713       }
03714       peer_unref(peer);
03715    }
03716 
03717    return res;
03718 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 3367 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_verbose(), error(), ast_channel::hangupcause, iax2_destroy(), iax2_predestroy(), IAX_ALREADYGONE, IAX_COMMAND_HANGUP, iax_ie_append_byte(), IAX_IE_CAUSECODE, iaxs, iaxsl, option_debug, option_verbose, PTR_TO_CALLNO, send_command_final(), ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

03368 {
03369    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03370    int alreadygone;
03371    struct iax_ie_data ied;
03372    memset(&ied, 0, sizeof(ied));
03373    ast_mutex_lock(&iaxsl[callno]);
03374    if (callno && iaxs[callno]) {
03375       if (option_debug)
03376          ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
03377       alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
03378       /* Send the hangup unless we have had a transmission error or are already gone */
03379       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
03380       if (!iaxs[callno]->error && !alreadygone) {
03381          send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
03382          if (!iaxs[callno]) {
03383             ast_mutex_unlock(&iaxsl[callno]);
03384             return 0;
03385          }
03386       }
03387       /* Explicitly predestroy it */
03388       iax2_predestroy(callno);
03389       /* If we were already gone to begin with, destroy us now */
03390       if (alreadygone && iaxs[callno]) {
03391          if (option_debug)
03392             ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
03393          iax2_destroy(callno);
03394       }
03395    }
03396    ast_mutex_unlock(&iaxsl[callno]);
03397    if (option_verbose > 2) 
03398       ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
03399    return 0;
03400 }

static int iax2_indicate ( struct ast_channel c,
int  condition,
const void *  data,
size_t  datalen 
) [static]

Definition at line 3633 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(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, option_debug, chan_iax2_pvt::peercallno, PTR_TO_CALLNO, send_command(), and ast_channel::tech_pvt.

03634 {
03635    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03636    struct chan_iax2_pvt *pvt;
03637    int res = 0;
03638 
03639    if (option_debug && iaxdebug)
03640       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03641 
03642    ast_mutex_lock(&iaxsl[callno]);
03643    pvt = iaxs[callno];
03644 
03645    if (!pvt->peercallno) {
03646       /* We don't know the remote side's call number, yet.  :( */
03647       int count = 10;
03648       while (count-- && pvt && !pvt->peercallno) {
03649          DEADLOCK_AVOIDANCE(&iaxsl[callno]);
03650          pvt = iaxs[callno];
03651       }
03652       if (!pvt->peercallno) {
03653          res = -1;
03654          goto done;
03655       }
03656    }
03657 
03658    switch (condition) {
03659    case AST_CONTROL_HOLD:
03660       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03661          ast_moh_start(c, data, pvt->mohinterpret);
03662          goto done;
03663       }
03664       break;
03665    case AST_CONTROL_UNHOLD:
03666       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03667          ast_moh_stop(c);
03668          goto done;
03669       }
03670    }
03671 
03672    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03673 
03674 done:
03675    ast_mutex_unlock(&iaxsl[callno]);
03676 
03677    return res;
03678 }

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 10517 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.

10518 {
10519    int res = 0;
10520    struct iax2_dpcache *dp;
10521 #if 0
10522    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10523 #endif
10524    if ((priority != 1) && (priority != 2))
10525       return 0;
10526    ast_mutex_lock(&dpcache_lock);
10527    dp = find_cache(chan, data, context, exten, priority);
10528    if (dp) {
10529       if (dp->flags & CACHE_FLAG_MATCHMORE)
10530          res= 1;
10531    }
10532    ast_mutex_unlock(&dpcache_lock);
10533    if (!dp) {
10534       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10535    }
10536    return res;
10537 }

static int iax2_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4958 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04959 {
04960    if (argc < 3 || argc > 4)
04961       return RESULT_SHOWUSAGE;
04962    iaxdebug = 0;
04963    ast_cli(fd, "IAX2 Debugging Disabled\n");
04964    return RESULT_SUCCESS;
04965 }

static int iax2_no_jb_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4976 of file chan_iax2.c.

References ast_cli(), jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04977 {
04978    if (argc < 4 || argc > 5)
04979       return RESULT_SHOWUSAGE;
04980    jb_setoutput(jb_error_output, jb_warning_output, NULL);
04981    jb_debug_output("\n");
04982    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
04983    return RESULT_SUCCESS;
04984 }

static int iax2_no_trunk_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4967 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04968 {
04969    if (argc < 4 || argc > 5)
04970       return RESULT_SHOWUSAGE;
04971    iaxtrunkdebug = 0;
04972    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
04973    return RESULT_SUCCESS;
04974 }

static int iax2_poke_noanswer ( const void *  data  )  [static]

Definition at line 8849 of file chan_iax2.c.

References __iax2_poke_noanswer(), peer_unref(), iax2_peer::pokeexpire, and schedule_action.

Referenced by iax2_poke_peer().

08850 {
08851    struct iax2_peer *peer = (struct iax2_peer *)data;
08852    peer->pokeexpire = -1;
08853 #ifdef SCHED_MULTITHREADED
08854    if (schedule_action(__iax2_poke_noanswer, data))
08855 #endif      
08856       __iax2_poke_noanswer(data);
08857    peer_unref(peer);
08858    return 0;
08859 }

static int iax2_poke_peer ( struct iax2_peer peer,
int  heldcall 
) [static]

Definition at line 8870 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, 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, sched, 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().

08871 {
08872    int callno;
08873    if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) {
08874       /* IF we have no IP without dnsmgr, or this isn't to be monitored, return
08875         immediately after clearing things out */
08876       peer->lastms = 0;
08877       peer->historicms = 0;
08878       peer->pokeexpire = -1;
08879       peer->callno = 0;
08880       return 0;
08881    }
08882 
08883    /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */
08884    if ((callno = peer->callno) > 0) {
08885       ast_log(LOG_NOTICE, "Still have a callno...\n");
08886       ast_mutex_lock(&iaxsl[callno]);
08887       iax2_destroy(callno);
08888       ast_mutex_unlock(&iaxsl[callno]);
08889    }
08890    if (heldcall)
08891       ast_mutex_unlock(&iaxsl[heldcall]);
08892    callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0);
08893    if (heldcall)
08894       ast_mutex_lock(&iaxsl[heldcall]);
08895    if (peer->callno < 1) {
08896       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
08897       return -1;
08898    }
08899 
08900    /* Speed up retransmission times for this qualify call */
08901    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
08902    iaxs[peer->callno]->peerpoke = peer;
08903    
08904    /* Remove any pending pokeexpire task */
08905    if (peer->pokeexpire > -1) {
08906       if (!ast_sched_del(sched, peer->pokeexpire)) {
08907          peer->pokeexpire = -1;
08908          peer_unref(peer);
08909       }
08910    }
08911 
08912    /* Queue up a new task to handle no reply */
08913    /* If the host is already unreachable then use the unreachable interval instead */
08914    if (peer->lastms < 0) {
08915       peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
08916    } else
08917       peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
08918 
08919    if (peer->pokeexpire == -1)
08920       peer_unref(peer);
08921 
08922    /* And send the poke */
08923    ast_mutex_lock(&iaxsl[callno]);
08924    if (iaxs[callno]) {
08925       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
08926    }
08927    ast_mutex_unlock(&iaxsl[callno]);
08928 
08929    return 0;
08930 }

static int iax2_poke_peer_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 8861 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

08862 {
08863    struct iax2_peer *peer = obj;
08864 
08865    iax2_poke_peer(peer, 0);
08866 
08867    return 0;
08868 }

static int iax2_poke_peer_s ( const void *  data  )  [static]

Definition at line 6463 of file chan_iax2.c.

References __iax2_poke_peer_s(), iax2_peer::pokeexpire, and schedule_action.

Referenced by __iax2_poke_noanswer(), and socket_process().

06464 {
06465    struct iax2_peer *peer = (struct iax2_peer *)data;
06466    peer->pokeexpire = -1;
06467 #ifdef SCHED_MULTITHREADED
06468    if (schedule_action(__iax2_poke_peer_s, data))
06469 #endif      
06470       __iax2_poke_peer_s(data);
06471    return 0;
06472 }

static int iax2_predestroy ( int  callno  )  [static]

Note:
Since this function calls iax2_queue_hangup(), the pvt struct for the given call number may disappear during its execution.

Definition at line 2112 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().

02113 {
02114    struct ast_channel *c;
02115    struct chan_iax2_pvt *pvt = iaxs[callno];
02116 
02117    if (!pvt)
02118       return -1;
02119    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
02120       iax2_destroy_helper(pvt);
02121       ast_set_flag(pvt, IAX_ALREADYGONE); 
02122    }
02123    c = pvt->owner;
02124    if (c) {
02125       c->tech_pvt = NULL;
02126       iax2_queue_hangup(callno);
02127       pvt->owner = NULL;
02128       ast_module_unref(ast_module_info->self);
02129    }
02130    return 0;
02131 }

static void * iax2_process_thread ( void *  data  )  [static]

Definition at line 8526 of file chan_iax2.c.

References ast_cond_timedwait(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_tvadd(), iax2_process_thread_cleanup(), IAX_TYPE_DYNAMIC, iaxactivethreadcount, iaxdynamicthreadcount, insert_idle_thread(), t, and thread.

Referenced by find_idle_thread(), and start_network_thread().

08527 {
08528    struct iax2_thread *thread = data;
08529    struct timeval tv;
08530    struct timespec ts;
08531    int put_into_idle = 0;
08532 
08533    ast_atomic_fetchadd_int(&iaxactivethreadcount,1);
08534    pthread_cleanup_push(iax2_process_thread_cleanup, data);
08535    for(;;) {
08536       /* Wait for something to signal us to be awake */
08537       ast_mutex_lock(&thread->lock);
08538 
08539       /* Flag that we're ready to accept signals */
08540       thread->ready_for_signal = 1;
08541       
08542       /* Put into idle list if applicable */
08543       if (put_into_idle)
08544          insert_idle_thread(thread);
08545 
08546       if (thread->type == IAX_TYPE_DYNAMIC) {
08547          struct iax2_thread *t = NULL;
08548          /* Wait to be signalled or time out */
08549          tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08550          ts.tv_sec = tv.tv_sec;
08551          ts.tv_nsec = tv.tv_usec * 1000;
08552          if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
08553             /* This thread was never put back into the available dynamic
08554              * thread list, so just go away. */
08555             if (!put_into_idle) {
08556                ast_mutex_unlock(&thread->lock);
08557                break;
08558             }
08559             AST_LIST_LOCK(&dynamic_list);
08560             /* Account for the case where this thread is acquired *right* after a timeout */
08561             if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list)))
08562                iaxdynamicthreadcount--;
08563             AST_LIST_UNLOCK(&dynamic_list);
08564             if (t) {
08565                /* This dynamic thread timed out waiting for a task and was
08566                 * not acquired immediately after the timeout, 
08567                 * so it's time to go away. */
08568                ast_mutex_unlock(&thread->lock);
08569                break;
08570             }
08571             /* Someone grabbed our thread *right* after we timed out.
08572              * Wait for them to set us up with something to do and signal
08573              * us to continue. */
08574             tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08575             ts.tv_sec = tv.tv_sec;
08576             ts.tv_nsec = tv.tv_usec * 1000;
08577             if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT)
08578             {
08579                ast_mutex_unlock(&thread->lock);
08580                break;
08581             }
08582          }
08583       } else {
08584          ast_cond_wait(&thread->cond, &thread->lock);
08585       }
08586 
08587       /* Go back into our respective list */
08588       put_into_idle = 1;
08589 
08590       ast_mutex_unlock(&thread->lock);
08591 
08592       if (thread->iostate == IAX_IOSTATE_IDLE)
08593          continue;
08594 
08595       /* Add ourselves to the active list now */
08596       AST_LIST_LOCK(&active_list);
08597       AST_LIST_INSERT_HEAD(&active_list, thread, list);
08598       AST_LIST_UNLOCK(&active_list);
08599 
08600       /* See what we need to do */
08601       switch(thread->iostate) {
08602       case IAX_IOSTATE_READY:
08603          thread->actions++;
08604          thread->iostate = IAX_IOSTATE_PROCESSING;
08605          socket_process(thread);
08606          handle_deferred_full_frames(thread);
08607          break;
08608       case IAX_IOSTATE_SCHEDREADY:
08609          thread->actions++;
08610          thread->iostate = IAX_IOSTATE_PROCESSING;
08611 #ifdef SCHED_MULTITHREADED
08612          thread->schedfunc(thread->scheddata);
08613 #endif      
08614          break;
08615       }
08616       time(&thread->checktime);
08617       thread->iostate = IAX_IOSTATE_IDLE;
08618 #ifdef DEBUG_SCHED_MULTITHREAD
08619       thread->curfunc[0]='\0';
08620 #endif      
08621 
08622       /* Now... remove ourselves from the active list, and return to the idle list */
08623       AST_LIST_LOCK(&active_list);
08624       AST_LIST_REMOVE(&active_list, thread, list);
08625       AST_LIST_UNLOCK(&active_list);
08626 
08627       /* Make sure another frame didn't sneak in there after we thought we were done. */
08628       handle_deferred_full_frames(thread);
08629    }
08630 
08631    /*!\note For some reason, idle threads are exiting without being removed
08632     * from an idle list, which is causing memory corruption.  Forcibly remove
08633     * it from the list, if it's there.
08634     */
08635    AST_LIST_LOCK(&idle_list);
08636    AST_LIST_REMOVE(&idle_list, thread, list);
08637    AST_LIST_UNLOCK(&idle_list);
08638 
08639    AST_LIST_LOCK(&dynamic_list);
08640    AST_LIST_REMOVE(&dynamic_list, thread, list);
08641    AST_LIST_UNLOCK(&dynamic_list);
08642 
08643    /* I am exiting here on my own volition, I need to clean up my own data structures
08644    * Assume that I am no longer in any of the lists (idle, active, or dynamic)
08645    */
08646    pthread_cleanup_pop(1);
08647 
08648    return NULL;
08649 }

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8517 of file chan_iax2.c.

References ast_cond_destroy(), ast_mutex_destroy(), free, iaxactivethreadcount, and thread.

Referenced by iax2_process_thread().

08518 {
08519    struct iax2_thread *thread = data;
08520    ast_mutex_destroy(&thread->lock);
08521    ast_cond_destroy(&thread->cond);
08522    free(thread);
08523    ast_atomic_dec_and_test(&iaxactivethreadcount);
08524 }

static int iax2_prov_cmd ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 8804 of file chan_iax2.c.

References ast_cli(), iax2_provision(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

08805 {
08806    int force = 0;
08807    int res;
08808    if (argc < 4)
08809       return RESULT_SHOWUSAGE;
08810    if ((argc > 4)) {
08811       if (!strcasecmp(argv[4], "forced"))
08812          force = 1;
08813       else
08814          return RESULT_SHOWUSAGE;
08815    }
08816    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08817    if (res < 0)
08818       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08819    else if (res < 1)
08820       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08821    else
08822       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08823    return RESULT_SUCCESS;
08824 }

static char* iax2_prov_complete_template_3rd ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 8707 of file chan_iax2.c.

References iax_prov_complete_template().

08708 {
08709    if (pos != 3)
08710       return NULL;
08711    return iax_prov_complete_template(line, word, pos, state);
08712 }

static int iax2_provision ( struct sockaddr_in *  end,
int  sockfd,
char *  dest,
const char *  template,
int  force 
) [static]

Definition at line 8714 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, 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, NEW_FORCE, option_debug, iax_ie_data::pos, sched, and send_command().

Referenced by check_provisioning(), iax2_prov_app(), and iax2_prov_cmd().

08715 {
08716    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
08717       is found for template */
08718    struct iax_ie_data provdata;
08719    struct iax_ie_data ied;
08720    unsigned int sig;
08721    struct sockaddr_in sin;
08722    int callno;
08723    struct create_addr_info cai;
08724 
08725    memset(&cai, 0, sizeof(cai));
08726 
08727    if (option_debug)
08728       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
08729 
08730    if (iax_provision_build(&provdata, &sig, template, force)) {
08731       if (option_debug)
08732          ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
08733       return 0;
08734    }
08735 
08736    if (end) {
08737       memcpy(&sin, end, sizeof(sin));
08738       cai.sockfd = sockfd;
08739    } else if (create_addr(dest, NULL, &sin, &cai))
08740       return -1;
08741 
08742    /* Build the rest of the message */
08743    memset(&ied, 0, sizeof(ied));
08744    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
08745 
08746    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
08747    if (!callno)
08748       return -1;
08749 
08750    if (iaxs[callno]) {
08751       /* Schedule autodestruct in case they don't ever give us anything back */
08752       AST_SCHED_DEL(sched, iaxs[callno]->autoid);
08753       iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
08754       ast_set_flag(iaxs[callno], IAX_PROVISION);
08755       /* Got a call number now, so go ahead and send the provisioning information */
08756       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
08757    }
08758    ast_mutex_unlock(&iaxsl[callno]);
08759 
08760    return 1;
08761 }

static int iax2_prune_realtime ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2236 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.

02237 {
02238    struct iax2_peer *peer;
02239 
02240    if (argc != 4)
02241         return RESULT_SHOWUSAGE;
02242    if (!strcmp(argv[3],"all")) {
02243       reload_config();
02244       ast_cli(fd, "OK cache is flushed.\n");
02245    } else if ((peer = find_peer(argv[3], 0))) {
02246       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
02247          ast_set_flag(peer, IAX_RTAUTOCLEAR);
02248          expire_registry(peer_ref(peer));
02249          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
02250       } else {
02251          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
02252       }
02253       peer_unref(peer);
02254    } else {
02255       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
02256    }
02257    
02258    return RESULT_SUCCESS;
02259 }

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.

Precondition:
Assumes lock for callno is already held.
Note:
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 may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.

Definition at line 1722 of file chan_iax2.c.

References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_control_data(), DEADLOCK_AVOIDANCE, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.

Referenced by socket_process().

01724 {
01725    for (;;) {
01726       if (iaxs[callno] && iaxs[callno]->owner) {
01727          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01728             /* Avoid deadlock by pausing and trying again */
01729             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01730          } else {
01731             ast_queue_control_data(iaxs[callno]->owner, control, data, datalen);
01732             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01733             break;
01734          }
01735       } else
01736          break;
01737    }
01738    return 0;
01739 }

static int iax2_queue_frame ( int  callno,
struct ast_frame f 
) [static]

Queue a frame to a call's owning asterisk channel.

Precondition:
This function assumes that iaxsl[callno] is locked when called.
Note:
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 may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.

Definition at line 1660 of file chan_iax2.c.

References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, f, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.

Referenced by __attempt_transmit(), __auto_congest(), __do_deliver(), __get_from_jb(), and socket_process().

01661 {
01662    for (;;) {
01663       if (iaxs[callno] && iaxs[callno]->owner) {
01664          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01665             /* Avoid deadlock by pausing and trying again */
01666             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01667          } else {
01668             ast_queue_frame(iaxs[callno]->owner, f);
01669             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01670             break;
01671          }
01672       } else
01673          break;
01674    }
01675    return 0;
01676 }

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.

Precondition:
Assumes lock for callno is already held.
Note:
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 may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.

Definition at line 1691 of file chan_iax2.c.

References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.

Referenced by iax2_predestroy().

01692 {
01693    for (;;) {
01694       if (iaxs[callno] && iaxs[callno]->owner) {
01695          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01696             /* Avoid deadlock by pausing and trying again */
01697             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01698          } else {
01699             ast_queue_hangup(iaxs[callno]->owner);
01700             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01701             break;
01702          }
01703       } else
01704          break;
01705    }
01706    return 0;
01707 }

static struct ast_frame * iax2_read ( struct ast_channel c  )  [static]

Definition at line 3428 of file chan_iax2.c.

References ast_log(), ast_null_frame, and LOG_NOTICE.

03429 {
03430    ast_log(LOG_NOTICE, "I should never be called!\n");
03431    return &ast_null_frame;
03432 }

static int iax2_register ( char *  value,
int  lineno 
) [static]

Definition at line 5945 of file chan_iax2.c.

References ast_calloc, ast_dnsmgr_lookup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), copy(), free, hostname, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, LOG_WARNING, secret, and strsep().

Referenced by set_config().

05946 {
05947    struct iax2_registry *reg;
05948    char copy[256];
05949    char *username, *hostname, *secret;
05950    char *porta;
05951    char *stringp=NULL;
05952    
05953    if (!value)
05954       return -1;
05955    ast_copy_string(copy, value, sizeof(copy));
05956    stringp=copy;
05957    username = strsep(&stringp, "@");
05958    hostname = strsep(&stringp, "@");
05959    if (!hostname) {
05960       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
05961       return -1;
05962    }
05963    stringp=username;
05964    username = strsep(&stringp, ":");
05965    secret = strsep(&stringp, ":");
05966    stringp=hostname;
05967    hostname = strsep(&stringp, ":");
05968    porta = strsep(&stringp, ":");
05969    
05970    if (porta && !atoi(porta)) {
05971       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
05972       return -1;
05973    }
05974    if (!(reg = ast_calloc(1, sizeof(*reg))))
05975       return -1;
05976    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
05977       free(reg);
05978       return -1;
05979    }
05980    ast_copy_string(reg->username, username, sizeof(reg->username));
05981    if (secret)
05982       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
05983    reg->expire = -1;
05984    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
05985    reg->addr.sin_family = AF_INET;
05986    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
05987    AST_LIST_LOCK(&registrations);
05988    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
05989    AST_LIST_UNLOCK(&registrations);
05990    
05991    return 0;
05992 }

static int iax2_reload ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10240 of file chan_iax2.c.

References reload_config().

10241 {
10242    return reload_config();
10243 }

static struct ast_channel * iax2_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static]

Definition at line 8942 of file chan_iax2.c.

References ast_best_codec(), AST_CAUSE_CONGESTION, AST_CAUSE_UNREGISTERED, ast_copy_flags, ast_getformatname(), ast_hangup(), ast_iax2_new(), ast_log(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_translator_best_choice(), create_addr(), find_callno_locked(), fmt, globalflags, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iaxsl, LOG_WARNING, make_trunk(), chan_iax2_pvt::maxtime, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), ast_channel::readformat, and ast_channel::writeformat.

08943 {
08944    int callno;
08945    int res;
08946    int fmt, native;
08947    struct sockaddr_in sin;
08948    struct ast_channel *c;
08949    struct parsed_dial_string pds;
08950    struct create_addr_info cai;
08951    char *tmpstr;
08952 
08953    memset(&pds, 0, sizeof(pds));
08954    tmpstr = ast_strdupa(data);
08955    parse_dial_string(tmpstr, &pds);
08956 
08957    if (ast_strlen_zero(pds.peer)) {
08958       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
08959       return NULL;
08960    }
08961           
08962    memset(&cai, 0, sizeof(cai));
08963    cai.capability = iax2_capability;
08964 
08965    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08966    
08967    /* Populate our address from the given */
08968    if (create_addr(pds.peer, NULL, &sin, &cai)) {
08969       *cause = AST_CAUSE_UNREGISTERED;
08970       return NULL;
08971    }
08972 
08973    if (pds.port)
08974       sin.sin_port = htons(atoi(pds.port));
08975 
08976    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
08977    if (callno < 1) {
08978       ast_log(LOG_WARNING, "Unable to create call\n");
08979       *cause = AST_CAUSE_CONGESTION;
08980       return NULL;
08981    }
08982 
08983    /* If this is a trunk, update it now */
08984    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
08985    if (ast_test_flag(&cai, IAX_TRUNK)) {
08986       int new_callno;
08987       if ((new_callno = make_trunk(callno, 1)) != -1)
08988          callno = new_callno;
08989    }
08990    iaxs[callno]->maxtime = cai.maxtime;
08991    if (cai.found)
08992       ast_string_field_set(iaxs[callno], host, pds.peer);
08993 
08994    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
08995 
08996    ast_mutex_unlock(&iaxsl[callno]);
08997 
08998    if (c) {
08999       /* Choose a format we can live with */
09000       if (c->nativeformats & format) 
09001          c->nativeformats &= format;
09002       else {
09003          native = c->nativeformats;
09004          fmt = format;
09005          res = ast_translator_best_choice(&fmt, &native);
09006          if (res < 0) {
09007             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
09008                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
09009             ast_hangup(c);
09010             return NULL;
09011          }
09012          c->nativeformats = native;
09013       }
09014       c->readformat = ast_best_codec(c->nativeformats);
09015       c->writeformat = c->readformat;
09016    }
09017 
09018    return c;
09019 }

static int iax2_sched_add ( struct sched_context con,
int  when,
ast_sched_cb  callback,
const void *  data 
) [static]

Definition at line 983 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(), reg_source_db(), socket_process(), update_jbsched(), and update_registry().

00984 {
00985    int res;
00986 
00987    res = ast_sched_add(con, when, callback, data);
00988    signal_condition(&sched_lock, &sched_cond);
00989 
00990    return res;
00991 }

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 4269 of file chan_iax2.c.

References 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, ast_frame::datalen, iax_frame::datalen, ast_iax2_full_hdr::dcallno, iax_frame::dcallno, DIRECTION_OUTGRESS, encrypt_frame(), f, 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, 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, send_packet(), ast_frame::subclass, chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, iax_frame::transfer, 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().

04270 {
04271    /* Queue a packet for delivery on a given private structure.  Use "ts" for
04272       timestamp, or calculate if ts is 0.  Send immediately without retransmission
04273       or delayed, with retransmission */
04274    struct ast_iax2_full_hdr *fh;
04275    struct ast_iax2_mini_hdr *mh;
04276    struct ast_iax2_video_hdr *vh;
04277    struct {
04278       struct iax_frame fr2;
04279       unsigned char buffer[4096];
04280    } frb;
04281    struct iax_frame *fr;
04282    int res;
04283    int sendmini=0;
04284    unsigned int lastsent;
04285    unsigned int fts;
04286 
04287    frb.fr2.afdatalen = sizeof(frb.buffer);
04288 
04289    if (!pvt) {
04290       ast_log(LOG_WARNING, "No private structure for packet?\n");
04291       return -1;
04292    }
04293    
04294    lastsent = pvt->lastsent;
04295 
04296    /* Calculate actual timestamp */
04297    fts = calc_timestamp(pvt, ts, f);
04298 
04299    /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out
04300     * (the endpoint should detect the lost packet itself).  But, we want to do this here, so that we
04301     * increment the "predicted timestamps" for voice, if we're predecting */
04302    if(f->frametype == AST_FRAME_VOICE && f->datalen == 0)
04303        return 0;
04304 
04305 
04306    if ((ast_test_flag(pvt, IAX_TRUNK) || 
04307          (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) ||
04308          ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L))))
04309       /* High two bytes are the same on timestamp, or sending on a trunk */ &&
04310        (f->frametype == AST_FRAME_VOICE) 
04311       /* is a voice frame */ &&
04312       (f->subclass == pvt->svoiceformat) 
04313       /* is the same type */ ) {
04314          /* Force immediate rather than delayed transmission */
04315          now = 1;
04316          /* Mark that mini-style frame is appropriate */
04317          sendmini = 1;
04318    }
04319    if ( f->frametype == AST_FRAME_VIDEO ) {
04320       /*
04321        * If the lower 15 bits of the timestamp roll over, or if
04322        * the video format changed then send a full frame.
04323        * Otherwise send a mini video frame
04324        */
04325       if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) &&
04326           ((f->subclass & ~0x1) == pvt->svideoformat)
04327          ) {
04328          now = 1;
04329          sendmini = 1;
04330       } else {
04331          now = 0;
04332          sendmini = 0;
04333       }
04334       pvt->lastvsent = fts;
04335    }
04336    /* Allocate an iax_frame */
04337    if (now) {
04338       fr = &frb.fr2;
04339    } else
04340       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));
04341    if (!fr) {
04342       ast_log(LOG_WARNING, "Out of memory\n");
04343       return -1;
04344    }
04345    /* Copy our prospective frame into our immediate or retransmitted wrapper */
04346    iax_frame_wrap(fr, f);
04347 
04348    fr->ts = fts;
04349    fr->callno = pvt->callno;
04350    fr->transfer = transfer;
04351    fr->final = final;
04352    if (!sendmini) {
04353       /* We need a full frame */
04354       if (seqno > -1)
04355          fr->oseqno = seqno;
04356       else
04357          fr->oseqno = pvt->oseqno++;
04358       fr->iseqno = pvt->iseqno;
04359       fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr));
04360       fh->scallno = htons(fr->callno | IAX_FLAG_FULL);
04361       fh->ts = htonl(fr->ts);
04362       fh->oseqno = fr->oseqno;
04363       if (transfer) {
04364          fh->iseqno = 0;
04365       } else
04366          fh->iseqno = fr->iseqno;
04367       /* Keep track of the last thing we've acknowledged */
04368       if (!transfer)
04369          pvt->aseqno = fr->iseqno;
04370       fh->type = fr->af.frametype & 0xFF;
04371       if (fr->af.frametype == AST_FRAME_VIDEO)
04372          fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6);
04373       else
04374          fh->csub = compress_subclass(fr->af.subclass);
04375       if (transfer) {
04376          fr->dcallno = pvt->transfercallno;
04377       } else
04378          fr->dcallno = pvt->peercallno;
04379       fh->dcallno = htons(fr->dcallno);
04380       fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr);
04381       fr->data = fh;
04382       fr->retries = 0;
04383       /* Retry after 2x the ping time has passed */
04384       fr->retrytime = pvt->pingtime * 2;
04385       if (fr->retrytime < MIN_RETRY_TIME)
04386          fr->retrytime = MIN_RETRY_TIME;
04387       if (fr->retrytime > MAX_RETRY_TIME)
04388          fr->retrytime = MAX_RETRY_TIME;
04389       /* Acks' don't get retried */
04390       if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK))
04391          fr->retries = -1;
04392       else if (f->frametype == AST_FRAME_VOICE)
04393          pvt->svoiceformat = f->subclass;
04394       else if (f->frametype == AST_FRAME_VIDEO)
04395          pvt->svideoformat = f->subclass & ~0x1;
04396       if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04397          if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04398             if (iaxdebug) {
04399                if (fr->transfer)
04400                   iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr));
04401                else
04402                   iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr));
04403             }
04404             encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen);
04405          } else
04406             ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04407       }
04408    
04409       if (now) {
04410          res = send_packet(fr);
04411       } else
04412          res = iax2_transmit(fr);
04413    } else {
04414       if (ast_test_flag(pvt, IAX_TRUNK)) {
04415          iax2_trunk_queue(pvt, fr);
04416          res = 0;
04417       } else if (fr->af.frametype == AST_FRAME_VIDEO) {
04418          /* Video frame have no sequence number */
04419          fr->oseqno = -1;
04420          fr->iseqno = -1;
04421          vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr));
04422          vh->zeros = 0;
04423          vh->callno = htons(0x8000 | fr->callno);
04424          vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0));
04425          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);
04426          fr->data = vh;
04427          fr->retries = -1;
04428          res = send_packet(fr);        
04429       } else {
04430          /* Mini-frames have no sequence number */
04431          fr->oseqno = -1;
04432          fr->iseqno = -1;
04433          /* Mini frame will do */
04434          mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr));
04435          mh->callno = htons(fr->callno);
04436          mh->ts = htons(fr->ts & 0xFFFF);
04437          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);
04438          fr->data = mh;
04439          fr->retries = -1;
04440          if (pvt->transferring == TRANSFER_MEDIAPASS)
04441             fr->transfer = 1;
04442          if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04443             if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04444                encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen);
04445             } else
04446                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04447          }
04448          res = send_packet(fr);
04449       }
04450    }
04451    return res;
04452 }

static int iax2_sendhtml ( struct ast_channel c,
int  subclass,
const char *  data,
int  datalen 
) [static]

Definition at line 2761 of file chan_iax2.c.

References AST_FRAME_HTML, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.

02762 {
02763    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02764 }

static int iax2_sendimage ( struct ast_channel c,
struct ast_frame img 
) [static]

Definition at line 2756 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.

02757 {
02758    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
02759 }

static int iax2_sendtext ( struct ast_channel c,
const char *  text 
) [static]

Definition at line 2749 of file chan_iax2.c.

References AST_FRAME_TEXT, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.

02750 {
02751    
02752    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02753       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02754 }

static int iax2_setoption ( struct ast_channel c,
int  option,
void *  data,
int  datalen 
) [static]

Definition at line 3402 of file chan_iax2.c.

References AST_CONTROL_OPTION, AST_FRAME_CONTROL, ast_malloc, AST_OPTION_FLAG_REQUEST, AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, errno, free, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.

03403 {
03404    struct ast_option_header *h;
03405    int res;
03406 
03407    switch (option) {
03408    case AST_OPTION_TXGAIN:
03409    case AST_OPTION_RXGAIN:
03410       /* these two cannot be sent, because they require a result */
03411       errno = ENOSYS;
03412       return -1;
03413    default:
03414       if (!(h = ast_malloc(datalen + sizeof(*h))))
03415          return -1;
03416 
03417       h->flag = AST_OPTION_FLAG_REQUEST;
03418       h->option = htons(option);
03419       memcpy(h->data, data, datalen);
03420       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03421                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03422                  datalen + sizeof(*h), -1);
03423       free(h);
03424       return res;
03425    }
03426 }

static int iax2_show_cache ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2440 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.

02441 {
02442    struct iax2_dpcache *dp;
02443    char tmp[1024], *pc;
02444    int s;
02445    int x,y;
02446    struct timeval tv;
02447    gettimeofday(&tv, NULL);
02448    ast_mutex_lock(&dpcache_lock);
02449    dp = dpcache;
02450    ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02451    while(dp) {
02452       s = dp->expiry.tv_sec - tv.tv_sec;
02453       tmp[0] = '\0';
02454       if (dp->flags & CACHE_FLAG_EXISTS)
02455          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02456       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02457          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02458       if (dp->flags & CACHE_FLAG_CANEXIST)
02459          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02460       if (dp->flags & CACHE_FLAG_PENDING)
02461          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02462       if (dp->flags & CACHE_FLAG_TIMEOUT)
02463          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02464       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02465          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02466       if (dp->flags & CACHE_FLAG_MATCHMORE)
02467          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02468       if (dp->flags & CACHE_FLAG_UNKNOWN)
02469          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02470       /* Trim trailing pipe */
02471       if (!ast_strlen_zero(tmp))
02472          tmp[strlen(tmp) - 1] = '\0';
02473       else
02474          ast_copy_string(tmp, "(none)", sizeof(tmp));
02475       y=0;
02476       pc = strchr(dp->peercontext, '@');
02477       if (!pc)
02478          pc = dp->peercontext;
02479       else
02480          pc++;
02481       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
02482          if (dp->waiters[x] > -1)
02483             y++;
02484       if (s > 0)
02485          ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02486       else
02487          ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02488       dp = dp->next;
02489    }
02490    ast_mutex_unlock(&dpcache_lock);
02491    return RESULT_SUCCESS;
02492 }

static int iax2_show_channels ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4796 of file chan_iax2.c.

References 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.

04797 {
04798 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04799 #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"
04800 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04801    int x;
04802    int numchans = 0;
04803 
04804    if (argc != 3)
04805       return RESULT_SHOWUSAGE;
04806    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04807    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04808       ast_mutex_lock(&iaxsl[x]);
04809       if (iaxs[x]) {
04810          int lag, jitter, localdelay;
04811          jb_info jbinfo;
04812          
04813          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04814             jb_getinfo(iaxs[x]->jb, &jbinfo);
04815             jitter = jbinfo.jitter;
04816             localdelay = jbinfo.current - jbinfo.min;
04817          } else {
04818             jitter = -1;
04819             localdelay = 0;
04820          }
04821          lag = iaxs[x]->remote_rr.delay;
04822          ast_cli(fd, FORMAT,
04823             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04824             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04825             S_OR(iaxs[x]->username, "(None)"),
04826             iaxs[x]->callno, iaxs[x]->peercallno,
04827             iaxs[x]->oseqno, iaxs[x]->iseqno,
04828             lag,
04829             jitter,
04830             localdelay,
04831             ast_getformatname(iaxs[x]->voiceformat) );
04832          numchans++;
04833       }
04834       ast_mutex_unlock(&iaxsl[x]);
04835    }
04836    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04837    return RESULT_SUCCESS;
04838 #undef FORMAT
04839 #undef FORMAT2
04840 #undef FORMATB
04841 }

static int iax2_show_firmware ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4707 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.

04708 {
04709 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04710 #if !defined(__FreeBSD__)
04711 #define FORMAT "%-15.15s  %-15d %-15d\n"
04712 #else /* __FreeBSD__ */
04713 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04714 #endif /* __FreeBSD__ */
04715    struct iax_firmware *cur;
04716    if ((argc != 3) && (argc != 4))
04717       return RESULT_SHOWUSAGE;
04718    ast_mutex_lock(&waresl.lock);
04719    
04720    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04721    for (cur = waresl.wares;cur;cur = cur->next) {
04722       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04723          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04724             (int)ntohl(cur->fwh->datalen));
04725    }
04726    ast_mutex_unlock(&waresl.lock);
04727    return RESULT_SUCCESS;
04728 #undef FORMAT
04729 #undef FORMAT2
04730 }

static int iax2_show_netstats ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4919 of file chan_iax2.c.

References ast_cli(), ast_cli_netstats(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04920 {
04921    int numchans = 0;
04922    if (argc != 3)
04923       return RESULT_SHOWUSAGE;
04924    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04925    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04926    numchans = ast_cli_netstats(NULL, fd, 1);
04927    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04928    return RESULT_SUCCESS;
04929 }

static int iax2_show_peer ( int  fd,
int  argc,
char *  argv[] 
) [static]

Show one peer in detail.

Definition at line 2330 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.

02331 {
02332    char status[30];
02333    char cbuf[256];
02334    struct iax2_peer *peer;
02335    char codec_buf[512];
02336    int x = 0, codec = 0, load_realtime = 0;
02337 
02338    if (argc < 4)
02339       return RESULT_SHOWUSAGE;
02340 
02341    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0;
02342 
02343    peer = find_peer(argv[3], load_realtime);
02344    if (peer) {
02345       ast_cli(fd,"\n\n");
02346       ast_cli(fd, "  * Name       : %s\n", peer->name);
02347       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
02348       ast_cli(fd, "  Context      : %s\n", peer->context);
02349       ast_cli(fd, "  Mailbox      : %s\n", peer->mailbox);
02350       ast_cli(fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No");
02351       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
02352       ast_cli(fd, "  Expire       : %d\n", peer->expire);
02353       ast_cli(fd, "  ACL          : %s\n", (peer->ha?"Yes":"No"));
02354       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));
02355       ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
02356       ast_cli(fd, "  Username     : %s\n", peer->username);
02357       ast_cli(fd, "  Codecs       : ");
02358       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
02359       ast_cli(fd, "%s\n", codec_buf);
02360 
02361       ast_cli(fd, "  Codec Order  : (");
02362       for(x = 0; x < 32 ; x++) {
02363          codec = ast_codec_pref_index(&peer->prefs,x);
02364          if(!codec)
02365             break;
02366          ast_cli(fd, "%s", ast_getformatname(codec));
02367          if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1))
02368             ast_cli(fd, "|");
02369       }
02370 
02371       if (!x)
02372          ast_cli(fd, "none");
02373       ast_cli(fd, ")\n");
02374 
02375       ast_cli(fd, "  Status       : ");
02376       peer_status(peer, status, sizeof(status));   
02377       ast_cli(fd, "%s\n",status);
02378       ast_cli(fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
02379       ast_cli(fd,"\n");
02380       peer_unref(peer);
02381    } else {
02382       ast_cli(fd,"Peer %s not found.\n", argv[3]);
02383       ast_cli(fd,"\n");
02384    }
02385 
02386    return RESULT_SUCCESS;
02387 }

static int iax2_show_peers ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4696 of file chan_iax2.c.

References __iax2_show_peers().

04697 {
04698    return __iax2_show_peers(0, fd, NULL, argc, argv);
04699 }

static int iax2_show_registry ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4768 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.

04769 {
04770 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04771 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04772    struct iax2_registry *reg = NULL;
04773 
04774    char host[80];
04775    char perceived[80];
04776    if (argc != 3)
04777       return RESULT_SHOWUSAGE;
04778    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04779    AST_LIST_LOCK(&registrations);
04780    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04781       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04782       if (reg->us.sin_addr.s_addr) 
04783          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04784       else
04785          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04786       ast_cli(fd, FORMAT, host, 
04787                (reg->dnsmgr) ? "Y" : "N", 
04788                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04789    }
04790    AST_LIST_UNLOCK(&registrations);
04791    return RESULT_SUCCESS;
04792 #undef FORMAT
04793 #undef FORMAT2
04794 }

static int iax2_show_stats ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2414 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.

02415 {
02416    struct iax_frame *cur;
02417    int cnt = 0, dead=0, final=0;
02418 
02419    if (argc != 3)
02420       return RESULT_SHOWUSAGE;
02421 
02422    AST_LIST_LOCK(&iaxq.queue);
02423    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02424       if (cur->retries < 0)
02425          dead++;
02426       if (cur->final)
02427          final++;
02428       cnt++;
02429    }
02430    AST_LIST_UNLOCK(&iaxq.queue);
02431 
02432    ast_cli(fd, "    IAX Statistics\n");
02433    ast_cli(fd, "---------------------\n");
02434    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02435    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02436    
02437    return RESULT_SUCCESS;
02438 }

static int iax2_show_threads ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4637 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, thread, and type.

04638 {
04639    struct iax2_thread *thread = NULL;
04640    time_t t;
04641    int threadcount = 0, dynamiccount = 0;
04642    char type;
04643 
04644    if (argc != 3)
04645       return RESULT_SHOWUSAGE;
04646       
04647    ast_cli(fd, "IAX2 Thread Information\n");
04648    time(&t);
04649    ast_cli(fd, "Idle Threads:\n");
04650    AST_LIST_LOCK(&idle_list);
04651    AST_LIST_TRAVERSE(&idle_list, thread, list) {
04652 #ifdef DEBUG_SCHED_MULTITHREAD
04653       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04654          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04655 #else
04656       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
04657          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04658 #endif
04659       threadcount++;
04660    }
04661    AST_LIST_UNLOCK(&idle_list);
04662    ast_cli(fd, "Active Threads:\n");
04663    AST_LIST_LOCK(&active_list);
04664    AST_LIST_TRAVERSE(&active_list, thread, list) {
04665       if (thread->type == IAX_TYPE_DYNAMIC)
04666          type = 'D';
04667       else
04668          type = 'P';
04669 #ifdef DEBUG_SCHED_MULTITHREAD
04670       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04671          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04672 #else
04673       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04674          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04675 #endif
04676       threadcount++;
04677    }
04678    AST_LIST_UNLOCK(&active_list);
04679    ast_cli(fd, "Dynamic Threads:\n");
04680         AST_LIST_LOCK(&dynamic_list);
04681         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04682 #ifdef DEBUG_SCHED_MULTITHREAD
04683                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04684                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04685 #else
04686                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04687                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04688 #endif
04689       dynamiccount++;
04690         }
04691         AST_LIST_UNLOCK(&dynamic_list);
04692    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04693    return RESULT_SUCCESS;
04694 }

static int iax2_show_users ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4454 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.

04455 {
04456    regex_t regexbuf;
04457    int havepattern = 0;
04458 
04459 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
04460 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
04461 
04462    struct iax2_user *user = NULL;
04463    char auth[90];
04464    char *pstr = "";
04465    struct ao2_iterator i;
04466 
04467    switch (argc) {
04468    case 5:
04469       if (!strcasecmp(argv[3], "like")) {
04470          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04471             return RESULT_SHOWUSAGE;
04472          havepattern = 1;
04473       } else
04474          return RESULT_SHOWUSAGE;
04475    case 3:
04476       break;
04477    default:
04478       return RESULT_SHOWUSAGE;
04479    }
04480 
04481    ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
04482    i = ao2_iterator_init(users, 0);
04483    for (user = ao2_iterator_next(&i); user; 
04484       user_unref(user), user = ao2_iterator_next(&i)) {
04485       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
04486          continue;
04487       
04488       if (!ast_strlen_zero(user->secret)) {
04489          ast_copy_string(auth,user->secret,sizeof(auth));
04490       } else if (!ast_strlen_zero(user->inkeys)) {
04491          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
04492       } else
04493          ast_copy_string(auth, "-no secret-", sizeof(auth));
04494       
04495       if(ast_test_flag(user,IAX_CODEC_NOCAP))
04496          pstr = "REQ Only";
04497       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
04498          pstr = "Disabled";
04499       else
04500          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
04501       
04502       ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
04503          user->contexts ? user->contexts->context : context,
04504          user->ha ? "Yes" : "No", pstr);
04505    }
04506 
04507    if (havepattern)
04508       regfree(&regexbuf);
04509 
04510    return RESULT_SUCCESS;
04511 #undef FORMAT
04512 #undef FORMAT2
04513 }

static int iax2_start_transfer ( unsigned short  callno0,
unsigned short  callno1,
int  mediaonly 
) [static]

Definition at line 3434 of file chan_iax2.c.

References AST_FRAME_IAX, ast_random(), 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, send_command(), TRANSFER_BEGIN, TRANSFER_MBEGIN, and chan_iax2_pvt::transferring.

03435 {
03436    int res;
03437    struct iax_ie_data ied0;
03438    struct iax_ie_data ied1;
03439    unsigned int transferid = (unsigned int)ast_random();
03440    memset(&ied0, 0, sizeof(ied0));
03441    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03442    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03443    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03444 
03445    memset(&ied1, 0, sizeof(ied1));
03446    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03447    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03448    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03449    
03450    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03451    if (res)
03452       return -1;
03453    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03454    if (res)
03455       return -1;
03456    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03457    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03458    return 0;
03459 }

static int iax2_test_losspct ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2261 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02262 {
02263        if (argc != 4)
02264                return RESULT_SHOWUSAGE;
02265 
02266        test_losspct = atoi(argv[3]);
02267 
02268        return RESULT_SUCCESS;
02269 }

static int iax2_transfer ( struct ast_channel c,
const char *  dest 
) [static]

Definition at line 3680 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), chan_iax2_pvt::callno, IAX_COMMAND_TRANSFER, iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, option_debug, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.

03681 {
03682    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03683    struct iax_ie_data ied;
03684    char tmp[256], *context;
03685    ast_copy_string(tmp, dest, sizeof(tmp));
03686    context = strchr(tmp, '@');
03687    if (context) {
03688       *context = '\0';
03689       context++;
03690    }
03691    memset(&ied, 0, sizeof(ied));
03692    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03693    if (context)
03694       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03695    if (option_debug)
03696       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03697    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03698 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

Definition at line 2720 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().

02721 {
02722    /* Lock the queue and place this packet at the end */
02723    /* By setting this to 0, the network thread will send it for us, and
02724       queue retransmission if necessary */
02725    fr->sentyet = 0;
02726    AST_LIST_LOCK(&iaxq.queue);
02727    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02728    iaxq.count++;
02729    AST_LIST_UNLOCK(&iaxq.queue);
02730    /* Wake up the network and scheduler thread */
02731    if (netthreadid != AST_PTHREADT_NULL)
02732       pthread_kill(netthreadid, SIGURG);
02733    signal_condition(&sched_lock, &sched_cond);
02734    return 0;
02735 }

static int iax2_trunk_expired ( struct iax2_trunk_peer tpeer,
struct timeval *  now 
) [inline, static]

Definition at line 6518 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06519 {
06520    /* Drop when trunk is about 5 seconds idle */
06521    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06522       return 1;
06523    return 0;
06524 }

static int iax2_trunk_queue ( struct chan_iax2_pvt pvt,
struct iax_frame fr 
) [static]

Definition at line 4043 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, DEFAULT_TRUNKDATA, f, find_tpeer(), globalflags, IAX2_TRUNK_PREFACE, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, 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().

04044 {
04045    struct ast_frame *f;
04046    struct iax2_trunk_peer *tpeer;
04047    void *tmp, *ptr;
04048    struct ast_iax2_meta_trunk_entry *met;
04049    struct ast_iax2_meta_trunk_mini *mtm;
04050 
04051    f = &fr->af;
04052    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
04053    if (tpeer) {
04054       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
04055          /* Need to reallocate space */
04056          if (tpeer->trunkdataalloc < MAX_TRUNKDATA) {
04057             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
04058                ast_mutex_unlock(&tpeer->lock);
04059                return -1;
04060             }
04061             
04062             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
04063             tpeer->trunkdata = tmp;
04064             if (option_debug)
04065                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);
04066          } else {
04067             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));
04068             ast_mutex_unlock(&tpeer->lock);
04069             return -1;
04070          }
04071       }
04072 
04073       /* Append to meta frame */
04074       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
04075       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
04076          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
04077          mtm->len = htons(f->datalen);
04078          mtm->mini.callno = htons(pvt->callno);
04079          mtm->mini.ts = htons(0xffff & fr->ts);
04080          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
04081          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
04082       } else {
04083          met = (struct ast_iax2_meta_trunk_entry *)ptr;
04084          /* Store call number and length in meta header */
04085          met->callno = htons(pvt->callno);
04086          met->len = htons(f->datalen);
04087          /* Advance pointers/decrease length past trunk entry header */
04088          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
04089          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
04090       }
04091       /* Copy actual trunk data */
04092       memcpy(ptr, f->data, f->datalen);
04093       tpeer->trunkdatalen += f->datalen;
04094 
04095       tpeer->calls++;
04096       ast_mutex_unlock(&tpeer->lock);
04097    }
04098    return 0;
04099 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6435 of file chan_iax2.c.

References AST_FRAME_IAX, IAX_COMMAND_VNAK, iaxs, and send_command_immediate().

Referenced by socket_process().

06436 {
06437    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06438 }

static int iax2_write ( struct ast_channel c,
struct ast_frame f 
) [static]

Definition at line 4986 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(), f, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, iaxs, iaxsl, option_debug, PTR_TO_CALLNO, and ast_channel::tech_pvt.

04987 {
04988    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
04989    int res = -1;
04990    ast_mutex_lock(&iaxsl[callno]);
04991    if (iaxs[callno]) {
04992    /* If there's an outstanding error, return failure now */
04993       if (!iaxs[callno]->error) {
04994          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
04995             res = 0;
04996             /* Don't waste bandwidth sending null frames */
04997          else if (f->frametype == AST_FRAME_NULL)
04998             res = 0;
04999          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
05000             res = 0;
05001          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
05002             res = 0;
05003          else
05004          /* Simple, just queue for transmission */
05005             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
05006       } else {
05007          if (option_debug)
05008             ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
05009       }
05010    }
05011    /* If it's already gone, just return */
05012    ast_mutex_unlock(&iaxsl[callno]);
05013    return res;
05014 }

static int iax_check_version ( char *  dev  )  [static]

Definition at line 1895 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().

01896 {
01897    int res = 0;
01898    struct iax_firmware *cur;
01899    if (!ast_strlen_zero(dev)) {
01900       ast_mutex_lock(&waresl.lock);
01901       cur = waresl.wares;
01902       while(cur) {
01903          if (!strcmp(dev, (char *)cur->fwh->devname)) {
01904             res = ntohs(cur->fwh->version);
01905             break;
01906          }
01907          cur = cur->next;
01908       }
01909       ast_mutex_unlock(&waresl.lock);
01910    }
01911    return res;
01912 }

static void iax_debug_output ( const char *  data  )  [static]

Definition at line 761 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

00762 {
00763    if (iaxdebug)
00764       ast_verbose("%s", data);
00765 }

static void iax_error_output ( const char *  data  )  [static]

Definition at line 767 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

00768 {
00769    ast_log(LOG_WARNING, "%s", data);
00770 }

static int iax_firmware_append ( struct iax_ie_data ied,
const unsigned char *  dev,
unsigned int  desc 
) [static]

Definition at line 1914 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().

01915 {
01916    int res = -1;
01917    unsigned int bs = desc & 0xff;
01918    unsigned int start = (desc >> 8) & 0xffffff;
01919    unsigned int bytes;
01920    struct iax_firmware *cur;
01921    if (!ast_strlen_zero((char *)dev) && bs) {
01922       start *= bs;
01923       ast_mutex_lock(&waresl.lock);
01924       cur = waresl.wares;
01925       while(cur) {
01926          if (!strcmp((char *)dev, (char *)cur->fwh->devname)) {
01927             iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
01928             if (start < ntohl(cur->fwh->datalen)) {
01929                bytes = ntohl(cur->fwh->datalen) - start;
01930                if (bytes > bs)
01931                   bytes = bs;
01932                iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
01933             } else {
01934                bytes = 0;
01935                iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
01936             }
01937             if (bytes == bs)
01938                res = 0;
01939             else
01940                res = 1;
01941             break;
01942          }
01943          cur = cur->next;
01944       }
01945       ast_mutex_unlock(&waresl.lock);
01946    }
01947    return res;
01948 }

static int iax_park ( struct ast_channel chan1,
struct ast_channel chan2 
) [static]

Definition at line 6706 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, 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().

06707 {
06708    struct iax_dual *d;
06709    struct ast_channel *chan1m, *chan2m;
06710    pthread_t th;
06711    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
06712    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
06713    if (chan2m && chan1m) {
06714       /* Make formats okay */
06715       chan1m->readformat = chan1->readformat;
06716       chan1m->writeformat = chan1->writeformat;
06717       ast_channel_masquerade(chan1m, chan1);
06718       /* Setup the extensions and such */
06719       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
06720       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
06721       chan1m->priority = chan1->priority;
06722       
06723       /* We make a clone of the peer channel too, so we can play
06724          back the announcement */
06725       /* Make formats okay */
06726       chan2m->readformat = chan2->readformat;
06727       chan2m->writeformat = chan2->writeformat;
06728       ast_channel_masquerade(chan2m, chan2);
06729       /* Setup the extensions and such */
06730       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
06731       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
06732       chan2m->priority = chan2->priority;
06733       if (ast_do_masquerade(chan2m)) {
06734          ast_log(LOG_WARNING, "Masquerade failed :(\n");
06735          ast_hangup(chan2m);
06736          return -1;
06737       }
06738    } else {
06739       if (chan1m)
06740          ast_hangup(chan1m);
06741       if (chan2m)
06742          ast_hangup(chan2m);
06743       return -1;
06744    }
06745    if ((d = ast_calloc(1, sizeof(*d)))) {
06746       pthread_attr_t attr;
06747 
06748       pthread_attr_init(&attr);
06749       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06750 
06751       d->chan1 = chan1m;
06752       d->chan2 = chan2m;
06753       if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
06754          pthread_attr_destroy(&attr);
06755          return 0;
06756       }
06757       pthread_attr_destroy(&attr);
06758       free(d);
06759    }
06760    return -1;
06761 }

static void* iax_park_thread ( void *  stuff  )  [static]

Definition at line 6686 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().

06687 {
06688    struct ast_channel *chan1, *chan2;
06689    struct iax_dual *d;
06690    struct ast_frame *f;
06691    int ext;
06692    int res;
06693    d = stuff;
06694    chan1 = d->chan1;
06695    chan2 = d->chan2;
06696    free(d);
06697    f = ast_read(chan1);
06698    if (f)
06699       ast_frfree(f);
06700    res = ast_park_call(chan1, chan2, 0, &ext);
06701    ast_hangup(chan2);
06702    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06703    return NULL;
06704 }

static struct iax_frame* iaxfrdup2 ( struct iax_frame fr  )  [static]

Definition at line 1409 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().

01410 {
01411    struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable);
01412    if (new) {
01413       size_t afdatalen = new->afdatalen;
01414       memcpy(new, fr, sizeof(*new));
01415       iax_frame_wrap(new, &fr->af);
01416       new->afdatalen = afdatalen;
01417       new->data = NULL;
01418       new->datalen = 0;
01419       new->direction = DIRECTION_INGRESS;
01420       new->retrans = -1;
01421    }
01422    return new;
01423 }

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

Definition at line 891 of file chan_iax2.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, IAX_TYPE_DYNAMIC, and thread.

Referenced by iax2_process_thread().

00892 {
00893    if (thread->type == IAX_TYPE_DYNAMIC) {
00894       AST_LIST_LOCK(&dynamic_list);
00895       AST_LIST_INSERT_TAIL(&dynamic_list, thread, list);
00896       AST_LIST_UNLOCK(&dynamic_list);
00897    } else {
00898       AST_LIST_LOCK(&idle_list);
00899       AST_LIST_INSERT_TAIL(&idle_list, thread, list);
00900       AST_LIST_UNLOCK(&idle_list);
00901    }
00902 
00903    return;
00904 }

static void jb_debug_output ( const char *  fmt,
  ... 
) [static]

Definition at line 796 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

00797 {
00798    va_list args;
00799    char buf[1024];
00800 
00801    va_start(args, fmt);
00802    vsnprintf(buf, 1024, fmt, args);
00803    va_end(args);
00804 
00805    ast_verbose(buf);
00806 }

static void jb_error_output ( const char *  fmt,
  ... 
) [static]

Definition at line 772 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().

00773 {
00774    va_list args;
00775    char buf[1024];
00776 
00777    va_start(args, fmt);
00778    vsnprintf(buf, 1024, fmt, args);
00779    va_end(args);
00780 
00781    ast_log(LOG_ERROR, buf);
00782 }

static void jb_warning_output ( const char *  fmt,
  ... 
) [static]

Definition at line 784 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().

00785 {
00786    va_list args;
00787    char buf[1024];
00788 
00789    va_start(args, fmt);
00790    vsnprintf(buf, 1024, fmt, args);
00791    va_end(args);
00792 
00793    ast_log(LOG_WARNING, buf);
00794 }

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 11076 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, 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, netsock, option_verbose, outsock, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), peers, pvt_cmp_cb(), pvt_hash_cb(), reload_firmware(), sched, sched_context_create(), set_config(), start_network_thread(), user_cmp_cb(), user_hash_cb(), users, VERBOSE_PREFIX_2, and waresl.

11077 {
11078    char *config = "iax.conf";
11079    int res = 0;
11080    int x;
11081    struct iax2_registry *reg = NULL;
11082 
11083    peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
11084    if (!peers)
11085       return AST_MODULE_LOAD_FAILURE;
11086    users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
11087    if (!users) {
11088       ao2_ref(peers, -1);
11089       return AST_MODULE_LOAD_FAILURE;
11090    }
11091    iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb);
11092    if (!iax_peercallno_pvts) {
11093       ao2_ref(peers, -1);
11094       ao2_ref(users, -1);
11095       return AST_MODULE_LOAD_FAILURE;
11096    }
11097 
11098    ast_custom_function_register(&iaxpeer_function);
11099 
11100    iax_set_output(iax_debug_output);
11101    iax_set_error(iax_error_output);
11102    jb_setoutput(jb_error_output, jb_warning_output, NULL);
11103    
11104 #ifdef HAVE_ZAPTEL
11105 #ifdef ZT_TIMERACK
11106    timingfd = open("/dev/zap/timer", O_RDWR);
11107    if (timingfd < 0)
11108 #endif
11109       timingfd = open("/dev/zap/pseudo", O_RDWR);
11110    if (timingfd < 0) 
11111       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
11112 #endif      
11113 
11114    memset(iaxs, 0, sizeof(iaxs));
11115 
11116    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11117       ast_mutex_init(&iaxsl[x]);
11118    }
11119    
11120    ast_cond_init(&sched_cond, NULL);
11121 
11122    io = io_context_create();
11123    sched = sched_context_create();
11124    
11125    if (!io || !sched) {
11126       ast_log(LOG_ERROR, "Out of memory\n");
11127       return -1;
11128    }
11129 
11130    netsock = ast_netsock_list_alloc();
11131    if (!netsock) {
11132       ast_log(LOG_ERROR, "Could not allocate netsock list.\n");
11133       return -1;
11134    }
11135    ast_netsock_init(netsock);
11136 
11137    outsock = ast_netsock_list_alloc();
11138    if (!outsock) {
11139       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
11140       return -1;
11141    }
11142    ast_netsock_init(outsock);
11143 
11144    ast_mutex_init(&waresl.lock);
11145 
11146    AST_LIST_HEAD_INIT(&iaxq.queue);
11147    
11148    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
11149 
11150    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
11151    
11152    ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" );
11153    ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" );
11154 
11155    if(set_config(config, 0) == -1)
11156       return AST_MODULE_LOAD_DECLINE;
11157 
11158    if (ast_channel_register(&iax2_tech)) {
11159       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
11160       __unload_module();
11161       return -1;
11162    }
11163 
11164    if (ast_register_switch(&iax2_switch)) 
11165       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
11166 
11167    res = start_network_thread();
11168    if (!res) {
11169       if (option_verbose > 1) 
11170          ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n");
11171    } else {
11172       ast_log(LOG_ERROR, "Unable to start network thread\n");
11173       ast_netsock_release(netsock);
11174       ast_netsock_release(outsock);
11175    }
11176 
11177    AST_LIST_LOCK(&registrations);
11178    AST_LIST_TRAVERSE(&registrations, reg, entry)
11179       iax2_do_register(reg);
11180    AST_LIST_UNLOCK(&registrations); 
11181 
11182    ao2_callback(peers, 0, peer_set_sock_cb, NULL);
11183    ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
11184 
11185    reload_firmware(0);
11186    iax_provision_reload();
11187    return res;
11188 }

static void lock_both ( unsigned short  callno0,
unsigned short  callno1 
) [static]

Definition at line 3461 of file chan_iax2.c.

References ast_mutex_lock(), ast_mutex_trylock(), DEADLOCK_AVOIDANCE, and iaxsl.

Referenced by iax2_bridge().

03462 {
03463    ast_mutex_lock(&iaxsl[callno0]);
03464    while (ast_mutex_trylock(&iaxsl[callno1])) {
03465       DEADLOCK_AVOIDANCE(&iaxsl[callno0]);
03466    }
03467 }

static int make_trunk ( unsigned short  callno,
int  locked 
) [static]

Definition at line 1463 of file chan_iax2.c.

References ARRAY_LEN, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax2_sched_add(), iaxsl, LOG_DEBUG, LOG_WARNING, MIN_REUSE_TIME, option_debug, sched, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().

Referenced by iax2_request(), and socket_process().

01464 {
01465    int x;
01466    int res= 0;
01467    struct timeval now;
01468    if (iaxs[callno]->oseqno) {
01469       ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n");
01470       return -1;
01471    }
01472    if (callno & TRUNK_CALL_START) {
01473       ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno);
01474       return -1;
01475    }
01476    gettimeofday(&now, NULL);
01477    for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) {
01478       ast_mutex_lock(&iaxsl[x]);
01479       if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01480          iaxs[x] = iaxs[callno];
01481          iaxs[x]->callno = x;
01482          iaxs[callno] = NULL;
01483          /* Update the two timers that should have been started */
01484          AST_SCHED_DEL(sched, iaxs[x]->pingid);
01485          AST_SCHED_DEL(sched, iaxs[x]->lagid);
01486          iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01487          iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01488          if (locked)
01489             ast_mutex_unlock(&iaxsl[callno]);
01490          res = x;
01491          if (!locked)
01492             ast_mutex_unlock(&iaxsl[x]);
01493          break;
01494       }
01495       ast_mutex_unlock(&iaxsl[x]);
01496    }
01497    if (x >= ARRAY_LEN(iaxs) - 1) {
01498       ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n");
01499       return -1;
01500    }
01501    if (option_debug)
01502       ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x);
01503    /* We move this call from a non-trunked to a trunked call */
01504    update_max_trunk();
01505    update_max_nontrunk();
01506    return res;
01507 }

static int manager_iax2_show_netstats ( struct mansession s,
const struct message m 
) [static]

Definition at line 4700 of file chan_iax2.c.

References ast_cli_netstats(), astman_append(), RESULT_SUCCESS, and s.

Referenced by load_module().

04701 {
04702    ast_cli_netstats(s, -1, 0);
04703    astman_append(s, "\r\n");
04704    return RESULT_SUCCESS;
04705 }

static int manager_iax2_show_peers ( struct mansession s,
const struct message m 
) [static]

Definition at line 4733 of file chan_iax2.c.

References __iax2_show_peers(), ast_strlen_zero(), astman_append(), astman_get_header(), and s.

Referenced by load_module().

04734 {
04735    char *a[] = { "iax2", "show", "users" };
04736    int ret;
04737    const char *id = astman_get_header(m,"ActionID");
04738 
04739    if (!ast_strlen_zero(id))
04740       astman_append(s, "ActionID: %s\r\n",id);
04741    ret = __iax2_show_peers(1, -1, s, 3, a );
04742    astman_append(s, "\r\n\r\n" );
04743    return ret;
04744 } /* /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 1429 of file chan_iax2.c.

References chan_iax2_pvt::addr, chan_iax2_pvt::callno, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, 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().

01430 {
01431    if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01432       (cur->addr.sin_port == sin->sin_port)) {
01433       /* This is the main host */
01434       if ( (cur->peercallno == 0 || cur->peercallno == callno) &&
01435           (check_dcallno ? dcallno == cur->callno : 1) ) {
01436          /* That's us.  Be sure we keep track of the peer call number */
01437          return 1;
01438       }
01439    }
01440    if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01441        (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {
01442       /* We're transferring */
01443       if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno))
01444          return 1;
01445    }
01446    return 0;
01447 }

static void memcpy_decrypt ( unsigned char *  dst,
const unsigned char *  src,
int  len,
aes_decrypt_ctx dcx 
) [static]

Definition at line 4107 of file chan_iax2.c.

References aes_decrypt(), ast_log(), and LOG_WARNING.

Referenced by decode_frame().

04108 {
04109 #if 0
04110    /* Debug with "fake encryption" */
04111    int x;
04112    if (len % 16)
04113       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04114    for (x=0;x<len;x++)
04115       dst[x] = src[x] ^ 0xff;
04116 #else 
04117    unsigned char lastblock[16] = { 0 };
04118    int x;
04119    while(len > 0) {
04120       aes_decrypt(src, dst, dcx);
04121       for (x=0;x<16;x++)
04122          dst[x] ^= lastblock[x];
04123       memcpy(lastblock, src, sizeof(lastblock));
04124       dst += 16;
04125       src += 16;
04126       len -= 16;
04127    }
04128 #endif
04129 }

static void memcpy_encrypt ( unsigned char *  dst,
const unsigned char *  src,
int  len,
aes_encrypt_ctx ecx 
) [static]

Definition at line 4131 of file chan_iax2.c.

References aes_encrypt(), ast_log(), and LOG_WARNING.

Referenced by encrypt_frame().

04132 {
04133 #if 0
04134    /* Debug with "fake encryption" */
04135    int x;
04136    if (len % 16)
04137       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04138    for (x=0;x<len;x++)
04139       dst[x] = src[x] ^ 0xff;
04140 #else
04141    unsigned char curblock[16] = { 0 };
04142    int x;
04143    while(len > 0) {
04144       for (x=0;x<16;x++)
04145          curblock[x] ^= src[x];
04146       aes_encrypt(curblock, dst, ecx);
04147       memcpy(curblock, dst, sizeof(curblock)); 
04148       dst += 16;
04149       src += 16;
04150       len -= 16;
04151    }
04152 #endif
04153 }

static void merge_encryption ( struct chan_iax2_pvt p,
unsigned int  enc 
) [static]

Definition at line 5311 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05312 {
05313    /* Select exactly one common encryption if there are any */
05314    p->encmethods &= enc;
05315    if (p->encmethods) {
05316       if (p->encmethods & IAX_ENCRYPT_AES128)
05317          p->encmethods = IAX_ENCRYPT_AES128;
05318       else
05319          p->encmethods = 0;
05320    }
05321 }

static void* network_thread ( void *  ignore  )  [static]

Definition at line 9049 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(), f, iax2_sched_add(), iax_frame_free(), iaxq, iaxs, iaxsl, io, option_debug, sched, send_packet(), and timing_read().

Referenced by start_network_thread().

09050 {
09051    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
09052       from the network, and queue them for delivery to the channels */
09053    int res, count, wakeup;
09054    struct iax_frame *f;
09055 
09056    if (timingfd > -1)
09057       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
09058    
09059    for(;;) {
09060       pthread_testcancel();
09061 
09062       /* Go through the queue, sending messages which have not yet been
09063          sent, and scheduling retransmissions if appropriate */
09064       AST_LIST_LOCK(&iaxq.queue);
09065       count = 0;
09066       wakeup = -1;
09067       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
09068          if (f->sentyet)
09069             continue;
09070          
09071          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
09072          if (ast_mutex_trylock(&iaxsl[f->callno])) {
09073             wakeup = 1;
09074             continue;
09075          }
09076 
09077          f->sentyet++;
09078 
09079          if (iaxs[f->callno]) {
09080             send_packet(f);
09081             count++;
09082          } 
09083 
09084          ast_mutex_unlock(&iaxsl[f->callno]);
09085 
09086          if (f->retries < 0) {
09087             /* This is not supposed to be retransmitted */
09088             AST_LIST_REMOVE_CURRENT(&iaxq.queue, list);
09089             iaxq.count--;
09090             /* Free the iax frame */
09091             iax_frame_free(f);
09092          } else {
09093             /* We need reliable delivery.  Schedule a retransmission */
09094             f->retries++;
09095             f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
09096          }
09097       }
09098       AST_LIST_TRAVERSE_SAFE_END
09099       AST_LIST_UNLOCK(&iaxq.queue);
09100 
09101       pthread_testcancel();
09102 
09103       if (option_debug && count >= 20)
09104          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
09105 
09106       /* Now do the IO, and run scheduled tasks */
09107       res = ast_io_wait(io, wakeup);
09108       if (res >= 0) {
09109          if (option_debug && res >= 20)
09110             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
09111       }
09112    }
09113    return NULL;
09114 }

static struct chan_iax2_pvt* new_iax ( struct sockaddr_in *  sin,
const char *  host 
) [static]

Definition at line 1370 of file chan_iax2.c.

References ao2_alloc(), ao2_ref(), ast_string_field_init, ast_string_field_set, exten, jb_new(), jb_setconf(), jb_conf::max_contig_interp, jb_conf::max_jitterbuf, prefs, pvt_destructor(), and jb_conf::resync_threshold.

Referenced by __find_callno().

01371 {
01372    struct chan_iax2_pvt *tmp;
01373    jb_conf jbconf;
01374 
01375    if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) {
01376       return NULL;
01377    }
01378 
01379    if (ast_string_field_init(tmp, 32)) {
01380       ao2_ref(tmp, -1);
01381       tmp = NULL;
01382       return NULL;
01383    }
01384       
01385    tmp->prefs = prefs;
01386    tmp->callno = 0;
01387    tmp->peercallno = 0;
01388    tmp->transfercallno = 0;
01389    tmp->bridgecallno = 0;
01390    tmp->pingid = -1;
01391    tmp->lagid = -1;
01392    tmp->autoid = -1;
01393    tmp->authid = -1;
01394    tmp->initid = -1;
01395 
01396    ast_string_field_set(tmp,exten, "s");
01397    ast_string_field_set(tmp,host, host);
01398 
01399    tmp->jb = jb_new();
01400    tmp->jbid = -1;
01401    jbconf.max_jitterbuf = maxjitterbuffer;
01402    jbconf.resync_threshold = resyncthreshold;
01403    jbconf.max_contig_interp = maxjitterinterps;
01404    jb_setconf(tmp->jb,&jbconf);
01405 
01406    return tmp;
01407 }

static void parse_dial_string ( char *  data,
struct parsed_dial_string pds 
) [static]

Parses an IAX dial string into its component parts.

Parameters:
data the string to be parsed
pds pointer to a struct parsed_dial_string to be filled in
Returns:
nothing
This function parses the string and fills the structure with pointers to its component parts. The input string will be modified.

Note:
This function supports both plaintext passwords and RSA key names; if the password string is formatted as '[keyname]', then the keyname will be placed into the key field, and the password field will be set to NULL.

The dial string format is: [username[:password]@]peer[:port][/exten[@context]][/options]

Definition at line 3180 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().

03181 {
03182    if (ast_strlen_zero(data))
03183       return;
03184 
03185    pds->peer = strsep(&data, "/");
03186    pds->exten = strsep(&data, "/");
03187    pds->options = data;
03188 
03189    if (pds->exten) {
03190       data = pds->exten;
03191       pds->exten = strsep(&data, "@");
03192       pds->context = data;
03193    }
03194 
03195    if (strchr(pds->peer, '@')) {
03196       data = pds->peer;
03197       pds->username = strsep(&data, "@");
03198       pds->peer = data;
03199    }
03200 
03201    if (pds->username) {
03202       data = pds->username;
03203       pds->username = strsep(&data, ":");
03204       pds->password = data;
03205    }
03206 
03207    data = pds->peer;
03208    pds->peer = strsep(&data, ":");
03209    pds->port = data;
03210 
03211    /* check for a key name wrapped in [] in the secret position, if found,
03212       move it to the key field instead
03213    */
03214    if (pds->password && (pds->password[0] == '[')) {
03215       pds->key = ast_strip_quoted(pds->password, "[", "]");
03216       pds->password = NULL;
03217    }
03218 }

static int peer_cmp_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Note:
The only member of the peer passed here guaranteed to be set is the name field

Definition at line 1108 of file chan_iax2.c.

Referenced by load_module().

01109 {
01110    struct iax2_peer *peer = obj, *peer2 = arg;
01111 
01112    return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0;
01113 }

static int peer_delme_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 9747 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09748 {
09749    struct iax2_peer *peer = obj;
09750 
09751    ast_set_flag(peer, IAX_DELME);
09752 
09753    return 0;
09754 }

static void peer_destructor ( void *  obj  )  [static]

Definition at line 9272 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().

09273 {
09274    struct iax2_peer *peer = obj;
09275 
09276    ast_free_ha(peer->ha);
09277 
09278    if (peer->callno > 0) {
09279       ast_mutex_lock(&iaxsl[peer->callno]);
09280       iax2_destroy(peer->callno);
09281       ast_mutex_unlock(&iaxsl[peer->callno]);
09282    }
09283 
09284    register_peer_exten(peer, 0);
09285 
09286    if (peer->dnsmgr)
09287       ast_dnsmgr_release(peer->dnsmgr);
09288 
09289    ast_string_field_free_memory(peer);
09290 }

static int peer_hash_cb ( const void *  obj,
const int  flags 
) [static]

Note:
The only member of the peer passed here guaranteed to be set is the name field

Definition at line 1098 of file chan_iax2.c.

References ast_str_hash().

Referenced by load_module().

01099 {
01100    const struct iax2_peer *peer = obj;
01101 
01102    return ast_str_hash(peer->name);
01103 }

static struct iax2_peer* peer_ref ( struct iax2_peer peer  )  [static]

Definition at line 1155 of file chan_iax2.c.

References ao2_ref().

Referenced by __iax2_poke_noanswer(), iax2_poke_peer(), iax2_prune_realtime(), reg_source_db(), socket_process(), and update_registry().

01156 {
01157    ao2_ref(peer, +1);
01158    return peer;
01159 }

static int peer_set_sock_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 11047 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

11048 {
11049    struct iax2_peer *peer = obj;
11050 
11051    if (peer->sockfd < 0)
11052       peer->sockfd = defaultsockfd;
11053 
11054    return 0;
11055 }

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 9199 of file chan_iax2.c.

References ast_get_ip(), ast_log(), ast_netsock_bind(), ast_netsock_find(), ast_netsock_sockfd(), ast_netsock_unref(), ast_strdupa, check_srcaddr(), IAX_DEFAULT_PORTNO, io, LOG_WARNING, netsock, option_debug, outsock, socket_read(), iax2_peer::sockfd, and strsep().

Referenced by build_peer().

09200 {
09201    struct sockaddr_in sin;
09202    int nonlocal = 1;
09203    int port = IAX_DEFAULT_PORTNO;
09204    int sockfd = defaultsockfd;
09205    char *tmp;
09206    char *addr;
09207    char *portstr;
09208 
09209    if (!(tmp = ast_strdupa(srcaddr)))
09210       return -1;
09211 
09212    addr = strsep(&tmp, ":");
09213    portstr = tmp;
09214 
09215    if (portstr) {
09216       port = atoi(portstr);
09217       if (port < 1)
09218          port = IAX_DEFAULT_PORTNO;
09219    }
09220    
09221    if (!ast_get_ip(&sin, addr)) {
09222       struct ast_netsock *sock;
09223       int res;
09224 
09225       sin.sin_port = 0;
09226       sin.sin_family = AF_INET;
09227       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
09228       if (res == 0) {
09229          /* ip address valid. */
09230          sin.sin_port = htons(port);
09231          if (!(sock = ast_netsock_find(netsock, &sin)))
09232             sock = ast_netsock_find(outsock, &sin);
09233          if (sock) {
09234             sockfd = ast_netsock_sockfd(sock);
09235             nonlocal = 0;
09236          } else {
09237             unsigned int orig_saddr = sin.sin_addr.s_addr;
09238             /* INADDR_ANY matches anyway! */
09239             sin.sin_addr.s_addr = INADDR_ANY;
09240             if (ast_netsock_find(netsock, &sin)) {
09241                sin.sin_addr.s_addr = orig_saddr;
09242                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
09243                if (sock) {
09244                   sockfd = ast_netsock_sockfd(sock);
09245                   ast_netsock_unref(sock);
09246                   nonlocal = 0;
09247                } else {
09248                   nonlocal = 2;
09249                }
09250             }
09251          }
09252       }
09253    }
09254       
09255    peer->sockfd = sockfd;
09256 
09257    if (nonlocal == 1) {
09258       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
09259          srcaddr, peer->name);
09260       return -1;
09261         } else if (nonlocal == 2) {
09262       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
09263          srcaddr, peer->name);
09264          return -1;
09265    } else {
09266       if (option_debug)
09267          ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
09268       return 0;
09269    }
09270 }

static int peer_status ( struct iax2_peer peer,
char *  status,
int  statuslen 
) [static]

peer_status: Report Peer status in character string

Definition at line 2307 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().

02308 {
02309    int res = 0;
02310    if (peer->maxms) {
02311       if (peer->lastms < 0) {
02312          ast_copy_string(status, "UNREACHABLE", statuslen);
02313       } else if (peer->lastms > peer->maxms) {
02314          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02315          res = 1;
02316       } else if (peer->lastms) {
02317          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02318          res = 1;
02319       } else {
02320          ast_copy_string(status, "UNKNOWN", statuslen);
02321       }
02322    } else { 
02323       ast_copy_string(status, "Unmonitored", statuslen);
02324       res = -1;
02325    }
02326    return res;
02327 }

static struct iax2_peer* peer_unref ( struct iax2_peer peer  )  [inline, static]

Definition at line 1161 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(), reg_source_db(), registry_authrequest(), set_config(), socket_process(), unlink_peer(), and update_registry().

01162 {
01163    ao2_ref(peer, -1);
01164    return NULL;
01165 }

static void poke_all_peers ( void   )  [static]

Definition at line 10208 of file chan_iax2.c.

References ao2_iterator_init(), ao2_iterator_next(), iax2_poke_peer(), peer_unref(), and peers.

Referenced by reload_config().

10209 {
10210    struct ao2_iterator i;
10211    struct iax2_peer *peer;
10212 
10213    i = ao2_iterator_init(peers, 0);
10214    while ((peer = ao2_iterator_next(&i))) {
10215       iax2_poke_peer(peer, 0);
10216       peer_unref(peer);
10217    }
10218 }

static void prune_peers ( void   )  [static]

Definition at line 9805 of file chan_iax2.c.

References ao2_iterator_init(), ao2_iterator_next(), ast_test_flag, IAX_DELME, peer_unref(), peers, and unlink_peer().

09806 {
09807    struct iax2_peer *peer;
09808    struct ao2_iterator i;
09809 
09810    i = ao2_iterator_init(peers, 0);
09811    while ((peer = ao2_iterator_next(&i))) {
09812       if (ast_test_flag(peer, IAX_DELME))
09813          unlink_peer(peer);
09814       peer_unref(peer);
09815    }
09816 }

static void prune_users ( void   )  [static]

Definition at line 9791 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().

09792 {
09793    struct iax2_user *user;
09794    struct ao2_iterator i;
09795 
09796    i = ao2_iterator_init(users, 0);
09797    while ((user = ao2_iterator_next(&i))) {
09798       if (ast_test_flag(user, IAX_DELME))
09799          ao2_unlink(users, user);
09800       user_unref(user);
09801    }
09802 }

static int pvt_cmp_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 11064 of file chan_iax2.c.

References chan_iax2_pvt::frames_received, and match().

Referenced by load_module().

11065 {
11066    struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
11067 
11068    /* The frames_received field is used to hold whether we're matching
11069     * against a full frame or not ... */
11070 
11071    return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 
11072       pvt2->frames_received) ? CMP_MATCH : 0;
11073 }

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1331 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().

01332 {
01333    struct chan_iax2_pvt *pvt = obj;
01334    struct iax_frame *cur = NULL;
01335 
01336    iax2_destroy_helper(pvt);
01337 
01338    /* Already gone */
01339    ast_set_flag(pvt, IAX_ALREADYGONE); 
01340 
01341    AST_LIST_LOCK(&iaxq.queue);
01342    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
01343       /* Cancel any pending transmissions */
01344       if (cur->callno == pvt->callno) { 
01345          cur->retries = -1;
01346       }
01347    }
01348    AST_LIST_UNLOCK(&iaxq.queue);
01349 
01350    if (pvt->reg) {
01351       pvt->reg->callno = 0;
01352    }
01353 
01354    if (!pvt->owner) {
01355       jb_frame frame;
01356       if (pvt->vars) {
01357           ast_variables_destroy(pvt->vars);
01358           pvt->vars = NULL;
01359       }
01360 
01361       while (jb_getall(pvt->jb, &frame) == JB_OK) {
01362          iax2_frame_free(frame.data);
01363       }
01364 
01365       jb_destroy(pvt->jb);
01366       ast_string_field_free_memory(pvt);
01367    }
01368 }

static int pvt_hash_cb ( const void *  obj,
const int  flags 
) [static]

Definition at line 11057 of file chan_iax2.c.

References chan_iax2_pvt::peercallno.

Referenced by load_module().

11058 {
11059    const struct chan_iax2_pvt *pvt = obj;
11060 
11061    return pvt->peercallno;
11062 }

static int raw_hangup ( struct sockaddr_in *  sin,
unsigned short  src,
unsigned short  dst,
int  sockfd 
) [static]

Definition at line 5293 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, 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().

05294 {
05295    struct ast_iax2_full_hdr fh;
05296    fh.scallno = htons(src | IAX_FLAG_FULL);
05297    fh.dcallno = htons(dst);
05298    fh.ts = 0;
05299    fh.oseqno = 0;
05300    fh.iseqno = 0;
05301    fh.type = AST_FRAME_IAX;
05302    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
05303    if (iaxdebug)
05304        iax_showframe(NULL, &fh, 0, sin, 0);
05305    if (option_debug)
05306       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
05307          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
05308    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
05309 }

static struct iax2_peer * realtime_peer ( const char *  peername,
struct sockaddr_in *  sin 
) [static]

Note:
This function calls reg_source_db -> iax2_poke_peer -> find_callno, so do not call this with a pvt lock held.

Note:
If this one loaded something, then we need to ensure that the host field matched. The only reason why we can't have this as a criteria is because we only have the IP address and the host field might be set as a name (and the reverse PTR might not match).

Definition at line 2782 of file chan_iax2.c.

References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), hp, ast_variable::name, ast_variable::next, ast_variable::value, and var.

02783 {
02784    struct ast_variable *var = NULL;
02785    struct ast_variable *tmp;
02786    struct iax2_peer *peer=NULL;
02787    time_t regseconds = 0, nowtime;
02788    int dynamic=0;
02789 
02790    if (peername) {
02791       var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", NULL);
02792       if (!var && sin)
02793          var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), NULL);
02794    } else if (sin) {
02795       char porta[25];
02796       sprintf(porta, "%d", ntohs(sin->sin_port));
02797       var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02798       if (var) {
02799          /* We'll need the peer name in order to build the structure! */
02800          for (tmp = var; tmp; tmp = tmp->next) {
02801             if (!strcasecmp(tmp->name, "name"))
02802                peername = tmp->value;
02803          }
02804       }
02805    }
02806    if (!var && peername) { /* Last ditch effort */
02807       var = ast_load_realtime("iaxpeers", "name", peername, NULL);
02808       /*!\note
02809        * If this one loaded something, then we need to ensure that the host
02810        * field matched.  The only reason why we can't have this as a criteria
02811        * is because we only have the IP address and the host field might be
02812        * set as a name (and the reverse PTR might not match).
02813        */
02814       if (var && sin) {
02815          for (tmp = var; tmp; tmp = tmp->next) {
02816             if (!strcasecmp(tmp->name, "host")) {
02817                struct ast_hostent ahp;
02818                struct hostent *hp;
02819                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
02820                   /* No match */
02821                   ast_variables_destroy(var);
02822                   var = NULL;
02823                }
02824                break;
02825             }
02826          }
02827       }
02828    }
02829    if (!var)
02830       return NULL;
02831 
02832    peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
02833    
02834    if (!peer) {
02835       ast_variables_destroy(var);
02836       return NULL;
02837    }
02838 
02839    for (tmp = var; tmp; tmp = tmp->next) {
02840       /* Make sure it's not a user only... */
02841       if (!strcasecmp(tmp->name, "type")) {
02842          if (strcasecmp(tmp->value, "friend") &&
02843              strcasecmp(tmp->value, "peer")) {
02844             /* Whoops, we weren't supposed to exist! */
02845             peer = peer_unref(peer);
02846             break;
02847          } 
02848       } else if (!strcasecmp(tmp->name, "regseconds")) {
02849          ast_get_time_t(tmp->value, &regseconds, 0, NULL);
02850       } else if (!strcasecmp(tmp->name, "ipaddr")) {
02851          inet_aton(tmp->value, &(peer->addr.sin_addr));
02852       } else if (!strcasecmp(tmp->name, "port")) {
02853          peer->addr.sin_port = htons(atoi(tmp->value));
02854       } else if (!strcasecmp(tmp->name, "host")) {
02855          if (!strcasecmp(tmp->value, "dynamic"))
02856             dynamic = 1;
02857       }
02858    }
02859 
02860    ast_variables_destroy(var);
02861 
02862    if (!peer)
02863       return NULL;
02864 
02865    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02866       ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
02867       if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
02868          if (peer->expire > -1) {
02869             if (!ast_sched_del(sched, peer->expire)) {
02870                peer->expire = -1;
02871                peer_unref(peer);
02872             }
02873          }
02874          peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer));
02875          if (peer->expire == -1)
02876             peer_unref(peer);
02877       }
02878       ao2_link(peers, peer);
02879       if (ast_test_flag(peer, IAX_DYNAMIC))
02880          reg_source_db(peer);
02881    } else {
02882       ast_set_flag(peer, IAX_TEMPONLY);   
02883    }
02884 
02885    if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) {
02886       time(&nowtime);
02887       if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) {
02888          memset(&peer->addr, 0, sizeof(peer->addr));
02889          realtime_update_peer(peer->name, &peer->addr, 0);
02890          if (option_debug)
02891             ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n",
02892                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02893       }
02894       else {
02895          if (option_debug)
02896             ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n",
02897                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02898       }
02899    }
02900 
02901    return peer;
02902 }

static void realtime_update_peer ( const char *  peername,
struct sockaddr_in *  sin,
time_t  regtime 
) [static]

Definition at line 2975 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

Referenced by __expire_registry(), update_peer(), and update_registry().

02976 {
02977    char port[10];
02978    char regseconds[20];
02979    
02980    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
02981    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
02982    ast_update_realtime("iaxpeers", "name", peername, 
02983       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
02984       "regseconds", regseconds, NULL);
02985 }

static struct iax2_user* realtime_user ( const char *  username,
struct sockaddr_in *  sin 
) [static]

Definition at line 2904 of file chan_iax2.c.

References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), hp, ast_variable::name, ast_variable::next, ast_variable::value, and var.

02905 {
02906    struct ast_variable *var;
02907    struct ast_variable *tmp;
02908    struct iax2_user *user=NULL;
02909 
02910    var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL);
02911    if (!var)
02912       var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), NULL);
02913    if (!var && sin) {
02914       char porta[6];
02915       snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port));
02916       var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02917       if (!var)
02918          var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02919    }
02920    if (!var) { /* Last ditch effort */
02921       var = ast_load_realtime("iaxusers", "name", username, NULL);
02922       /*!\note
02923        * If this one loaded something, then we need to ensure that the host
02924        * field matched.  The only reason why we can't have this as a criteria
02925        * is because we only have the IP address and the host field might be
02926        * set as a name (and the reverse PTR might not match).
02927        */
02928       if (var) {
02929          for (tmp = var; tmp; tmp = tmp->next) {
02930             if (!strcasecmp(tmp->name, "host")) {
02931                struct ast_hostent ahp;
02932                struct hostent *hp;
02933                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
02934                   /* No match */
02935                   ast_variables_destroy(var);
02936                   var = NULL;
02937                }
02938                break;
02939             }
02940          }
02941       }
02942    }
02943    if (!var)
02944       return NULL;
02945 
02946    tmp = var;
02947    while(tmp) {
02948       /* Make sure it's not a peer only... */
02949       if (!strcasecmp(tmp->name, "type")) {
02950          if (strcasecmp(tmp->value, "friend") &&
02951              strcasecmp(tmp->value, "user")) {
02952             return NULL;
02953          } 
02954       }
02955       tmp = tmp->next;
02956    }
02957 
02958    user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
02959 
02960    ast_variables_destroy(var);
02961 
02962    if (!user)
02963       return NULL;
02964 
02965    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02966       ast_set_flag(user, IAX_RTCACHEFRIENDS);
02967       ao2_link(users, user);
02968    } else {
02969       ast_set_flag(user, IAX_TEMPONLY);   
02970    }
02971 
02972    return user;
02973 }

static void reg_source_db ( struct iax2_peer p  )  [static]

Definition at line 6074 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(), sched, and VERBOSE_PREFIX_3.

Referenced by build_peer(), set_config(), and temp_peer().

06075 {
06076    char data[80];
06077    struct in_addr in;
06078    char *c, *d;
06079    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
06080       c = strchr(data, ':');
06081       if (c) {
06082          *c = '\0';
06083          c++;
06084          if (inet_aton(data, &in)) {
06085             d = strchr(c, ':');
06086             if (d) {
06087                *d = '\0';
06088                d++;
06089                if (option_verbose > 2)
06090                   ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 
06091                   ast_inet_ntoa(in), atoi(c), atoi(d));
06092                iax2_poke_peer(p, 0);
06093                p->expiry = atoi(d);
06094                memset(&p->addr, 0, sizeof(p->addr));
06095                p->addr.sin_family = AF_INET;
06096                p->addr.sin_addr = in;
06097                p->addr.sin_port = htons(atoi(c));
06098                if (p->expire > -1) {
06099                   if (!ast_sched_del(sched, p->expire)) {
06100                      p->expire = -1;
06101                      peer_unref(p);
06102                   }
06103                }
06104                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06105                p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
06106                if (p->expire == -1)
06107                   peer_unref(p);
06108                if (iax2_regfunk)
06109                   iax2_regfunk(p->name, 1);
06110                register_peer_exten(p, 1);
06111             }              
06112                
06113          }
06114       }
06115    }
06116 }

static void register_peer_exten ( struct iax2_peer peer,
int  onoff 
) [static]

Definition at line 5994 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().

05995 {
05996    char multi[256];
05997    char *stringp, *ext;
05998    if (!ast_strlen_zero(regcontext)) {
05999       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
06000       stringp = multi;
06001       while((ext = strsep(&stringp, "&"))) {
06002          if (onoff) {
06003             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
06004                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
06005                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
06006          } else
06007             ast_context_remove_extension(regcontext, ext, 1, NULL);
06008       }
06009    }
06010 }

static int register_verify ( int  callno,
struct sockaddr_in *  sin,
struct iax_ies ies 
) [static]

Verify inbound registration.

Definition at line 5457 of file chan_iax2.c.

References iax2_peer::addr, ast_apply_ha(), ast_check_signature, ast_clear_flag, 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, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, IAX_STATE_UNCHANGED, iaxs, iaxsl, ies, inaddrcmp(), LOG_NOTICE, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), secret, and strsep().

Referenced by handle_request_register(), and socket_process().

05458 {
05459    char requeststr[256] = "";
05460    char peer[256] = "";
05461    char md5secret[256] = "";
05462    char rsasecret[256] = "";
05463    char secret[256] = "";
05464    struct iax2_peer *p = NULL;
05465    struct ast_key *key;
05466    char *keyn;
05467    int x;
05468    int expire = 0;
05469    int res = -1;
05470 
05471    ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED);
05472    /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
05473    if (ies->username)
05474       ast_copy_string(peer, ies->username, sizeof(peer));
05475    if (ies->password)
05476       ast_copy_string(secret, ies->password, sizeof(secret));
05477    if (ies->md5_result)
05478       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05479    if (ies->rsa_result)
05480       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05481    if (ies->refresh)
05482       expire = ies->refresh;
05483 
05484    if (ast_strlen_zero(peer)) {
05485       ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr));
05486       return -1;
05487    }
05488 
05489    /* SLD: first call to lookup peer during registration */
05490    ast_mutex_unlock(&iaxsl[callno]);
05491    p = find_peer(peer, 1);
05492    ast_mutex_lock(&iaxsl[callno]);
05493    if (!p || !iaxs[callno]) {
05494       if (authdebug && !p)
05495          ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05496       goto return_unref;
05497    }
05498 
05499    if (!ast_test_flag(p, IAX_DYNAMIC)) {
05500       if (authdebug)
05501          ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05502       goto return_unref;
05503    }
05504 
05505    if (!ast_apply_ha(p->ha, sin)) {
05506       if (authdebug)
05507          ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05508       goto return_unref;
05509    }
05510    if (!inaddrcmp(&p->addr, sin))
05511       ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED);
05512    ast_string_field_set(iaxs[callno], secret, p->secret);
05513    ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
05514    /* Check secret against what we have on file */
05515    if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05516       if (!ast_strlen_zero(p->inkeys)) {
05517          char tmpkeys[256];
05518          char *stringp=NULL;
05519          ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys));
05520          stringp=tmpkeys;
05521          keyn = strsep(&stringp, ":");
05522          while(keyn) {
05523             key = ast_key_get(keyn, AST_KEY_PUBLIC);
05524             if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
05525                ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05526                break;
05527             } else if (!key) 
05528                ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
05529             keyn = strsep(&stringp, ":");
05530          }
05531          if (!keyn) {
05532             if (authdebug)
05533                ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
05534             goto return_unref;
05535          }
05536       } else {
05537          if (authdebug)
05538             ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
05539          goto return_unref;
05540       }
05541    } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05542       struct MD5Context md5;
05543       unsigned char digest[16];
05544       char *tmppw, *stringp;
05545       
05546       tmppw = ast_strdupa(p->secret);
05547       stringp = tmppw;
05548       while((tmppw = strsep(&stringp, ";"))) {
05549          MD5Init(&md5);
05550          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
05551          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05552          MD5Final(digest, &md5);
05553          for (x=0;x<16;x++)
05554             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05555          if (!strcasecmp(requeststr, md5secret)) 
05556             break;
05557       }
05558       if (tmppw) {
05559          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05560       } else {
05561          if (authdebug)
05562             ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret);
05563          goto return_unref;
05564       }
05565    } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
05566       /* They've provided a plain text password and we support that */
05567       if (strcmp(secret, p->secret)) {
05568          if (authdebug)
05569             ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05570          goto return_unref;
05571       } else
05572          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05573    } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) {
05574       if (authdebug)
05575          ast_log(LOG_NOTICE, "Inappropriate authentication received\n");
05576       goto return_unref;
05577    }
05578    ast_string_field_set(iaxs[callno], peer, peer);
05579    /* Choose lowest expiry number */
05580    if (expire && (expire < iaxs[callno]->expiry)) 
05581       iaxs[callno]->expiry = expire;
05582 
05583    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05584 
05585    res = 0;
05586 
05587 return_unref:
05588    if (p)
05589       peer_unref(p);
05590 
05591    return res;
05592 }

static int registry_authrequest ( int  callno  )  [static]

Definition at line 6253 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, 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(), and send_command().

Referenced by socket_process().

06254 {
06255    struct iax_ie_data ied;
06256    struct iax2_peer *p;
06257    char challenge[10];
06258    const char *peer_name;
06259    int res = -1;
06260 
06261    peer_name = ast_strdupa(iaxs[callno]->peer);
06262 
06263    /* SLD: third call to find_peer in registration */
06264    ast_mutex_unlock(&iaxsl[callno]);
06265    p = find_peer(peer_name, 1);
06266    ast_mutex_lock(&iaxsl[callno]);
06267    if (!iaxs[callno])
06268       goto return_unref;
06269    if (!p) {
06270       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
06271       goto return_unref;
06272    }
06273    
06274    memset(&ied, 0, sizeof(ied));
06275    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
06276    if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06277       /* Build the challenge */
06278       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06279       ast_string_field_set(iaxs[callno], challenge, challenge);
06280       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06281    }
06282    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06283 
06284    res = 0;
06285 
06286 return_unref:
06287    peer_unref(p);
06288 
06289    return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
06290 }

static int registry_rerequest ( struct iax_ies ies,
int  callno,
struct sockaddr_in *  sin 
) [static]

Definition at line 6292 of file chan_iax2.c.

References iax2_registry::addr, AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), authenticate(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, ies, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_AUTHSENT, iax2_registry::regstate, iax2_registry::secret, send_command(), and iax2_registry::username.

Referenced by socket_process().

06293 {
06294    struct iax2_registry *reg;
06295    /* Start pessimistic */
06296    struct iax_ie_data ied;
06297    char peer[256] = "";
06298    char challenge[256] = "";
06299    int res;
06300    int authmethods = 0;
06301    if (ies->authmethods)
06302       authmethods = ies->authmethods;
06303    if (ies->username)
06304       ast_copy_string(peer, ies->username, sizeof(peer));
06305    if (ies->challenge)
06306       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
06307    memset(&ied, 0, sizeof(ied));
06308    reg = iaxs[callno]->reg;
06309    if (reg) {
06310          if (inaddrcmp(&reg->addr, sin)) {
06311             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
06312             return -1;
06313          }
06314          if (ast_strlen_zero(reg->secret)) {
06315             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
06316             reg->regstate = REG_STATE_NOAUTH;
06317             return -1;
06318          }
06319          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
06320          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
06321          if (reg->secret[0] == '[') {
06322             char tmpkey[256];
06323             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
06324             tmpkey[strlen(tmpkey) - 1] = '\0';
06325             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL);
06326          } else
06327             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL);
06328          if (!res) {
06329             reg->regstate = REG_STATE_AUTHSENT;
06330             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
06331          } else
06332             return -1;
06333          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
06334    } else   
06335       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
06336    return -1;
06337 }

static char* regstate2str ( int  regstate  )  [static]

Definition at line 4746 of file chan_iax2.c.

References REG_STATE_AUTHSENT, 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().

04747 {
04748    switch(regstate) {
04749    case REG_STATE_UNREGISTERED:
04750       return "Unregistered";
04751    case REG_STATE_REGSENT:
04752       return "Request Sent";
04753    case REG_STATE_AUTHSENT:
04754       return "Auth. Sent";
04755    case REG_STATE_REGISTERED:
04756       return "Registered";
04757    case REG_STATE_REJECTED:
04758       return "Rejected";
04759    case REG_STATE_TIMEOUT:
04760       return "Timeout";
04761    case REG_STATE_NOAUTH:
04762       return "No Authentication";
04763    default:
04764       return "Unknown";
04765    }
04766 }

static int reload ( void   )  [static]

Definition at line 10245 of file chan_iax2.c.

References reload_config().

10246 {
10247    return reload_config();
10248 }

static int reload_config ( void   )  [static]

Definition at line 10219 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().

10220 {
10221    char *config = "iax.conf";
10222    struct iax2_registry *reg;
10223 
10224    if (set_config(config, 1) > 0) {
10225       prune_peers();
10226       prune_users();
10227       AST_LIST_LOCK(&registrations);
10228       AST_LIST_TRAVERSE(&registrations, reg, entry)
10229          iax2_do_register(reg);
10230       AST_LIST_UNLOCK(&registrations);
10231       /* Qualify hosts, too */
10232       poke_all_peers();
10233    }
10234    reload_firmware(0);
10235    iax_provision_reload();
10236 
10237    return 0;
10238 }

static void reload_firmware ( int  unload  )  [static]

Definition at line 1951 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().

01952 {
01953    struct iax_firmware *cur, *curl, *curp;
01954    DIR *fwd;
01955    struct dirent *de;
01956    char dir[256];
01957    char fn[256];
01958    /* Mark all as dead */
01959    ast_mutex_lock(&waresl.lock);
01960    cur = waresl.wares;
01961    while(cur) {
01962       cur->dead = 1;
01963       cur = cur->next;
01964    }
01965 
01966    /* Now that we've freed them, load the new ones */
01967    if (!unload) {
01968       snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
01969       fwd = opendir(dir);
01970       if (fwd) {
01971          while((de = readdir(fwd))) {
01972             if (de->d_name[0] != '.') {
01973                snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name);
01974                if (!try_firmware(fn)) {
01975                   if (option_verbose > 1)
01976                      ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name);
01977                }
01978             }
01979          }
01980          closedir(fwd);
01981       } else 
01982          ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
01983    }
01984 
01985    /* Clean up leftovers */
01986    cur = waresl.wares;
01987    curp = NULL;
01988    while(cur) {
01989       curl = cur;
01990       cur = cur->next;
01991       if (curl->dead) {
01992          if (curp) {
01993             curp->next = cur;
01994          } else {
01995             waresl.wares = cur;
01996          }
01997          destroy_firmware(curl);
01998       } else {
01999          curp = cur;
02000       }
02001    }
02002    ast_mutex_unlock(&waresl.lock);
02003 }

static void remove_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1246 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().

01247 {
01248    if (!pvt->peercallno) {
01249       ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
01250       return;
01251    }
01252 
01253    ao2_unlink(iax_peercallno_pvts, pvt);
01254 }

static void save_rr ( struct iax_frame fr,
struct iax_ies ies 
) [static]

Definition at line 6796 of file chan_iax2.c.

References iax_frame::callno, iax_rr::delay, iax_rr::dropped, iaxs, ies, iax_rr::jitter, iax_rr::losscnt, iax_rr::losspct, iax_rr::ooo, iax_rr::packets, and chan_iax2_pvt::remote_rr.

Referenced by socket_process().

06797 {
06798    iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter;
06799    iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24;
06800    iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff;
06801    iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts;
06802    iaxs[fr->callno]->remote_rr.delay = ies->rr_delay;
06803    iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped;
06804    iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo;
06805 }

static void* sched_thread ( void *  ignore  )  [static]

Definition at line 9021 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(), option_debug, and sched.

Referenced by start_network_thread().

09022 {
09023    int count;
09024    int res;
09025    struct timeval tv;
09026    struct timespec ts;
09027 
09028    for (;;) {
09029       res = ast_sched_wait(sched);
09030       if ((res > 1000) || (res < 0))
09031          res = 1000;
09032       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
09033       ts.tv_sec = tv.tv_sec;
09034       ts.tv_nsec = tv.tv_usec * 1000;
09035 
09036       pthread_testcancel();
09037       ast_mutex_lock(&sched_lock);
09038       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
09039       ast_mutex_unlock(&sched_lock);
09040       pthread_testcancel();
09041 
09042       count = ast_sched_runq(sched);
09043       if (option_debug && count >= 20)
09044          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
09045    }
09046    return NULL;
09047 }

static int schedule_delivery ( struct iax_frame fr,
int  updatehistory,
int  fromtrunk,
unsigned int *  tsout 
) [static]

Note:
This function assumes fr->callno is locked

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 2635 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, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, len, LOG_DEBUG, option_debug, ast_channel_tech::properties, sched, ast_channel::tech, iax_frame::ts, type, unwrap_timestamp(), and update_jbsched().

Referenced by socket_process().

02636 {
02637    int type, len;
02638    int ret;
02639    int needfree = 0;
02640    struct ast_channel *owner = NULL;
02641    struct ast_channel *bridge = NULL;
02642    
02643    /* Attempt to recover wrapped timestamps */
02644    unwrap_timestamp(fr);
02645 
02646    /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
02647    if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore))
02648       fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000));
02649    else {
02650 #if 0
02651       if (option_debug)
02652          ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n");
02653 #endif
02654       fr->af.delivery = ast_tv(0,0);
02655    }
02656 
02657    type = JB_TYPE_CONTROL;
02658    len = 0;
02659 
02660    if(fr->af.frametype == AST_FRAME_VOICE) {
02661       type = JB_TYPE_VOICE;
02662       len = ast_codec_get_samples(&fr->af) / 8;
02663    } else if(fr->af.frametype == AST_FRAME_CNG) {
02664       type = JB_TYPE_SILENCE;
02665    }
02666 
02667    if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
02668       if (tsout)
02669          *tsout = fr->ts;
02670       __do_deliver(fr);
02671       return -1;
02672    }
02673 
02674    if ((owner = iaxs[fr->callno]->owner))
02675       bridge = ast_bridged_channel(owner);
02676 
02677    /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
02678     * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
02679    if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) {
02680       jb_frame frame;
02681 
02682       /* deliver any frames in the jb */
02683       while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
02684          __do_deliver(frame.data);
02685          /* __do_deliver() can make the call disappear */
02686          if (!iaxs[fr->callno])
02687             return -1;
02688       }
02689 
02690       jb_reset(iaxs[fr->callno]->jb);
02691 
02692       AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid);
02693 
02694       /* deliver this frame now */
02695       if (tsout)
02696          *tsout = fr->ts;
02697       __do_deliver(fr);
02698       return -1;
02699    }
02700 
02701    /* insert into jitterbuffer */
02702    /* TODO: Perhaps we could act immediately if it's not droppable and late */
02703    ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
02704          calc_rxstamp(iaxs[fr->callno],fr->ts));
02705    if (ret == JB_DROP) {
02706       needfree++;
02707    } else if (ret == JB_SCHED) {
02708       update_jbsched(iaxs[fr->callno]);
02709    }
02710    if (tsout)
02711       *tsout = fr->ts;
02712    if (needfree) {
02713       /* Free our iax frame */
02714       iax2_frame_free(fr);
02715       return -1;
02716    }
02717    return 0;
02718 }

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 3153 of file chan_iax2.c.

References AST_FRAME_IAX, compress_subclass(), and f.

Referenced by socket_process().

03154 {
03155    struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno),
03156       .ts = htonl(ts), .iseqno = seqno, .oseqno = seqno, .type = AST_FRAME_IAX,
03157       .csub = compress_subclass(command) };
03158 
03159    return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin));
03160 }

static int send_command ( struct chan_iax2_pvt ,
char  ,
int  ,
unsigned  int,
const unsigned char *  ,
int  ,
int   
) [static]

Definition at line 5030 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().

05031 {
05032    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
05033 }

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]

Note:
Since this function calls iax2_predestroy() -> iax2_queue_hangup(), the pvt struct for the given call number may disappear during its execution.

Definition at line 5049 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().

05050 {
05051    int call_num = i->callno;
05052    /* It is assumed that the callno has already been locked */
05053    iax2_predestroy(i->callno);
05054    if (!iaxs[call_num])
05055       return -1;
05056    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
05057 }

static int send_command_immediate ( struct chan_iax2_pvt ,
char  ,
int  ,
unsigned  int,
const unsigned char *  ,
int  ,
int   
) [static]

Definition at line 5059 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

05060 {
05061    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
05062 }

static int send_command_locked ( unsigned short  callno,
char  ,
int  ,
unsigned  int,
const unsigned char *  ,
int  ,
int   
) [static]

Definition at line 5035 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().

05036 {
05037    int res;
05038    ast_mutex_lock(&iaxsl[callno]);
05039    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
05040    ast_mutex_unlock(&iaxsl[callno]);
05041    return res;
05042 }

static int send_command_transfer ( struct chan_iax2_pvt ,
char  ,
int  ,
unsigned  int,
const unsigned char *  ,
int   
) [static]

Definition at line 5064 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

05065 {
05066    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
05067 }

static int send_lagrq ( const void *  data  )  [static]

Definition at line 1052 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

Referenced by __find_callno(), __send_lagrq(), and make_trunk().

01053 {
01054 #ifdef SCHED_MULTITHREADED
01055    if (schedule_action(__send_lagrq, data))
01056 #endif      
01057       __send_lagrq(data);
01058    return 0;
01059 }

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 2076 of file chan_iax2.c.

References chan_iax2_pvt::addr, ast_inet_ntoa(), ast_log(), errno, error(), f, handle_error(), iax_showframe(), iaxs, LOG_DEBUG, option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, and transfer.

Referenced by __attempt_transmit(), iax2_send(), network_thread(), and vnak_retransmit().

02077 {
02078    int res;
02079    int callno = f->callno;
02080 
02081    /* Don't send if there was an error, but return error instead */
02082    if (!callno || !iaxs[callno] || iaxs[callno]->error)
02083        return -1;
02084    
02085    /* Called with iaxsl held */
02086    if (option_debug > 2 && iaxdebug)
02087       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));
02088    if (f->transfer) {
02089       if (iaxdebug)
02090          iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
02091       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer,
02092                sizeof(iaxs[callno]->transfer));
02093    } else {
02094       if (iaxdebug)
02095          iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
02096       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr,
02097                sizeof(iaxs[callno]->addr));
02098    }
02099    if (res < 0) {
02100       if (option_debug && iaxdebug)
02101          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
02102       handle_error();
02103    } else
02104       res = 0;
02105    return res;
02106 }

static int send_ping ( const void *  data  )  [static]

Definition at line 1012 of file chan_iax2.c.

References __send_ping(), and schedule_action.

Referenced by __find_callno(), __send_ping(), and make_trunk().

01013 {
01014 #ifdef SCHED_MULTITHREADED
01015    if (schedule_action(__send_ping, data))
01016 #endif      
01017       __send_ping(data);
01018    return 0;
01019 }

static int send_trunk ( struct iax2_trunk_peer tpeer,
struct timeval *  now 
) [static]

Definition at line 6474 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, globalflags, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_TRUNKTIMESTAMPS, 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().

06475 {
06476    int res = 0;
06477    struct iax_frame *fr;
06478    struct ast_iax2_meta_hdr *meta;
06479    struct ast_iax2_meta_trunk_hdr *mth;
06480    int calls = 0;
06481    
06482    /* Point to frame */
06483    fr = (struct iax_frame *)tpeer->trunkdata;
06484    /* Point to meta data */
06485    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
06486    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
06487    if (tpeer->trunkdatalen) {
06488       /* We're actually sending a frame, so fill the meta trunk header and meta header */
06489       meta->zeros = 0;
06490       meta->metacmd = IAX_META_TRUNK;
06491       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
06492          meta->cmddata = IAX_META_TRUNK_MINI;
06493       else
06494          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
06495       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
06496       /* And the rest of the ast_iax2 header */
06497       fr->direction = DIRECTION_OUTGRESS;
06498       fr->retrans = -1;
06499       fr->transfer = 0;
06500       /* Any appropriate call will do */
06501       fr->data = fr->afdata;
06502       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
06503       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
06504       calls = tpeer->calls;
06505 #if 0
06506       if (option_debug)
06507          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));
06508 #endif      
06509       /* Reset transmit trunk side data */
06510       tpeer->trunkdatalen = 0;
06511       tpeer->calls = 0;
06512    }
06513    if (res < 0)
06514       return res;
06515    return calls;
06516 }

static int set_config ( char *  config_file,
int  reload 
) [static]

Load configuration.

Definition at line 9849 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(), globalflags, 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, io, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MAX_PEER_BUCKETS, ast_variable::name, netsock, ast_variable::next, option_verbose, outsock, peer_unref(), peers, portno, prefs, reg_source_db(), 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().

09850 {
09851    struct ast_config *cfg, *ucfg;
09852    int capability=iax2_capability;
09853    struct ast_variable *v;
09854    char *cat;
09855    const char *utype;
09856    const char *tosval;
09857    int format;
09858    int portno = IAX_DEFAULT_PORTNO;
09859    int  x;
09860    struct iax2_user *user;
09861    struct iax2_peer *peer;
09862    struct ast_netsock *ns;
09863 #if 0
09864    static unsigned short int last_port=0;
09865 #endif
09866 
09867    cfg = ast_config_load(config_file);
09868    
09869    if (!cfg) {
09870       ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
09871       return -1;
09872    }
09873 
09874    if (reload) {
09875       set_config_destroy();
09876    }
09877 
09878    /* Reset global codec prefs */   
09879    memset(&prefs, 0 , sizeof(struct ast_codec_pref));
09880    
09881    /* Reset Global Flags */
09882    memset(&globalflags, 0, sizeof(globalflags));
09883    ast_set_flag(&globalflags, IAX_RTUPDATE);
09884 
09885 #ifdef SO_NO_CHECK
09886    nochecksums = 0;
09887 #endif
09888 
09889    min_reg_expire = IAX_DEFAULT_REG_EXPIRE;
09890    max_reg_expire = IAX_DEFAULT_REG_EXPIRE;
09891 
09892    maxauthreq = 3;
09893 
09894    v = ast_variable_browse(cfg, "general");
09895 
09896    /* Seed initial tos value */
09897    tosval = ast_variable_retrieve(cfg, "general", "tos");
09898    if (tosval) {
09899       if (ast_str2tos(tosval, &tos))
09900          ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n");
09901    }
09902    while(v) {
09903       if (!strcasecmp(v->name, "bindport")){ 
09904          if (reload)
09905             ast_log(LOG_NOTICE, "Ignoring bindport on reload\n");
09906          else
09907             portno = atoi(v->value);
09908       } else if (!strcasecmp(v->name, "pingtime")) 
09909          ping_time = atoi(v->value);
09910       else if (!strcasecmp(v->name, "iaxthreadcount")) {
09911          if (reload) {
09912             if (atoi(v->value) != iaxthreadcount)
09913                ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n");
09914          } else {
09915             iaxthreadcount = atoi(v->value);
09916             if (iaxthreadcount < 1) {
09917                ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n");
09918                iaxthreadcount = 1;
09919             } else if (iaxthreadcount > 256) {
09920                ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n");
09921                iaxthreadcount = 256;
09922             }
09923          }
09924       } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) {
09925          if (reload) {
09926             AST_LIST_LOCK(&dynamic_list);
09927             iaxmaxthreadcount = atoi(v->value);
09928             AST_LIST_UNLOCK(&dynamic_list);
09929          } else {
09930             iaxmaxthreadcount = atoi(v->value);
09931             if (iaxmaxthreadcount < 0) {
09932                ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n");
09933                iaxmaxthreadcount = 0;
09934             } else if (iaxmaxthreadcount > 256) {
09935                ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n");
09936                iaxmaxthreadcount = 256;
09937             }
09938          }
09939       } else if (!strcasecmp(v->name, "nochecksums")) {
09940 #ifdef SO_NO_CHECK
09941          if (ast_true(v->value))
09942             nochecksums = 1;
09943          else
09944             nochecksums = 0;
09945 #else
09946          if (ast_true(v->value))
09947             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
09948 #endif
09949       }
09950       else if (!strcasecmp(v->name, "maxjitterbuffer")) 
09951          maxjitterbuffer = atoi(v->value);
09952       else if (!strcasecmp(v->name, "resyncthreshold")) 
09953          resyncthreshold = atoi(v->value);
09954       else if (!strcasecmp(v->name, "maxjitterinterps")) 
09955          maxjitterinterps = atoi(v->value);
09956       else if (!strcasecmp(v->name, "lagrqtime")) 
09957          lagrq_time = atoi(v->value);
09958       else if (!strcasecmp(v->name, "maxregexpire")) 
09959          max_reg_expire = atoi(v->value);
09960       else if (!strcasecmp(v->name, "minregexpire")) 
09961          min_reg_expire = atoi(v->value);
09962       else if (!strcasecmp(v->name, "bindaddr")) {
09963          if (reload) {
09964             ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n");
09965          } else {
09966             if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) {
09967                ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno);
09968             } else {
09969                if (option_verbose > 1) {
09970                   if (strchr(v->value, ':'))
09971                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value);
09972                   else
09973                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno);
09974                }
09975                if (defaultsockfd < 0) 
09976                   defaultsockfd = ast_netsock_sockfd(ns);
09977                ast_netsock_unref(ns);
09978             }
09979          }
09980       } else if (!strcasecmp(v->name, "authdebug"))
09981          authdebug = ast_true(v->value);
09982       else if (!strcasecmp(v->name, "encryption"))
09983          iax2_encryption = get_encrypt_methods(v->value);
09984       else if (!strcasecmp(v->name, "notransfer")) {
09985          ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09986          ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09987          ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER);   
09988       } else if (!strcasecmp(v->name, "transfer")) {
09989          if (!strcasecmp(v->value, "mediaonly")) {
09990             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 
09991          } else if (ast_true(v->value)) {
09992             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09993          } else 
09994             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09995       } else if (!strcasecmp(v->name, "codecpriority")) {
09996          if(!strcasecmp(v->value, "caller"))
09997             ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST);
09998          else if(!strcasecmp(v->value, "disabled"))
09999             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
10000          else if(!strcasecmp(v->value, "reqonly")) {
10001             ast_set_flag((&globalflags), IAX_CODEC_NOCAP);
10002             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
10003          }
10004       } else if (!strcasecmp(v->name, "jitterbuffer"))
10005          ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 
10006       else if (!strcasecmp(v->name, "forcejitterbuffer"))
10007          ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);  
10008       else if (!strcasecmp(v->name, "delayreject"))
10009          delayreject = ast_true(v->value);
10010       else if (!strcasecmp(v->name, "allowfwdownload"))
10011          ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD);
10012       else if (!strcasecmp(v->name, "rtcachefriends"))
10013          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS);  
10014       else if (!strcasecmp(v->name, "rtignoreregexpire"))
10015          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE);  
10016       else if (!strcasecmp(v->name, "rtupdate"))
10017          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE);
10018       else if (!strcasecmp(v->name, "trunktimestamps"))
10019          ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS);
10020       else if (!strcasecmp(v->name, "rtautoclear")) {
10021          int i = atoi(v->value);
10022          if(i > 0)
10023             global_rtautoclear = i;
10024          else
10025             i = 0;
10026          ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR);   
10027       } else if (!strcasecmp(v->name, "trunkfreq")) {
10028          trunkfreq = atoi(v->value);
10029          if (trunkfreq < 10)
10030             trunkfreq = 10;
10031       } else if (!strcasecmp(v->name, "autokill")) {
10032          if (sscanf(v->value, "%d", &x) == 1) {
10033             if (x >= 0)
10034                autokill = x;
10035             else
10036                ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
10037          } else if (ast_true(v->value)) {
10038             autokill = DEFAULT_MAXMS;
10039          } else {
10040             autokill = 0;
10041          }
10042       } else if (!strcasecmp(v->name, "bandwidth")) {
10043          if (!strcasecmp(v->value, "low")) {
10044             capability = IAX_CAPABILITY_LOWBANDWIDTH;
10045          } else if (!strcasecmp(v->value, "medium")) {
10046             capability = IAX_CAPABILITY_MEDBANDWIDTH;
10047          } else if (!strcasecmp(v->value, "high")) {
10048             capability = IAX_CAPABILITY_FULLBANDWIDTH;
10049          } else
10050             ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n");
10051       } else if (!strcasecmp(v->name, "allow")) {
10052          ast_parse_allow_disallow(&prefs, &capability, v->value, 1);
10053       } else if (!strcasecmp(v->name, "disallow")) {
10054          ast_parse_allow_disallow(&prefs, &capability, v->value, 0);
10055       } else if (!strcasecmp(v->name, "register")) {
10056          iax2_register(v->value, v->lineno);
10057       } else if (!strcasecmp(v->name, "iaxcompat")) {
10058          iaxcompat = ast_true(v->value);
10059       } else if (!strcasecmp(v->name, "regcontext")) {
10060          ast_copy_string(regcontext, v->value, sizeof(regcontext));
10061          /* Create context if it doesn't exist already */
10062          if (!ast_context_find(regcontext))
10063             ast_context_create(NULL, regcontext, "IAX2");
10064       } else if (!strcasecmp(v->name, "tos")) {
10065          if (ast_str2tos(v->value, &tos))
10066             ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno);
10067       } else if (!strcasecmp(v->name, "accountcode")) {
10068          ast_copy_string(accountcode, v->value, sizeof(accountcode));
10069       } else if (!strcasecmp(v->name, "mohinterpret")) {
10070          ast_copy_string(mohinterpret, v->value, sizeof(user->mohinterpret));
10071       } else if (!strcasecmp(v->name, "mohsuggest")) {
10072          ast_copy_string(mohsuggest, v->value, sizeof(user->mohsuggest));
10073       } else if (!strcasecmp(v->name, "amaflags")) {
10074          format = ast_cdr_amaflags2int(v->value);
10075          if (format < 0) {
10076             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
10077          } else {
10078             amaflags = format;
10079          }
10080       } else if (!strcasecmp(v->name, "language")) {
10081          ast_copy_string(language, v->value, sizeof(language));
10082       } else if (!strcasecmp(v->name, "maxauthreq")) {
10083          maxauthreq = atoi(v->value);
10084          if (maxauthreq < 0)
10085             maxauthreq = 0;
10086       } else if (!strcasecmp(v->name, "adsi")) {
10087          adsi = ast_true(v->value);
10088       } /*else if (strcasecmp(v->name,"type")) */
10089       /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
10090       v = v->next;
10091    }
10092    
10093    if (defaultsockfd < 0) {
10094       if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) {
10095          ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
10096       } else {
10097          if (option_verbose > 1)
10098             ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno);
10099          defaultsockfd = ast_netsock_sockfd(ns);
10100          ast_netsock_unref(ns);
10101       }
10102    }
10103    if (reload) {
10104       ast_netsock_release(outsock);
10105       outsock = ast_netsock_list_alloc();
10106       if (!outsock) {
10107          ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
10108          return -1;
10109       }
10110       ast_netsock_init(outsock);
10111    }
10112 
10113    if (min_reg_expire > max_reg_expire) {
10114       ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n",
10115          min_reg_expire, max_reg_expire, max_reg_expire);
10116       min_reg_expire = max_reg_expire;
10117    }
10118    iax2_capability = capability;
10119    
10120    ucfg = ast_config_load("users.conf");
10121    if (ucfg) {
10122       struct ast_variable *gen;
10123       int genhasiax;
10124       int genregisteriax;
10125       const char *hasiax, *registeriax;
10126       
10127       genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax"));
10128       genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax"));
10129       gen = ast_variable_browse(ucfg, "general");
10130       cat = ast_category_browse(ucfg, NULL);
10131       while (cat) {
10132          if (strcasecmp(cat, "general")) {
10133             hasiax = ast_variable_retrieve(ucfg, cat, "hasiax");
10134             registeriax = ast_variable_retrieve(ucfg, cat, "registeriax");
10135             if (ast_true(hasiax) || (!hasiax && genhasiax)) {
10136                /* Start with general parameters, then specific parameters, user and peer */
10137                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
10138                if (user) {
10139                   __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10140                   user = user_unref(user);
10141                }
10142                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
10143                if (peer) {
10144                   if (ast_test_flag(peer, IAX_DYNAMIC))
10145                      reg_source_db(peer);
10146                   __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10147                   peer = peer_unref(peer);
10148                }
10149             }
10150             if (ast_true(registeriax) || (!registeriax && genregisteriax)) {
10151                char tmp[256];
10152                const char *host = ast_variable_retrieve(ucfg, cat, "host");
10153                const char *username = ast_variable_retrieve(ucfg, cat, "username");
10154                const char *secret = ast_variable_retrieve(ucfg, cat, "secret");
10155                if (!host)
10156                   host = ast_variable_retrieve(ucfg, "general", "host");
10157                if (!username)
10158                   username = ast_variable_retrieve(ucfg, "general", "username");
10159                if (!secret)
10160                   secret = ast_variable_retrieve(ucfg, "general", "secret");
10161                if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
10162                   if (!ast_strlen_zero(secret))
10163                      snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host);
10164                   else
10165                      snprintf(tmp, sizeof(tmp), "%s@%s", username, host);
10166                   iax2_register(tmp, 0);
10167                }
10168             }
10169          }
10170          cat = ast_category_browse(ucfg, cat);
10171       }
10172       ast_config_destroy(ucfg);
10173    }
10174    
10175    cat = ast_category_browse(cfg, NULL);
10176    while(cat) {
10177       if (strcasecmp(cat, "general")) {
10178          utype = ast_variable_retrieve(cfg, cat, "type");
10179          if (utype) {
10180             if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
10181                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
10182                if (user) {
10183                   __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10184                   user = user_unref(user);
10185                }
10186             }
10187             if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
10188                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
10189                if (peer) {
10190                   if (ast_test_flag(peer, IAX_DYNAMIC))
10191                      reg_source_db(peer);
10192                   __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10193                   peer = peer_unref(peer);
10194                }
10195             } else if (strcasecmp(utype, "user")) {
10196                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file);
10197             }
10198          } else
10199             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
10200       }
10201       cat = ast_category_browse(cfg, cat);
10202    }
10203    ast_config_destroy(cfg);
10204    set_timing();
10205    return 1;
10206 }

static void set_config_destroy ( void   )  [static]

Definition at line 9833 of file chan_iax2.c.

References ast_clear_flag, delete_users(), globalflags, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, and IAX_USEJITTERBUF.

Referenced by set_config().

09834 {
09835    strcpy(accountcode, "");
09836    strcpy(language, "");
09837    strcpy(mohinterpret, "default");
09838    strcpy(mohsuggest, "");
09839    amaflags = 0;
09840    delayreject = 0;
09841    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09842    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09843    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09844    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09845    delete_users();
09846 }

static void set_timing ( void   )  [static]

Definition at line 9818 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09819 {
09820 #ifdef HAVE_ZAPTEL
09821    int bs = trunkfreq * 8;
09822    if (timingfd > -1) {
09823       if (
09824 #ifdef ZT_TIMERACK
09825          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09826 #endif         
09827          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09828          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09829    }
09830 #endif
09831 }

static void signal_condition ( ast_mutex_t lock,
ast_cond_t cond 
) [static]

Definition at line 754 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().

00755 {
00756    ast_mutex_lock(lock);
00757    ast_cond_signal(cond);
00758    ast_mutex_unlock(lock);
00759 }

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 6948 of file chan_iax2.c.

References 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(), iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, calc_timestamp(), iax2_peer::callno, iax2_dpcache::callno, iax_frame::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, check_access(), check_provisioning(), cid_num, complete_dpreply(), complete_transfer(), construct_rr(), ast_channel::context, DEADLOCK_AVOIDANCE, decrypt_frame(), dp_lookup(), EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, f, iax_frame::final, find_callno(), find_callno_locked(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, format, chan_iax2_pvt::frames_received, ast_frame::frametype, globalflags, 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, iaxfrdup2(), iaxq, iaxs, iaxsl, ies, inaddrcmp(), chan_iax2_pvt::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_iax2_meta_trunk_mini::len, len, iax2_trunk_peer::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_trunk(), manager_event(), iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, NEW_ALLOW, NEW_PREVENT, option_debug, option_verbose, iax_frame::oseqno, pbx_builtin_setvar_helper(), iax2_dpcache::peer, peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, raw_hangup(), REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), remove_by_peercallno(), iax_frame::retries, chan_iax2_pvt::rseqno, iax2_trunk_peer::rxtrunktime, S_OR, save_rr(), sched, schedule_delivery(), send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax2_peer::smoothing, spawn_dp_lookup(), stop_stuff(), store_by_peercallno(), thread, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, iax2_trunk_peer::trunkact, try_transfer(), iax_frame::ts, ast_iax2_mini_hdr::ts, uncompress_subclass(), update_registry(), 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().

06949 {
06950    struct sockaddr_in sin;
06951    int res;
06952    int updatehistory=1;
06953    int new = NEW_PREVENT;
06954    void *ptr;
06955    int dcallno = 0;
06956    struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf;
06957    struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf;
06958    struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf;
06959    struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf;
06960    struct ast_iax2_meta_trunk_hdr *mth;
06961    struct ast_iax2_meta_trunk_entry *mte;
06962    struct ast_iax2_meta_trunk_mini *mtm;
06963    struct iax_frame *fr;
06964    struct iax_frame *cur;
06965    struct ast_frame f = { 0, };
06966    struct ast_channel *c;
06967    struct iax2_dpcache *dp;
06968    struct iax2_peer *peer;
06969    struct iax2_trunk_peer *tpeer;
06970    struct timeval rxtrunktime;
06971    struct iax_ies ies;
06972    struct iax_ie_data ied0, ied1;
06973    int format;
06974    int fd;
06975    int exists;
06976    int minivid = 0;
06977    unsigned int ts;
06978    char empty[32]="";      /* Safety measure */
06979    struct iax_frame *duped_fr;
06980    char host_pref_buf[128];
06981    char caller_pref_buf[128];
06982    struct ast_codec_pref pref;
06983    char *using_prefs = "mine";
06984 
06985    /* allocate an iax_frame with 4096 bytes of data buffer */
06986    fr = alloca(sizeof(*fr) + 4096);
06987    memset(fr, 0, sizeof(*fr));
06988    fr->afdatalen = 4096; /* From alloca() above */
06989 
06990    /* Copy frequently used parameters to the stack */
06991    res = thread->buf_len;
06992    fd = thread->iofd;
06993    memcpy(&sin, &thread->iosin, sizeof(sin));
06994 
06995    if (res < sizeof(*mh)) {
06996       ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*mh));
06997       return 1;
06998    }
06999    if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) {
07000       if (res < sizeof(*vh)) {
07001          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));
07002          return 1;
07003       }
07004 
07005       /* This is a video frame, get call number */
07006       fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd, 0);
07007       minivid = 1;
07008    } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) {
07009       unsigned char metatype;
07010 
07011       if (res < sizeof(*meta)) {
07012          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));
07013          return 1;
07014       }
07015 
07016       /* This is a meta header */
07017       switch(meta->metacmd) {
07018       case IAX_META_TRUNK:
07019          if (res < (sizeof(*meta) + sizeof(*mth))) {
07020             ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %zd min)\n", res,
07021                sizeof(*meta) + sizeof(*mth));
07022             return 1;
07023          }
07024          mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data);
07025          ts = ntohl(mth->ts);
07026          metatype = meta->cmddata;
07027          res -= (sizeof(*meta) + sizeof(*mth));
07028          ptr = mth->data;
07029          tpeer = find_tpeer(&sin, fd);
07030          if (!tpeer) {
07031             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));
07032             return 1;
07033          }
07034          tpeer->trunkact = ast_tvnow();
07035          if (!ts || ast_tvzero(tpeer->rxtrunktime))
07036             tpeer->rxtrunktime = tpeer->trunkact;
07037          rxtrunktime = tpeer->rxtrunktime;
07038          ast_mutex_unlock(&tpeer->lock);
07039          while(res >= sizeof(*mte)) {
07040             /* Process channels */
07041             unsigned short callno, trunked_ts, len;
07042 
07043             if (metatype == IAX_META_TRUNK_MINI) {
07044                mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
07045                ptr += sizeof(*mtm);
07046                res -= sizeof(*mtm);
07047                len = ntohs(mtm->len);
07048                callno = ntohs(mtm->mini.callno);
07049                trunked_ts = ntohs(mtm->mini.ts);
07050             } else if (metatype == IAX_META_TRUNK_SUPERMINI) {
07051                mte = (struct ast_iax2_meta_trunk_entry *)ptr;
07052                ptr += sizeof(*mte);
07053                res -= sizeof(*mte);
07054                len = ntohs(mte->len);
07055                callno = ntohs(mte->callno);
07056                trunked_ts = 0;
07057             } else {
07058                ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
07059                break;
07060             }
07061             /* Stop if we don't have enough data */
07062             if (len > res)
07063                break;
07064             fr->callno = find_callno_locked(callno & ~IAX_FLAG_FULL, 0, &sin, NEW_PREVENT, fd, 0);
07065             if (fr->callno) {
07066                /* If it's a valid call, deliver the contents.  If not, we
07067                   drop it, since we don't have a scallno to use for an INVAL */
07068                /* Process as a mini frame */
07069                memset(&f, 0, sizeof(f));
07070                f.frametype = AST_FRAME_VOICE;
07071                if (iaxs[fr->callno]) {
07072                   if (iaxs[fr->callno]->voiceformat > 0) {
07073                      f.subclass = iaxs[fr->callno]->voiceformat;
07074                      f.datalen = len;
07075                      if (f.datalen >= 0) {
07076                         if (f.datalen)
07077                            f.data = ptr;
07078                         if(trunked_ts) {
07079                            fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff);
07080                         } else
07081                            fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts);
07082                         /* Don't pass any packets until we're started */
07083                         if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
07084                            /* Common things */
07085                            f.src = "IAX2";
07086                            if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 
07087                               f.samples = ast_codec_get_samples(&f);
07088                            iax_frame_wrap(fr, &f);
07089                            duped_fr = iaxfrdup2(fr);
07090                            if (duped_fr) {
07091                               schedule_delivery(duped_fr, updatehistory, 1, &fr->ts);
07092                            }
07093                            /* It is possible for the pvt structure to go away after we call schedule_delivery */
07094                            if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) {
07095                               iaxs[fr->callno]->last = fr->ts;
07096 #if 1
07097                               if (option_debug && iaxdebug)
07098                                  ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts);
07099 #endif
07100                            }
07101                         }
07102                      } else {
07103                         ast_log(LOG_WARNING, "Datalen < 0?\n");
07104                      }
07105                   } else {
07106                      ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n ");
07107                      iax2_vnak(fr->callno);
07108                   }
07109                }
07110                ast_mutex_unlock(&iaxsl[fr->callno]);
07111             }
07112             ptr += len;
07113             res -= len;
07114          }
07115          
07116       }
07117       return 1;
07118    }
07119 
07120 #ifdef DEBUG_SUPPORT
07121    if (iaxdebug && (res >= sizeof(*fh)))
07122       iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh));
07123 #endif
07124    if (ntohs(mh->callno) & IAX_FLAG_FULL) {
07125       if (res < sizeof(*fh)) {
07126          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));
07127          return 1;
07128       }
07129 
07130       /* Get the destination call number */
07131       dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS;
07132       /* Retrieve the type and subclass */
07133       f.frametype = fh->type;
07134       if (f.frametype == AST_FRAME_VIDEO) {
07135          f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
07136       } else {
07137          f.subclass = uncompress_subclass(fh->csub);
07138       }
07139 
07140       /* Deal with POKE/PONG without allocating a callno */
07141       if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_POKE) {
07142          /* Reply back with a PONG, but don't care about the result. */
07143          send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_PONG, ntohs(fh->ts), fh->oseqno);
07144          return 1;
07145       } else if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK && dcallno == 1) {
07146          /* Ignore */
07147          return 1;
07148       }
07149 
07150       if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) ||
07151                          (f.subclass == IAX_COMMAND_POKE) || (f.subclass == IAX_COMMAND_FWDOWNL) ||
07152                          (f.subclass == IAX_COMMAND_REGREL)))
07153          new = NEW_ALLOW;
07154    } else {
07155       /* Don't know anything about it yet */
07156       f.frametype = AST_FRAME_NULL;
07157       f.subclass = 0;
07158    }
07159 
07160    if (!fr->callno) {
07161       int check_dcallno = 0;
07162 
07163       /*
07164        * We enforce accurate destination call numbers for all full frames except
07165        * LAGRQ and PING commands.  This is because older versions of Asterisk
07166        * schedule these commands to get sent very quickly, and they will sometimes
07167        * be sent before they receive the first frame from the other side.  When
07168        * that happens, it doesn't contain the destination call number.  However,
07169        * not checking it for these frames is safe.
07170        * 
07171        * Discussed in the following thread:
07172        *    http://lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html 
07173        */
07174 
07175       if (ntohs(mh->callno) & IAX_FLAG_FULL) {
07176          check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1;
07177       }
07178 
07179       fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno);
07180    }
07181 
07182    if (fr->callno > 0)
07183       ast_mutex_lock(&iaxsl[fr->callno]);
07184 
07185    if (!fr->callno || !iaxs[fr->callno]) {
07186       /* A call arrived for a nonexistent destination.  Unless it's an "inval"
07187          frame, reply with an inval */
07188       if (ntohs(mh->callno) & IAX_FLAG_FULL) {
07189          /* We can only raw hangup control frames */
07190          if (((f.subclass != IAX_COMMAND_INVAL) &&
07191              (f.subclass != IAX_COMMAND_TXCNT) &&
07192              (f.subclass != IAX_COMMAND_TXACC) &&
07193              (f.subclass != IAX_COMMAND_FWDOWNL))||
07194              (f.frametype != AST_FRAME_IAX))
07195             raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL,
07196             fd);
07197       }
07198       if (fr->callno > 0) 
07199          ast_mutex_unlock(&iaxsl[fr->callno]);
07200       return 1;
07201    }
07202    if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) {
07203       if (decrypt_frame(fr->callno, fh, &f, &res)) {
07204          ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n");
07205          ast_mutex_unlock(&iaxsl[fr->callno]);
07206          return 1;
07207       }
07208 #ifdef DEBUG_SUPPORT
07209       else if (iaxdebug)
07210          iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh));
07211 #endif
07212    }
07213 
07214    /* count this frame */
07215    iaxs[fr->callno]->frames_received++;
07216 
07217    if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid &&
07218       f.subclass != IAX_COMMAND_TXCNT &&     /* for attended transfer */
07219       f.subclass != IAX_COMMAND_TXACC) {     /* for attended transfer */
07220       unsigned short new_peercallno;
07221 
07222       new_peercallno = (unsigned short) (ntohs(mh->callno) & ~IAX_FLAG_FULL);
07223       if (new_peercallno && new_peercallno != iaxs[fr->callno]->peercallno) {
07224          if (iaxs[fr->callno]->peercallno) {
07225             remove_by_peercallno(iaxs[fr->callno]);
07226          }
07227          iaxs[fr->callno]->peercallno = new_peercallno;
07228          store_by_peercallno(iaxs[fr->callno]);
07229       }
07230    }
07231    if (ntohs(mh->callno) & IAX_FLAG_FULL) {
07232       if (option_debug  && iaxdebug)
07233          ast_log(LOG_DEBUG, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass);
07234       /* Check if it's out of order (and not an ACK or INVAL) */
07235       fr->oseqno = fh->oseqno;
07236       fr->iseqno = fh->iseqno;
07237       fr->ts = ntohl(fh->ts);
07238 #ifdef IAXTESTS
07239       if (test_resync) {
07240          if (option_debug)
07241             ast_log(LOG_DEBUG, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync);
07242          fr->ts += test_resync;
07243       }
07244 #endif /* IAXTESTS */
07245 #if 0
07246       if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) ||
07247            ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX &&
07248                         (f.subclass == IAX_COMMAND_NEW ||
07249                          f.subclass == IAX_COMMAND_AUTHREQ ||
07250                          f.subclass == IAX_COMMAND_ACCEPT ||
07251                          f.subclass == IAX_COMMAND_REJECT))      ) )
07252 #endif
07253       if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE))
07254          updatehistory = 0;
07255       if ((iaxs[fr->callno]->iseqno != fr->oseqno) &&
07256          (iaxs[fr->callno]->iseqno ||
07257             ((f.subclass != IAX_COMMAND_TXCNT) &&
07258             (f.subclass != IAX_COMMAND_TXREADY) &&    /* for attended transfer */
07259             (f.subclass != IAX_COMMAND_TXREL) &&      /* for attended transfer */
07260             (f.subclass != IAX_COMMAND_UNQUELCH ) &&  /* for attended transfer */
07261             (f.subclass != IAX_COMMAND_TXACC)) ||
07262             (f.frametype != AST_FRAME_IAX))) {
07263          if (
07264           ((f.subclass != IAX_COMMAND_ACK) &&
07265            (f.subclass != IAX_COMMAND_INVAL) &&
07266            (f.subclass != IAX_COMMAND_TXCNT) &&
07267            (f.subclass != IAX_COMMAND_TXREADY) &&     /* for attended transfer */
07268            (f.subclass != IAX_COMMAND_TXREL) &&    /* for attended transfer */
07269            (f.subclass != IAX_COMMAND_UNQUELCH ) &&   /* for attended transfer */
07270            (f.subclass != IAX_COMMAND_TXACC) &&
07271            (f.subclass != IAX_COMMAND_VNAK)) ||
07272            (f.frametype != AST_FRAME_IAX)) {
07273             /* If it's not an ACK packet, it's out of order. */
07274             if (option_debug)
07275                ast_log(LOG_DEBUG, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 
07276                   iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass);
07277             /* Check to see if we need to request retransmission,
07278              * and take sequence number wraparound into account */
07279             if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) {
07280                /* If we've already seen it, ack it XXX There's a border condition here XXX */
07281                if ((f.frametype != AST_FRAME_IAX) || 
07282                      ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) {
07283                   if (option_debug)
07284                      ast_log(LOG_DEBUG, "Acking anyway\n");
07285                   /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if
07286                      we have anything to send, we'll retransmit and get an ACK back anyway XXX */
07287                   send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07288                }
07289             } else {
07290                /* Send a VNAK requesting retransmission */
07291                iax2_vnak(fr->callno);
07292             }
07293             ast_mutex_unlock(&iaxsl[fr->callno]);
07294             return 1;
07295          }
07296       } else {
07297          /* Increment unless it's an ACK or VNAK */
07298          if (((f.subclass != IAX_COMMAND_ACK) &&
07299              (f.subclass != IAX_COMMAND_INVAL) &&
07300              (f.subclass != IAX_COMMAND_TXCNT) &&
07301              (f.subclass != IAX_COMMAND_TXACC) &&
07302             (f.subclass != IAX_COMMAND_VNAK)) ||
07303              (f.frametype != AST_FRAME_IAX))
07304             iaxs[fr->callno]->iseqno++;
07305       }
07306       /* A full frame */
07307       if (res < sizeof(*fh)) {
07308          ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*fh));
07309          ast_mutex_unlock(&iaxsl[fr->callno]);
07310          return 1;
07311       }
07312       /* Ensure text frames are NULL-terminated */
07313       if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') {
07314          if (res < thread->buf_size)
07315             thread->buf[res++] = '\0';
07316          else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */
07317             thread->buf[res - 1] = '\0';
07318       }
07319       f.datalen = res - sizeof(*fh);
07320 
07321       /* Handle implicit ACKing unless this is an INVAL, and only if this is 
07322          from the real peer, not the transfer peer */
07323       if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 
07324           ((f.subclass != IAX_COMMAND_INVAL) ||
07325            (f.frametype != AST_FRAME_IAX))) {
07326          unsigned char x;
07327          int call_to_destroy;
07328          /* XXX This code is not very efficient.  Surely there is a better way which still
07329                 properly handles boundary conditions? XXX */
07330          /* First we have to qualify that the ACKed value is within our window */
07331          for (x=iaxs[fr->callno]->rseqno; x != iaxs[fr->callno]->oseqno; x++)
07332             if (fr->iseqno == x)
07333                break;
07334          if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) {
07335             /* The acknowledgement is within our window.  Time to acknowledge everything
07336                that it says to */
07337             for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) {
07338                /* Ack the packet with the given timestamp */
07339                if (option_debug && iaxdebug)
07340                   ast_log(LOG_DEBUG, "Cancelling transmission of packet %d\n", x);
07341                call_to_destroy = 0;
07342                AST_LIST_LOCK(&iaxq.queue);
07343                AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
07344                   /* If it's our call, and our timestamp, mark -1 retries */
07345                   if ((fr->callno == cur->callno) && (x == cur->oseqno)) {
07346                      cur->retries = -1;
07347                      /* Destroy call if this is the end */
07348                      if (cur->final)
07349                         call_to_destroy = fr->callno;
07350                   }
07351                }
07352                AST_LIST_UNLOCK(&iaxq.queue);
07353                if (call_to_destroy) {
07354                   if (iaxdebug && option_debug)
07355                      ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", call_to_destroy);
07356                   ast_mutex_lock(&iaxsl[call_to_destroy]);
07357                   iax2_destroy(call_to_destroy);
07358                   ast_mutex_unlock(&iaxsl[call_to_destroy]);
07359                }
07360             }
07361             /* Note how much we've received acknowledgement for */
07362             if (iaxs[fr->callno])
07363                iaxs[fr->callno]->rseqno = fr->iseqno;
07364             else {
07365                /* Stop processing now */
07366                ast_mutex_unlock(&iaxsl[fr->callno]);
07367                return 1;
07368             }
07369          } else if (option_debug)
07370             ast_log(LOG_DEBUG, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno);
07371       }
07372       if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 
07373          ((f.frametype != AST_FRAME_IAX) || 
07374           ((f.subclass != IAX_COMMAND_TXACC) &&
07375            (f.subclass != IAX_COMMAND_TXCNT)))) {
07376          /* Only messages we accept from a transfer host are TXACC and TXCNT */
07377          ast_mutex_unlock(&iaxsl[fr->callno]);
07378          return 1;
07379       }
07380 
07381       if (f.datalen) {
07382          if (f.frametype == AST_FRAME_IAX) {
07383             if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) {
07384                ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr));
07385                ast_mutex_unlock(&iaxsl[fr->callno]);
07386                return 1;
07387             }
07388             f.data = NULL;
07389             f.datalen = 0;
07390          } else
07391             f.data = thread->buf + sizeof(*fh);
07392       } else {
07393          if (f.frametype == AST_FRAME_IAX)
07394             f.data = NULL;
07395          else
07396             f.data = empty;
07397          memset(&ies, 0, sizeof(ies));
07398       }
07399 
07400       /* when we receive the first full frame for a new incoming channel,
07401          it is safe to start the PBX on the channel because we have now
07402          completed a 3-way handshake with the peer */
07403       if ((f.frametype == AST_FRAME_VOICE) ||
07404           (f.frametype == AST_FRAME_VIDEO) ||
07405           (f.frametype == AST_FRAME_IAX)) {
07406          if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) {
07407             ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART);
07408             if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) {
07409                ast_mutex_unlock(&iaxsl[fr->callno]);
07410                return 1;
07411             }
07412          }
07413       }
07414 
07415       if (f.frametype == AST_FRAME_VOICE) {
07416          if (f.subclass != iaxs[fr->callno]->voiceformat) {
07417                iaxs[fr->callno]->voiceformat = f.subclass;
07418                if (option_debug)
07419                   ast_log(LOG_DEBUG, "Ooh, voice format changed to %d\n", f.subclass);
07420                if (iaxs[fr->callno]->owner) {
07421                   int orignative;
07422 retryowner:
07423                   if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) {
07424                      DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]);
07425                      if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner;
07426                   }
07427                   if (iaxs[fr->callno]) {
07428                      if (iaxs[fr->callno]->owner) {
07429                         orignative = iaxs[fr->callno]->owner->nativeformats;
07430                         iaxs[fr->callno]->owner->nativeformats = f.subclass;
07431                         if (iaxs[fr->callno]->owner->readformat)
07432                            ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat);
07433                         iaxs[fr->callno]->owner->nativeformats = orignative;
07434                         ast_mutex_unlock(&iaxs[fr->callno]->owner->lock);
07435                      }
07436                   } else {
07437                      if (option_debug)
07438                         ast_log(LOG_DEBUG, "Neat, somebody took away the channel at a magical time but i found it!\n");
07439                      ast_mutex_unlock(&iaxsl[fr->callno]);
07440                      return 1;
07441                   }
07442                }
07443          }
07444       }
07445       if (f.frametype == AST_FRAME_VIDEO) {
07446          if (f.subclass != iaxs[fr->callno]->videoformat) {
07447             if (option_debug)
07448                ast_log(LOG_DEBUG, "Ooh, video format changed to %d\n", f.subclass & ~0x1);
07449             iaxs[fr->callno]->videoformat = f.subclass & ~0x1;
07450          }
07451       }
07452       if (f.frametype == AST_FRAME_IAX) {
07453          AST_SCHED_DEL(sched, iaxs[fr->callno]->initid);
07454          /* Handle the IAX pseudo frame itself */
07455          if (option_debug && iaxdebug)
07456             ast_log(LOG_DEBUG, "IAX subclass %d received\n", f.subclass);
07457 
07458                         /* Update last ts unless the frame's timestamp originated with us. */
07459          if (iaxs[fr->callno]->last < fr->ts &&
07460                             f.subclass != IAX_COMMAND_ACK &&
07461                             f.subclass != IAX_COMMAND_PONG &&
07462                             f.subclass != IAX_COMMAND_LAGRP) {
07463             iaxs[fr->callno]->last = fr->ts;
07464             if (option_debug && iaxdebug)
07465                ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts);
07466          }
07467 
07468          switch(f.subclass) {
07469          case IAX_COMMAND_ACK:
07470             /* Do nothing */
07471             break;
07472          case IAX_COMMAND_QUELCH:
07473             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
07474                     /* Generate Manager Hold event, if necessary*/
07475                if (iaxs[fr->callno]->owner) {
07476                   manager_event(EVENT_FLAG_CALL, "Hold",
07477                      "Channel: %s\r\n"
07478                      "Uniqueid: %s\r\n",
07479                      iaxs[fr->callno]->owner->name, 
07480                      iaxs[fr->callno]->owner->uniqueid);
07481                }
07482 
07483                ast_set_flag(iaxs[fr->callno], IAX_QUELCH);
07484                if (ies.musiconhold) {
07485                   if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) {
07486                      const char *mohsuggest = iaxs[fr->callno]->mohsuggest;
07487                      iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, 
07488                         S_OR(mohsuggest, NULL),
07489                         !ast_strlen_zero(mohsuggest) ? strlen(mohsuggest) + 1 : 0);
07490                      if (!iaxs[fr->callno]) {
07491                         ast_mutex_unlock(&iaxsl[fr->callno]);
07492                         return 1;
07493                      }
07494                   }
07495                }
07496             }
07497             break;
07498          case IAX_COMMAND_UNQUELCH:
07499             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
07500                     /* Generate Manager Unhold event, if necessary*/
07501                if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) {
07502                   manager_event(EVENT_FLAG_CALL, "Unhold",
07503                      "Channel: %s\r\n"
07504                      "Uniqueid: %s\r\n",
07505                      iaxs[fr->callno]->owner->name, 
07506                      iaxs[fr->callno]->owner->uniqueid);
07507                }
07508 
07509                ast_clear_flag(iaxs[fr->callno], IAX_QUELCH);
07510                if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) {
07511                   iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0);
07512                   if (!iaxs[fr->callno]) {
07513                      ast_mutex_unlock(&iaxsl[fr->callno]);
07514                      return 1;
07515                   }
07516                }
07517             }
07518             break;
07519          case IAX_COMMAND_TXACC:
07520             if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) {
07521                /* Ack the packet with the given timestamp */
07522                AST_LIST_LOCK(&iaxq.queue);
07523                AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
07524                   /* Cancel any outstanding txcnt's */
07525                   if ((fr->callno == cur->callno) && (cur->transfer))
07526                      cur->retries = -1;
07527                }
07528                AST_LIST_UNLOCK(&iaxq.queue);
07529                memset(&ied1, 0, sizeof(ied1));
07530                iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno);
07531                send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1);
07532                iaxs[fr->callno]->transferring = TRANSFER_READY;
07533             }
07534             break;
07535          case IAX_COMMAND_NEW:
07536             /* Ignore if it's already up */
07537             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD))
07538                break;
07539             if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) {
07540                ast_mutex_unlock(&iaxsl[fr->callno]);
07541                check_provisioning(&sin, fd, ies.serviceident, ies.provver);
07542                ast_mutex_lock(&iaxsl[fr->callno]);
07543                if (!iaxs[fr->callno]) {
07544                   ast_mutex_unlock(&iaxsl[fr->callno]);
07545                   return 1;
07546                }
07547             }
07548             /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */
07549             if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) {
07550                int new_callno;
07551                if ((new_callno = make_trunk(fr->callno, 1)) != -1)
07552                   fr->callno = new_callno;
07553             }
07554             /* For security, always ack immediately */
07555             if (delayreject)
07556                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07557             if (check_access(fr->callno, &sin, &ies)) {
07558                /* They're not allowed on */
07559                auth_fail(fr->callno, IAX_COMMAND_REJECT);
07560                if (authdebug)
07561                   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);
07562                break;
07563             }
07564             if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) {
07565                const char *context, *exten, *cid_num;
07566 
07567                context = ast_strdupa(iaxs[fr->callno]->context);
07568                exten = ast_strdupa(iaxs[fr->callno]->exten);
07569                cid_num = ast_strdupa(iaxs[fr->callno]->cid_num);
07570 
07571                /* This might re-enter the IAX code and need the lock */
07572                ast_mutex_unlock(&iaxsl[fr->callno]);
07573                exists = ast_exists_extension(NULL, context, exten, 1, cid_num);
07574                ast_mutex_lock(&iaxsl[fr->callno]);
07575 
07576                if (!iaxs[fr->callno]) {
07577                   ast_mutex_unlock(&iaxsl[fr->callno]);
07578                   return 1;
07579                }
07580             } else
07581                exists = 0;
07582             if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) {
07583                if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) {
07584                   memset(&ied0, 0, sizeof(ied0));
07585                   iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
07586                   iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
07587                   send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07588                   if (!iaxs[fr->callno]) {
07589                      ast_mutex_unlock(&iaxsl[fr->callno]);
07590                      return 1;
07591                   }
07592                   if (authdebug)
07593                      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);
07594                } else {
07595                   /* Select an appropriate format */
07596 
07597                   if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
07598                      if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07599                         using_prefs = "reqonly";
07600                      } else {
07601                         using_prefs = "disabled";
07602                      }
07603                      format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability;
07604                      memset(&pref, 0, sizeof(pref));
07605                      strcpy(caller_pref_buf, "disabled");
07606                      strcpy(host_pref_buf, "disabled");
07607                   } else {
07608                      using_prefs = "mine";
07609                      /* If the information elements are in here... use them */
07610                      if (ies.codec_prefs)
07611                         ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
07612                      if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
07613                         /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
07614                         if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
07615                            pref = iaxs[fr->callno]->rprefs;
07616                            using_prefs = "caller";
07617                         } else {
07618                            pref = iaxs[fr->callno]->prefs;
07619                         }
07620                      } else
07621                         pref = iaxs[fr->callno]->prefs;
07622                      
07623                      format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
07624                      ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
07625                      ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
07626                   }
07627                   if (!format) {
07628                      if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
07629                         format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
07630                      if (!format) {
07631                         memset(&ied0, 0, sizeof(ied0));
07632                         iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07633                         iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07634                         send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07635                         if (!iaxs[fr->callno]) {
07636                            ast_mutex_unlock(&iaxsl[fr->callno]);
07637                            return 1;
07638                         }
07639                         if (authdebug) {
07640                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
07641                               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);
07642                            else 
07643                               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);
07644                         }
07645                      } else {
07646                         /* Pick one... */
07647                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07648                            if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability))
07649                               format = 0;
07650                         } else {
07651                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
07652                               using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
07653                               memset(&pref, 0, sizeof(pref));
07654                               format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
07655                               strcpy(caller_pref_buf,"disabled");
07656                               strcpy(host_pref_buf,"disabled");
07657                            } else {
07658                               using_prefs = "mine";
07659                               if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
07660                                  /* Do the opposite of what we tried above. */
07661                                  if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
07662                                     pref = iaxs[fr->callno]->prefs;                       
07663                                  } else {
07664                                     pref = iaxs[fr->callno]->rprefs;
07665                                     using_prefs = "caller";
07666                                  }
07667                                  format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1);
07668                            
07669                               } else /* if no codec_prefs IE do it the old way */
07670                                  format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 
07671                            }
07672                         }
07673 
07674                         if (!format) {
07675                            memset(&ied0, 0, sizeof(ied0));
07676                            iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07677                            iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07678                            ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
07679                            send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07680                            if (!iaxs[fr->callno]) {
07681                               ast_mutex_unlock(&iaxsl[fr->callno]);
07682                               return 1;
07683                            }
07684                            if (authdebug)
07685                               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);
07686                            ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);   
07687                            break;
07688                         }
07689                      }
07690                   }
07691                   if (format) {
07692                      /* No authentication required, let them in */
07693                      memset(&ied1, 0, sizeof(ied1));
07694                      iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
07695                      send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
07696                      if (strcmp(iaxs[fr->callno]->exten, "TBD")) {
07697                         ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07698                         if (option_verbose > 2) 
07699                            ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n"
07700                                     "%srequested format = %s,\n"
07701                                     "%srequested prefs = %s,\n"
07702                                     "%sactual format = %s,\n"
07703                                     "%shost prefs = %s,\n"
07704                                     "%spriority = %s\n",
07705                                     ast_inet_ntoa(sin.sin_addr), 
07706                                     VERBOSE_PREFIX_4,
07707                                     ast_getformatname(iaxs[fr->callno]->peerformat), 
07708                                     VERBOSE_PREFIX_4,
07709                                     caller_pref_buf,
07710                                     VERBOSE_PREFIX_4,
07711                                     ast_getformatname(format), 
07712                                     VERBOSE_PREFIX_4,
07713                                     host_pref_buf, 
07714                                     VERBOSE_PREFIX_4,
07715                                     using_prefs);
07716                         
07717                         iaxs[fr->callno]->chosenformat = format;
07718                         ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART);
07719                      } else {
07720                         ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
07721                         /* If this is a TBD call, we're ready but now what...  */
07722                         if (option_verbose > 2)
07723                            ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr));
07724                      }
07725                   }
07726                }
07727                break;
07728             }
07729             if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5)
07730                merge_encryption(iaxs[fr->callno],ies.encmethods);
07731             else
07732                iaxs[fr->callno]->encmethods = 0;
07733             if (!authenticate_request(fr->callno) && iaxs[fr->callno])
07734                ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED);
07735             if (!iaxs[fr->callno]) {
07736                ast_mutex_unlock(&iaxsl[fr->callno]);
07737                return 1;
07738             }
07739             break;
07740          case IAX_COMMAND_DPREQ:
07741             /* Request status in the dialplan */
07742             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) &&
07743                !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) {
07744                if (iaxcompat) {
07745                   /* Spawn a thread for the lookup */
07746                   spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num);
07747                } else {
07748                   /* Just look it up */
07749                   dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1);
07750                }
07751             }
07752             break;
07753          case IAX_COMMAND_HANGUP:
07754             ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
07755             if (option_debug)
07756                ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr->callno);
07757             /* Set hangup cause according to remote */
07758             if (ies.causecode && iaxs[fr->callno]->owner)
07759                iaxs[fr->callno]->owner->hangupcause = ies.causecode;
07760             /* Send ack immediately, before we destroy */
07761             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07762             iax2_destroy(fr->callno);
07763             break;
07764          case IAX_COMMAND_REJECT:
07765             /* Set hangup cause according to remote */
07766             if (ies.causecode && iaxs[fr->callno]->owner)
07767                iaxs[fr->callno]->owner->hangupcause = ies.causecode;
07768 
07769             if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) {
07770                if (iaxs[fr->callno]->owner && authdebug)
07771                   ast_log(LOG_WARNING, "Call rejected by %s: %s\n",
07772                      ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr),
07773                      ies.cause ? ies.cause : "<Unknown>");
07774                if (option_debug)
07775                   ast_log(LOG_DEBUG, "Immediately destroying %d, having received reject\n",
07776                      fr->callno);
07777             }
07778             /* Send ack immediately, before we destroy */
07779             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK,
07780                          fr->ts, NULL, 0, fr->iseqno);
07781             if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION))
07782                iaxs[fr->callno]->error = EPERM;
07783             iax2_destroy(fr->callno);
07784             break;
07785          case IAX_COMMAND_TRANSFER:
07786          {
07787             struct ast_channel *bridged_chan;
07788 
07789             if (iaxs[fr->callno]->owner && (bridged_chan = ast_bridged_channel(iaxs[fr->callno]->owner)) && ies.called_number) {
07790                /* Set BLINDTRANSFER channel variables */
07791 
07792                ast_mutex_unlock(&iaxsl[fr->callno]);
07793                pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", bridged_chan->name);
07794                ast_mutex_lock(&iaxsl[fr->callno]);
07795                if (!iaxs[fr->callno]) {
07796                   ast_mutex_unlock(&iaxsl[fr->callno]);
07797                   return 1;
07798                }
07799 
07800                pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", iaxs[fr->callno]->owner->name);
07801                if (!strcmp(ies.called_number, ast_parking_ext())) {
07802                   if (iax_park(bridged_chan, iaxs[fr->callno]->owner)) {
07803                      ast_log(LOG_WARNING, "Failed to park call on '%s'\n", bridged_chan->name);
07804                   } else {
07805                      ast_log(LOG_DEBUG, "Parked call on '%s'\n", bridged_chan->name);
07806                   }
07807                } else {
07808                   if (ast_async_goto(bridged_chan, iaxs[fr->callno]->context, ies.called_number, 1))
07809                      ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", bridged_chan->name, 
07810                         ies.called_number, iaxs[fr->callno]->context);
07811                   else
07812                      ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", bridged_chan->name, 
07813                         ies.called_number, iaxs[fr->callno]->context);
07814                }
07815             } else
07816                   ast_log(LOG_DEBUG, "Async goto not applicable on call %d\n", fr->callno);
07817 
07818             break;
07819          }
07820          case IAX_COMMAND_ACCEPT:
07821             /* Ignore if call is already up or needs authentication or is a TBD */
07822             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED))
07823                break;
07824             if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) {
07825                /* Send ack immediately, before we destroy */
07826                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07827                iax2_destroy(fr->callno);
07828                break;
07829             }
07830             if (ies.format) {
07831                iaxs[fr->callno]->peerformat = ies.format;
07832             } else {
07833                if (iaxs[fr->callno]->owner)
07834                   iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats;
07835                else
07836                   iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability;
07837             }
07838             if (option_verbose > 2)
07839                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));
07840             if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) {
07841                memset(&ied0, 0, sizeof(ied0));
07842                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07843                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07844                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07845                if (!iaxs[fr->callno]) {
07846                   ast_mutex_unlock(&iaxsl[fr->callno]);
07847                   return 1;
07848                }
07849                if (authdebug)
07850                   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);
07851             } else {
07852                ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07853                if (iaxs[fr->callno]->owner) {
07854                   /* Switch us to use a compatible format */
07855                   iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat;
07856                   if (option_verbose > 2)
07857                      ast_verbose(VERBOSE_PREFIX_3 "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats));
07858 retryowner2:
07859                   if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) {
07860                      DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]);
07861                      if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2;
07862                   }
07863                   
07864                   if (iaxs[fr->callno] && iaxs[fr->callno]->owner) {
07865                      /* Setup read/write formats properly. */
07866                      if (iaxs[fr->callno]->owner->writeformat)
07867                         ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat);   
07868                      if (iaxs[fr->callno]->owner->readformat)
07869                         ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat);  
07870                      ast_mutex_unlock(&iaxs[fr->callno]->owner->lock);
07871                   }
07872                }
07873             }
07874             if (iaxs[fr->callno]) {
07875                ast_mutex_lock(&dpcache_lock);
07876                dp = iaxs[fr->callno]->dpentries;
07877                while(dp) {
07878                   if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) {
07879                      iax2_dprequest(dp, fr->callno);
07880                   }
07881                   dp = dp->peer;
07882                }
07883                ast_mutex_unlock(&dpcache_lock);
07884             }
07885             break;
07886          case IAX_COMMAND_POKE:
07887             /* Send back a pong packet with the original timestamp */
07888             send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1);
07889             if (!iaxs[fr->callno]) {
07890                ast_mutex_unlock(&iaxsl[fr->callno]);
07891                return 1;
07892             }
07893             break;
07894          case IAX_COMMAND_PING:
07895          {
07896             struct iax_ie_data pingied;
07897             construct_rr(iaxs[fr->callno], &pingied);
07898             /* Send back a pong packet with the original timestamp */
07899             send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1);
07900          }
07901             break;
07902          case IAX_COMMAND_PONG:
07903             /* Calculate ping time */
07904             iaxs[fr->callno]->pingtime =  calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts;
07905             /* save RR info */
07906             save_rr(fr, &ies);
07907 
07908             if (iaxs[fr->callno]->peerpoke) {
07909                peer = iaxs[fr->callno]->peerpoke;
07910                if ((peer->lastms < 0)  || (peer->historicms > peer->maxms)) {
07911                   if (iaxs[fr->callno]->pingtime <= peer->maxms) {
07912                      ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime);
07913                      manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 
07914                      ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
07915                   }
07916                } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) {
07917                   if (iaxs[fr->callno]->pingtime > peer->maxms) {
07918                      ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime);
07919                      manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 
07920                      ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
07921                   }
07922                }
07923                peer->lastms = iaxs[fr->callno]->pingtime;
07924                if (peer->smoothing && (peer->lastms > -1))
07925                   peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2;
07926                else if (peer->smoothing && peer->lastms < 0)
07927                   peer->historicms = (0 + peer->historicms) / 2;
07928                else              
07929                   peer->historicms = iaxs[fr->callno]->pingtime;
07930 
07931                /* Remove scheduled iax2_poke_noanswer */
07932                if (peer->pokeexpire > -1) {
07933                   if (!ast_sched_del(sched, peer->pokeexpire)) {
07934                      peer_unref(peer);
07935                      peer->pokeexpire = -1;
07936                   }
07937                }
07938                /* Schedule the next cycle */
07939                if ((peer->lastms < 0)  || (peer->historicms > peer->maxms)) 
07940                   peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
07941                else
07942                   peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer_ref(peer));
07943                if (peer->pokeexpire == -1)
07944                   peer_unref(peer);
07945                /* and finally send the ack */
07946                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07947                /* And wrap up the qualify call */
07948                iax2_destroy(fr->callno);
07949                peer->callno = 0;
07950                if (option_debug)
07951                   ast_log(LOG_DEBUG, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms);
07952             }
07953             break;
07954          case IAX_COMMAND_LAGRQ:
07955          case IAX_COMMAND_LAGRP:
07956             f.src = "LAGRQ";
07957             f.mallocd = 0;
07958             f.offset = 0;
07959             f.samples = 0;
07960             iax_frame_wrap(fr, &f);
07961             if(f.subclass == IAX_COMMAND_LAGRQ) {
07962                /* Received a LAGRQ - echo back a LAGRP */
07963                fr->af.subclass = IAX_COMMAND_LAGRP;
07964                iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0);
07965             } else {
07966                /* Received LAGRP in response to our LAGRQ */
07967                unsigned int ts;
07968                /* This is a reply we've been given, actually measure the difference */
07969                ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af);
07970                iaxs[fr->callno]->lag = ts - fr->ts;
07971                if (option_debug && iaxdebug)
07972                   ast_log(LOG_DEBUG, "Peer %s lag measured as %dms\n",
07973                      ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag);
07974             }
07975             break;
07976          case IAX_COMMAND_AUTHREQ:
07977             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
07978                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>");
07979                break;
07980             }
07981             if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) {
07982                struct ast_frame hangup_fr = { .frametype = AST_FRAME_CONTROL,
07983                         .subclass = AST_CONTROL_HANGUP,
07984                };
07985                ast_log(LOG_WARNING, 
07986                   "I don't know how to authenticate %s to %s\n", 
07987                   ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr));
07988                iax2_queue_frame(fr->callno, &hangup_fr);
07989             }
07990             if (!iaxs[fr->callno]) {
07991                ast_mutex_unlock(&iaxsl[fr->callno]);
07992                return 1;
07993             }
07994             break;
07995          case IAX_COMMAND_AUTHREP:
07996             /* For security, always ack immediately */
07997             if (delayreject)
07998                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07999             /* Ignore once we've started */
08000             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
08001                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>");
08002                break;
08003             }
08004             if (authenticate_verify(iaxs[fr->callno], &ies)) {
08005                if (authdebug)
08006                   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);
08007                memset(&ied0, 0, sizeof(ied0));
08008                auth_fail(fr->callno, IAX_COMMAND_REJECT);
08009                break;
08010             }
08011             if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) {
08012                /* This might re-enter the IAX code and need the lock */
08013                exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num);
08014             } else
08015                exists = 0;
08016             if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) {
08017                if (authdebug)
08018                   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);
08019                memset(&ied0, 0, sizeof(ied0));
08020                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
08021                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
08022                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
08023                if (!iaxs[fr->callno]) {
08024                   ast_mutex_unlock(&iaxsl[fr->callno]);
08025                   return 1;
08026                }
08027             } else {
08028                /* Select an appropriate format */
08029                if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
08030                   if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
08031                      using_prefs = "reqonly";
08032                   } else {
08033                      using_prefs = "disabled";
08034                   }
08035                   format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability;
08036                   memset(&pref, 0, sizeof(pref));
08037                   strcpy(caller_pref_buf, "disabled");
08038                   strcpy(host_pref_buf, "disabled");
08039                } else {
08040                   using_prefs = "mine";
08041                   if (ies.codec_prefs)
08042                      ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
08043                   if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
08044                      if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
08045                         pref = iaxs[fr->callno]->rprefs;
08046                         using_prefs = "caller";
08047                      } else {
08048                         pref = iaxs[fr->callno]->prefs;
08049                      }
08050                   } else /* if no codec_prefs IE do it the old way */
08051                      pref = iaxs[fr->callno]->prefs;
08052                
08053                   format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
08054                   ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
08055                   ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
08056                }
08057                if (!format) {
08058                   if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
08059                      if (option_debug)
08060                         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);
08061                      format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
08062                   }
08063                   if (!format) {
08064                      if (authdebug) {
08065                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 
08066                            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);
08067                         else
08068                            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);
08069                      }
08070                      memset(&ied0, 0, sizeof(ied0));
08071                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
08072                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
08073                      send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
08074                      if (!iaxs[fr->callno]) {
08075                         ast_mutex_unlock(&iaxsl[fr->callno]);
08076                         return 1;
08077                      }
08078                   } else {
08079                      /* Pick one... */
08080                      if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
08081                         if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability))
08082                            format = 0;
08083                      } else {
08084                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
08085                            using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
08086                            memset(&pref, 0, sizeof(pref));
08087                            format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ?
08088                               iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
08089                            strcpy(caller_pref_buf,"disabled");
08090                            strcpy(host_pref_buf,"disabled");
08091                         } else {
08092                            using_prefs = "mine";
08093                            if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
08094                               /* Do the opposite of what we tried above. */
08095                               if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
08096                                  pref = iaxs[fr->callno]->prefs;                 
08097                               } else {
08098                                  pref = iaxs[fr->callno]->rprefs;
08099                                  using_prefs = "caller";
08100                               }
08101                               format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1);
08102                            } else /* if no codec_prefs IE do it the old way */
08103                               format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 
08104                         }
08105                      }
08106                      if (!format) {
08107                         ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
08108                         if (authdebug) {
08109                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
08110                               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);
08111                            else
08112                               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);
08113                         }
08114                         memset(&ied0, 0, sizeof(ied0));
08115                         iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
08116                         iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
08117                         send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
08118                         if (!iaxs[fr->callno]) {
08119                            ast_mutex_unlock(&iaxsl[fr->callno]);
08120                            return 1;
08121                         }
08122                      }
08123                   }
08124                }
08125                if (format) {
08126                   /* Authentication received */
08127                   memset(&ied1, 0, sizeof(ied1));
08128                   iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
08129                   send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
08130                   if (strcmp(iaxs[fr->callno]->exten, "TBD")) {
08131                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
08132                      if (option_verbose > 2) 
08133                         ast_verbose(VERBOSE_PREFIX_3 "Accepting AUTHENTICATED call from %s:\n"
08134                                  "%srequested format = %s,\n"
08135                                  "%srequested prefs = %s,\n"
08136                                  "%sactual format = %s,\n"
08137                                  "%shost prefs = %s,\n"
08138                                  "%spriority = %s\n", 
08139                                  ast_inet_ntoa(sin.sin_addr), 
08140                                  VERBOSE_PREFIX_4,
08141                                  ast_getformatname(iaxs[fr->callno]->peerformat),
08142                                  VERBOSE_PREFIX_4,
08143                                  caller_pref_buf,
08144                                  VERBOSE_PREFIX_4,
08145                                  ast_getformatname(format),
08146                                  VERBOSE_PREFIX_4,
08147                                  host_pref_buf,
08148                                  VERBOSE_PREFIX_4,
08149                                  using_prefs);
08150 
08151                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
08152                      if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format)))
08153                         iax2_destroy(fr->callno);
08154                   } else {
08155                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
08156                      /* If this is a TBD call, we're ready but now what...  */
08157                      if (option_verbose > 2)
08158                         ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr));
08159                   }
08160                }
08161             }
08162             break;
08163          case IAX_COMMAND_DIAL:
08164             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) {
08165                ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
08166                ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s");
08167                if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) {
08168                   if (authdebug)
08169                      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);
08170                   memset(&ied0, 0, sizeof(ied0));
08171                   iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
08172                   iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
08173                   send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
08174                   if (!iaxs[fr->callno]) {
08175                      ast_mutex_unlock(&iaxsl[fr->callno]);
08176                      return 1;
08177                   }
08178                } else {
08179                   ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
08180                   if (option_verbose > 2) 
08181                      ast_verbose(VERBOSE_PREFIX_3 "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat);
08182                   ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
08183                   send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1);
08184                   if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat)))
08185                      iax2_destroy(fr->callno);
08186                }
08187             }
08188             break;
08189          case IAX_COMMAND_INVAL:
08190             iaxs[fr->callno]->error = ENOTCONN;
08191             if (option_debug)
08192                ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr->callno);
08193             iax2_destroy(fr->callno);
08194             if (option_debug)
08195                ast_log(LOG_DEBUG, "Destroying call %d\n", fr->callno);
08196             break;
08197          case IAX_COMMAND_VNAK:
08198             if (option_debug)
08199                ast_log(LOG_DEBUG, "Received VNAK: resending outstanding frames\n");
08200             /* Force retransmission */
08201             vnak_retransmit(fr->callno, fr->iseqno);
08202             break;
08203          case IAX_COMMAND_REGREQ:
08204          case IAX_COMMAND_REGREL:
08205             /* For security, always ack immediately */
08206             if (delayreject)
08207                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08208             if (register_verify(fr->callno, &sin, &ies)) {
08209                if (!iaxs[fr->callno]) {
08210                   ast_mutex_unlock(&iaxsl[fr->callno]);
08211                   return 1;
08212                }
08213                /* Send delayed failure */
08214                auth_fail(fr->callno, IAX_COMMAND_REGREJ);
08215                break;
08216             }
08217             if (!iaxs[fr->callno]) {
08218                ast_mutex_unlock(&iaxsl[fr->callno]);
08219                return 1;
08220             }
08221             if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 
08222                   ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED)) {
08223                if (f.subclass == IAX_COMMAND_REGREL)
08224                   memset(&sin, 0, sizeof(sin));
08225                if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh))
08226                   ast_log(LOG_WARNING, "Registry error\n");
08227                if (!iaxs[fr->callno]) {
08228                   ast_mutex_unlock(&iaxsl[fr->callno]);
08229                   return 1;
08230                }
08231                if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) {
08232                   ast_mutex_unlock(&iaxsl[fr->callno]);
08233                   check_provisioning(&sin, fd, ies.serviceident, ies.provver);
08234                   ast_mutex_lock(&iaxsl[fr->callno]);
08235                   if (!iaxs[fr->callno]) {
08236                      ast_mutex_unlock(&iaxsl[fr->callno]);
08237                      return 1;
08238                   }
08239                }
08240                break;
08241             }
08242             registry_authrequest(fr->callno);
08243             if (!iaxs[fr->callno]) {
08244                ast_mutex_unlock(&iaxsl[fr->callno]);
08245                return 1;
08246             }
08247             break;
08248          case IAX_COMMAND_REGACK:
08249             if (iax2_ack_registry(&ies, &sin, fr->callno)) 
08250                ast_log(LOG_WARNING, "Registration failure\n");
08251             /* Send ack immediately, before we destroy */
08252             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08253             iax2_destroy(fr->callno);
08254             break;
08255          case IAX_COMMAND_REGREJ:
08256             if (iaxs[fr->callno]->reg) {
08257                if (authdebug) {
08258                   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));
08259                   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>");
08260                }
08261                iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED;
08262             }
08263             /* Send ack immediately, before we destroy */
08264             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08265             iax2_destroy(fr->callno);
08266             break;
08267          case IAX_COMMAND_REGAUTH:
08268             /* Authentication request */
08269             if (registry_rerequest(&ies, fr->callno, &sin)) {
08270                memset(&ied0, 0, sizeof(ied0));
08271                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found");
08272                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
08273                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
08274                if (!iaxs[fr->callno]) {
08275                   ast_mutex_unlock(&iaxsl[fr->callno]);
08276                   return 1;
08277                }
08278             }
08279             break;
08280          case IAX_COMMAND_TXREJ:
08281             iaxs[fr->callno]->transferring = 0;
08282             if (option_verbose > 2) 
08283                ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
08284             memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer));
08285             if (iaxs[fr->callno]->bridgecallno) {
08286                if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) {
08287                   iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0;
08288                   send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
08289                }
08290             }
08291             break;
08292          case IAX_COMMAND_TXREADY:
08293             if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) ||
08294                 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) {
08295                if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)
08296                   iaxs[fr->callno]->transferring = TRANSFER_MREADY;
08297                else
08298                   iaxs[fr->callno]->transferring = TRANSFER_READY;
08299                if (option_verbose > 2) 
08300                   ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
08301                if (iaxs[fr->callno]->bridgecallno) {
08302                   if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) ||
08303                       (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) {
08304                      /* They're both ready, now release them. */
08305                      if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) {
08306                         if (option_verbose > 2) 
08307                            ast_verbose(VERBOSE_PREFIX_3 "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
08308                               iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
08309 
08310                         iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA;
08311                         iaxs[fr->callno]->transferring = TRANSFER_MEDIA;
08312 
08313                         memset(&ied0, 0, sizeof(ied0));
08314                         memset(&ied1, 0, sizeof(ied1));
08315                         iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
08316                         iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
08317                         send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1);
08318                         send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1);
08319                      } else {
08320                         if (option_verbose > 2) 
08321                            ast_verbose(VERBOSE_PREFIX_3 "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
08322                               iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
08323 
08324                         iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED;
08325                         iaxs[fr->callno]->transferring = TRANSFER_RELEASED;
08326                         ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
08327                         ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
08328 
08329                         /* Stop doing lag & ping requests */
08330                         stop_stuff(fr->callno);
08331                         stop_stuff(iaxs[fr->callno]->bridgecallno);
08332 
08333                         memset(&ied0, 0, sizeof(ied0));
08334                         memset(&ied1, 0, sizeof(ied1));
08335                         iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
08336                         iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
08337                         send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1);
08338                         send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1);
08339                      }
08340 
08341                   }
08342                }
08343             }
08344             break;
08345          case IAX_COMMAND_TXREQ:
08346             try_transfer(iaxs[fr->callno], &ies);
08347             break;
08348          case IAX_COMMAND_TXCNT:
08349             if (iaxs[fr->callno]->transferring)
08350                send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0);
08351             break;
08352          case IAX_COMMAND_TXREL:
08353             /* Send ack immediately, rather than waiting until we've changed addresses */
08354             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08355             complete_transfer(fr->callno, &ies);
08356             stop_stuff(fr->callno); /* for attended transfer to work with libiax */
08357             break;   
08358          case IAX_COMMAND_TXMEDIA:
08359             if (iaxs[fr->callno]->transferring == TRANSFER_READY) {
08360                                         AST_LIST_LOCK(&iaxq.queue);
08361                                         AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
08362                                                 /* Cancel any outstanding frames and start anew */
08363                                                 if ((fr->callno == cur->callno) && (cur->transfer)) {
08364                                                         cur->retries = -1;
08365                                                 }
08366                                         }
08367                                         AST_LIST_UNLOCK(&iaxq.queue);
08368                /* Start sending our media to the transfer address, but otherwise leave the call as-is */
08369                iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS;
08370             }
08371             break;   
08372          case IAX_COMMAND_DPREP:
08373             complete_dpreply(iaxs[fr->callno], &ies);
08374             break;
08375          case IAX_COMMAND_UNSUPPORT:
08376             ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown);
08377             break;
08378          case IAX_COMMAND_FWDOWNL:
08379             /* Firmware download */
08380             if (!ast_test_flag(&globalflags, IAX_ALLOWFWDOWNLOAD)) {
08381                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, NULL, 0, -1);
08382                break;
08383             }
08384             memset(&ied0, 0, sizeof(ied0));
08385             res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc);
08386             if (res < 0)
08387                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
08388             else if (res > 0)
08389                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1);
08390             else
08391                send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1);
08392             if (!iaxs[fr->callno]) {
08393                ast_mutex_unlock(&iaxsl[fr->callno]);
08394                return 1;
08395             }
08396             break;
08397          default:
08398             if (option_debug)
08399                ast_log(LOG_DEBUG, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno);
08400             memset(&ied0, 0, sizeof(ied0));
08401             iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass);
08402             send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1);
08403          }
08404          /* Don't actually pass these frames along */
08405          if ((f.subclass != IAX_COMMAND_ACK) && 
08406            (f.subclass != IAX_COMMAND_TXCNT) && 
08407            (f.subclass != IAX_COMMAND_TXACC) && 
08408            (f.subclass != IAX_COMMAND_INVAL) &&
08409            (f.subclass != IAX_COMMAND_VNAK)) { 
08410             if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno)
08411                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08412          }
08413          ast_mutex_unlock(&iaxsl[fr->callno]);
08414          return 1;
08415       }
08416       /* Unless this is an ACK or INVAL frame, ack it */
08417       if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno)
08418          send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08419    } else if (minivid) {
08420       f.frametype = AST_FRAME_VIDEO;
08421       if (iaxs[fr->callno]->videoformat > 0) 
08422          f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0);
08423       else {
08424          ast_log(LOG_WARNING, "Received mini frame before first full video frame\n ");
08425          iax2_vnak(fr->callno);
08426          ast_mutex_unlock(&iaxsl[fr->callno]);
08427          return 1;
08428       }
08429       f.datalen = res - sizeof(*vh);
08430       if (f.datalen)
08431          f.data = thread->buf + sizeof(*vh);
08432       else
08433          f.data = NULL;
08434 #ifdef IAXTESTS
08435       if (test_resync) {
08436          fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff);
08437       } else
08438 #endif /* IAXTESTS */
08439          fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff);
08440    } else {
08441       /* A mini frame */
08442       f.frametype = AST_FRAME_VOICE;
08443       if (iaxs[fr->callno]->voiceformat > 0)
08444          f.subclass = iaxs[fr->callno]->voiceformat;
08445       else {
08446          if (option_debug)
08447             ast_log(LOG_DEBUG, "Received mini frame before first full voice frame\n");
08448          iax2_vnak(fr->callno);
08449          ast_mutex_unlock(&iaxsl[fr->callno]);
08450          return 1;
08451       }
08452       f.datalen = res - sizeof(struct ast_iax2_mini_hdr);
08453       if (f.datalen < 0) {
08454          ast_log(LOG_WARNING, "Datalen < 0?\n");
08455          ast_mutex_unlock(&iaxsl[fr->callno]);
08456          return 1;
08457       }
08458       if (f.datalen)
08459          f.data = thread->buf + sizeof(*mh);
08460       else
08461          f.data = NULL;
08462 #ifdef IAXTESTS
08463       if (test_resync) {
08464          fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff);
08465       } else
08466 #endif /* IAXTESTS */
08467       fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts);
08468       /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */
08469    }
08470    /* Don't pass any packets until we're started */
08471    if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
08472       ast_mutex_unlock(&iaxsl[fr->callno]);
08473       return 1;
08474    }
08475    /* Common things */
08476    f.src = "IAX2";
08477    f.mallocd = 0;
08478    f.offset = 0;
08479    f.len = 0;
08480    if (f.datalen && (f.frametype == AST_FRAME_VOICE)) {
08481       f.samples = ast_codec_get_samples(&f);
08482       /* We need to byteswap incoming slinear samples from network byte order */
08483       if (f.subclass == AST_FORMAT_SLINEAR)
08484          ast_frame_byteswap_be(&f);
08485    } else
08486       f.samples = 0;
08487    iax_frame_wrap(fr, &f);
08488 
08489    /* If this is our most recent packet, use it as our basis for timestamping */
08490    if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) {
08491       /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/
08492       fr->outoforder = 0;
08493    } else {
08494       if (option_debug && iaxdebug && iaxs[fr->callno])
08495          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);
08496       fr->outoforder = -1;
08497    }
08498    fr->cacheable = ((f.frametype == AST_FRAME_VOICE) || (f.frametype == AST_FRAME_VIDEO));
08499    duped_fr = iaxfrdup2(fr);
08500    if (duped_fr) {
08501       schedule_delivery(duped_fr, updatehistory, 0, &fr->ts);
08502    }
08503    if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) {
08504       iaxs[fr->callno]->last = fr->ts;
08505 #if 1
08506       if (option_debug && iaxdebug)
08507          ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts);
08508 #endif
08509    }
08510 
08511    /* Always run again */
08512    ast_mutex_unlock(&iaxsl[fr->callno]);
08513    return 1;
08514 }

static int socket_read ( int *  id,
int  fd,
short  events,
void *  cbdata 
) [static]

Definition at line 6870 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), 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_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().

06871 {
06872    struct iax2_thread *thread;
06873    socklen_t len;
06874    time_t t;
06875    static time_t last_errtime = 0;
06876    struct ast_iax2_full_hdr *fh;
06877 
06878    if (!(thread = find_idle_thread())) {
06879       time(&t);
06880       if (t != last_errtime && option_debug)
06881          ast_log(LOG_DEBUG, "Out of idle IAX2 threads for I/O, pausing!\n");
06882       last_errtime = t;
06883       usleep(1);
06884       return 1;
06885    }
06886 
06887    len = sizeof(thread->iosin);
06888    thread->iofd = fd;
06889    thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
06890    thread->buf_size = sizeof(thread->readbuf);
06891    thread->buf = thread->readbuf;
06892    if (thread->buf_len < 0) {
06893       if (errno != ECONNREFUSED && errno != EAGAIN)
06894          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
06895       handle_error();
06896       thread->iostate = IAX_IOSTATE_IDLE;
06897       signal_condition(&thread->lock, &thread->cond);
06898       return 1;
06899    }
06900    if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
06901       thread->iostate = IAX_IOSTATE_IDLE;
06902       signal_condition(&thread->lock, &thread->cond);
06903       return 1;
06904    }
06905    
06906    /* Determine if this frame is a full frame; if so, and any thread is currently
06907       processing a full frame for the same callno from this peer, then drop this
06908       frame (and the peer will retransmit it) */
06909    fh = (struct ast_iax2_full_hdr *) thread->buf;
06910    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
06911       struct iax2_thread *cur = NULL;
06912       uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
06913       
06914       AST_LIST_LOCK(&active_list);
06915       AST_LIST_TRAVERSE(&active_list, cur, list) {
06916          if ((cur->ffinfo.callno == callno) &&
06917              !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
06918             break;
06919       }
06920       if (cur) {
06921          /* we found another thread processing a full frame for this call,
06922             so queue it up for processing later. */
06923          defer_full_frame(thread, cur);
06924          AST_LIST_UNLOCK(&active_list);
06925          thread->iostate = IAX_IOSTATE_IDLE;
06926          signal_condition(&thread->lock, &thread->cond);
06927          return 1;
06928       } else {
06929          /* this thread is going to process this frame, so mark it */
06930          thread->ffinfo.callno = callno;
06931          memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
06932          thread->ffinfo.type = fh->type;
06933          thread->ffinfo.csub = fh->csub;
06934       }
06935       AST_LIST_UNLOCK(&active_list);
06936    }
06937    
06938    /* Mark as ready and send on its way */
06939    thread->iostate = IAX_IOSTATE_READY;
06940 #ifdef DEBUG_SCHED_MULTITHREAD
06941    ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
06942 #endif
06943    signal_condition(&thread->lock, &thread->cond);
06944 
06945    return 1;
06946 }

static void spawn_dp_lookup ( int  callno,
const char *  context,
const char *  callednum,
const char *  callerid 
) [static]

Definition at line 6657 of file chan_iax2.c.

References ast_calloc, ast_log(), ast_pthread_create, ast_strdup, dp_lookup_thread(), and LOG_WARNING.

Referenced by socket_process().

06658 {
06659    pthread_t newthread;
06660    struct dpreq_data *dpr;
06661    pthread_attr_t attr;
06662    
06663    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06664       return;
06665 
06666    pthread_attr_init(&attr);
06667    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06668 
06669    dpr->callno = callno;
06670    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06671    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06672    if (callerid)
06673       dpr->callerid = ast_strdup(callerid);
06674    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06675       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06676    }
06677 
06678    pthread_attr_destroy(&attr);
06679 }

static int start_network_thread ( void   )  [static]

Definition at line 9116 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().

09117 {
09118    pthread_attr_t attr;
09119    int threadcount = 0;
09120    int x;
09121    for (x = 0; x < iaxthreadcount; x++) {
09122       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
09123       if (thread) {
09124          thread->type = IAX_TYPE_POOL;
09125          thread->threadnum = ++threadcount;
09126          ast_mutex_init(&thread->lock);
09127          ast_cond_init(&thread->cond, NULL);
09128          pthread_attr_init(&attr);
09129          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
09130          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
09131             ast_log(LOG_WARNING, "Failed to create new thread!\n");
09132             free(thread);
09133             thread = NULL;
09134          }
09135          AST_LIST_LOCK(&idle_list);
09136          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
09137          AST_LIST_UNLOCK(&idle_list);
09138       }
09139    }
09140    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
09141    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
09142    if (option_verbose > 1)
09143       ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount);
09144    return 0;
09145 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 6339 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06340 {
06341    iax2_destroy_helper(iaxs[callno]);
06342 }

static void store_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1236 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().

01237 {
01238    if (!pvt->peercallno) {
01239       ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
01240       return;
01241    }
01242 
01243    ao2_link(iax_peercallno_pvts, pvt);
01244 }

static int timing_read ( int *  id,
int  fd,
short  events,
void *  cbdata 
) [static]

Definition at line 6526 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_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().

06527 {
06528    char buf[1024];
06529    int res;
06530    struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL;
06531    int processed = 0;
06532    int totalcalls = 0;
06533 #ifdef ZT_TIMERACK
06534    int x = 1;
06535 #endif
06536    struct timeval now;
06537    if (iaxtrunkdebug)
06538       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA);
06539    gettimeofday(&now, NULL);
06540    if (events & AST_IO_PRI) {
06541 #ifdef ZT_TIMERACK
06542       /* Great, this is a timing interface, just call the ioctl */
06543       if (ioctl(fd, ZT_TIMERACK, &x)) {
06544          ast_log(LOG_WARNING, "Unable to acknowledge zap timer. IAX trunking will fail!\n");
06545          usleep(1);
06546          return -1;
06547       }
06548 #endif      
06549    } else {
06550       /* Read and ignore from the pseudo channel for timing */
06551       res = read(fd, buf, sizeof(buf));
06552       if (res < 1) {
06553          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
06554          return 1;
06555       }
06556    }
06557    /* For each peer that supports trunking... */
06558    ast_mutex_lock(&tpeerlock);
06559    tpeer = tpeers;
06560    while(tpeer) {
06561       processed++;
06562       res = 0;
06563       ast_mutex_lock(&tpeer->lock);
06564       /* We can drop a single tpeer per pass.  That makes all this logic
06565          substantially easier */
06566       if (!drop && iax2_trunk_expired(tpeer, &now)) {
06567          /* Take it out of the list, but don't free it yet, because it
06568             could be in use */
06569          if (prev)
06570             prev->next = tpeer->next;
06571          else
06572             tpeers = tpeer->next;
06573          drop = tpeer;
06574       } else {
06575          res = send_trunk(tpeer, &now);
06576          if (iaxtrunkdebug)
06577             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);
06578       }     
06579       totalcalls += res;   
06580       res = 0;
06581       ast_mutex_unlock(&tpeer->lock);
06582       prev = tpeer;
06583       tpeer = tpeer->next;
06584    }
06585    ast_mutex_unlock(&tpeerlock);
06586    if (drop) {
06587       ast_mutex_lock(&drop->lock);
06588       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
06589          because by the time they could get tpeerlock, we've already grabbed it */
06590       if (option_debug)
06591          ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
06592       if (drop->trunkdata) {
06593          free(drop->trunkdata);
06594          drop->trunkdata = NULL;
06595       }
06596       ast_mutex_unlock(&drop->lock);
06597       ast_mutex_destroy(&drop->lock);
06598       free(drop);
06599       
06600    }
06601    if (iaxtrunkdebug)
06602       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
06603    iaxtrunkdebug =0;
06604    return 1;
06605 }

static int transmit_trunk ( struct iax_frame f,
struct sockaddr_in *  sin,
int  sockfd 
) [static]

Definition at line 2062 of file chan_iax2.c.

References ast_log(), errno, f, handle_error(), LOG_DEBUG, and option_debug.

Referenced by send_trunk().

02063 {
02064    int res;
02065    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
02066                sizeof(*sin));
02067    if (res < 0) {
02068       if (option_debug)
02069          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
02070       handle_error();
02071    } else
02072       res = 0;
02073    return res;
02074 }

static int try_firmware ( char *  s  )  [static]

Definition at line 1750 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, md5(), MD5Final(), MD5Init(), MD5Update(), iax_firmware::mmaplen, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.

Referenced by reload_firmware().

01751 {
01752    struct stat stbuf;
01753    struct iax_firmware *cur;
01754    int ifd;
01755    int fd;
01756    int res;
01757    
01758    struct ast_iax2_firmware_header *fwh, fwh2;
01759    struct MD5Context md5;
01760    unsigned char sum[16];
01761    unsigned char buf[1024];
01762    int len, chunk;
01763    char *s2;
01764    char *last;
01765    s2 = alloca(strlen(s) + 100);
01766    if (!s2) {
01767       ast_log(LOG_WARNING, "Alloca failed!\n");
01768       return -1;
01769    }
01770    last = strrchr(s, '/');
01771    if (last)
01772       last++;
01773    else
01774       last = s;
01775    snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random());
01776    res = stat(s, &stbuf);
01777    if (res < 0) {
01778       ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno));
01779       return -1;
01780    }
01781    /* Make sure it's not a directory */
01782    if (S_ISDIR(stbuf.st_mode))
01783       return -1;
01784    ifd = open(s, O_RDONLY);
01785    if (ifd < 0) {
01786       ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno));
01787       return -1;
01788    }
01789    fd = open(s2, O_RDWR | O_CREAT | O_EXCL, 0600);
01790    if (fd < 0) {
01791       ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno));
01792       close(ifd);
01793       return -1;
01794    }
01795    /* Unlink our newly created file */
01796    unlink(s2);
01797    
01798    /* Now copy the firmware into it */
01799    len = stbuf.st_size;
01800    while(len) {
01801       chunk = len;
01802       if (chunk > sizeof(buf))
01803          chunk = sizeof(buf);
01804       res = read(ifd, buf, chunk);
01805       if (res != chunk) {
01806          ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01807          close(ifd);
01808          close(fd);
01809          return -1;
01810       }
01811       res = write(fd, buf, chunk);
01812       if (res != chunk) {
01813          ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01814          close(ifd);
01815          close(fd);
01816          return -1;
01817       }
01818       len -= chunk;
01819    }
01820    close(ifd);
01821    /* Return to the beginning */
01822    lseek(fd, 0, SEEK_SET);
01823    if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) {
01824       ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s);
01825       close(fd);
01826       return -1;
01827    }
01828    if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) {
01829       ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s);
01830       close(fd);
01831       return -1;
01832    }
01833    if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) {
01834       ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s);
01835       close(fd);
01836       return -1;
01837    }
01838    if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) {
01839       ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s);
01840       close(fd);
01841       return -1;
01842    }
01843    fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 
01844    if (fwh == (void *) -1) {
01845       ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno));
01846       close(fd);
01847       return -1;
01848    }
01849    MD5Init(&md5);
01850    MD5Update(&md5, fwh->data, ntohl(fwh->datalen));
01851    MD5Final(sum, &md5);
01852    if (memcmp(sum, fwh->chksum, sizeof(sum))) {
01853       ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s);
01854       munmap((void*)fwh, stbuf.st_size);
01855       close(fd);
01856       return -1;
01857    }
01858    cur = waresl.wares;
01859    while(cur) {
01860       if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) {
01861          /* Found a candidate */
01862          if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version)))
01863             /* The version we have on loaded is older, load this one instead */
01864             break;
01865          /* This version is no newer than what we have.  Don't worry about it.
01866             We'll consider it a proper load anyhow though */
01867          munmap((void*)fwh, stbuf.st_size);
01868          close(fd);
01869          return 0;
01870       }
01871       cur = cur->next;
01872    }
01873    if (!cur) {
01874       /* Allocate a new one and link it */
01875       if ((cur = ast_calloc(1, sizeof(*cur)))) {
01876          cur->fd = -1;
01877          cur->next = waresl.wares;
01878          waresl.wares = cur;
01879       }
01880    }
01881    if (cur) {
01882       if (cur->fwh) {
01883          munmap((void*)cur->fwh, cur->mmaplen);
01884       }
01885       if (cur->fd > -1)
01886          close(cur->fd);
01887       cur->fwh = fwh;
01888       cur->fd = fd;
01889       cur->mmaplen = stbuf.st_size;
01890       cur->dead = 0;
01891    }
01892    return 0;
01893 }

static int try_transfer ( struct chan_iax2_pvt pvt,
struct iax_ies ies 
) [static]

Definition at line 5741 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), IAX_COMMAND_TXCNT, iax_ie_append_int(), IAX_IE_TRANSFERID, ies, LOG_WARNING, send_command_transfer(), chan_iax2_pvt::transfer, TRANSFER_BEGIN, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferid, and chan_iax2_pvt::transferring.

Referenced by socket_process().

05742 {
05743    int newcall = 0;
05744    char newip[256];
05745    struct iax_ie_data ied;
05746    struct sockaddr_in new;
05747    
05748    
05749    memset(&ied, 0, sizeof(ied));
05750    if (ies->apparent_addr)
05751       bcopy(ies->apparent_addr, &new, sizeof(new));
05752    if (ies->callno)
05753       newcall = ies->callno;
05754    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05755       ast_log(LOG_WARNING, "Invalid transfer request\n");
05756       return -1;
05757    }
05758    pvt->transfercallno = newcall;
05759    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05760    inet_aton(newip, &pvt->transfer.sin_addr);
05761    pvt->transfer.sin_family = AF_INET;
05762    pvt->transferring = TRANSFER_BEGIN;
05763    pvt->transferid = ies->transferid;
05764    if (ies->transferid)
05765       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05766    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05767    return 0; 
05768 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1081 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

01082 {
01083    /* If the SC_LOG flag is set, return 2^csub otherwise csub */
01084    if (csub & IAX_FLAG_SC_LOG) {
01085       /* special case for 'compressed' -1 */
01086       if (csub == 0xff)
01087          return -1;
01088       else
01089          return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT);
01090    }
01091    else
01092       return csub;
01093 }

static void unlink_peer ( struct iax2_peer peer  )  [static]

Definition at line 6013 of file chan_iax2.c.

References ao2_unlink(), ast_sched_del(), iax2_peer::expire, peer_unref(), peers, iax2_peer::pokeexpire, and sched.

Referenced by __expire_registry(), build_peer(), and prune_peers().

06014 {
06015    if (peer->expire > -1) {
06016       if (!ast_sched_del(sched, peer->expire)) {
06017          peer->expire = -1;
06018          peer_unref(peer);
06019       }
06020    }
06021 
06022    if (peer->pokeexpire > -1) {
06023       if (!ast_sched_del(sched, peer->pokeexpire)) {
06024          peer->pokeexpire = -1;
06025          peer_unref(peer);
06026       }
06027    }
06028 
06029    ao2_unlink(peers, peer);
06030 }

static int unload_module ( void   )  [static]

Definition at line 11041 of file chan_iax2.c.

References __unload_module(), ast_custom_function_unregister(), and iaxpeer_function.

11042 {
11043    ast_custom_function_unregister(&iaxpeer_function);
11044    return __unload_module();
11045 }

static void unlock_both ( unsigned short  callno0,
unsigned short  callno1 
) [static]

Definition at line 3469 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03470 {
03471    ast_mutex_unlock(&iaxsl[callno1]);
03472    ast_mutex_unlock(&iaxsl[callno0]);
03473 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

Definition at line 2496 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().

02497 {
02498    int x;
02499 
02500    if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) {
02501       x = fr->ts - iaxs[fr->callno]->last;
02502       if (x < -50000) {
02503          /* Sudden big jump backwards in timestamp:
02504             What likely happened here is that miniframe timestamp has circled but we haven't
02505             gotten the update from the main packet.  We'll just pretend that we did, and
02506             update the timestamp appropriately. */
02507          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
02508          if (option_debug && iaxdebug)
02509             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02510       }
02511       if (x > 50000) {
02512          /* Sudden apparent big jump forwards in timestamp:
02513             What's likely happened is this is an old miniframe belonging to the previous
02514             top-16-bit timestamp that has turned up out of order.
02515             Adjust the timestamp appropriately. */
02516          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
02517          if (option_debug && iaxdebug)
02518             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02519       }
02520    }
02521 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 2525 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, chan_iax2_pvt::rxcore, and sched.

Referenced by __get_from_jb(), and schedule_delivery().

02526 {
02527    int when;
02528    
02529    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02530    
02531    when = jb_next(pvt->jb) - when;
02532 
02533    AST_SCHED_DEL(sched, pvt->jbid);
02534 
02535    if(when <= 0) {
02536       /* XXX should really just empty until when > 0.. */
02537       when = 1;
02538    }
02539    
02540    pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02541 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1449 of file chan_iax2.c.

References ast_log(), LOG_DEBUG, maxnontrunkcall, option_debug, and TRUNK_CALL_START.

Referenced by __find_callno(), and make_trunk().

01450 {
01451    int max = 1;
01452    int x;
01453    /* XXX Prolly don't need locks here XXX */
01454    for (x=1;x<TRUNK_CALL_START - 1; x++) {
01455       if (iaxs[x])
01456          max = x + 1;
01457    }
01458    maxnontrunkcall = max;
01459    if (option_debug && iaxdebug)
01460       ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max);
01461 }

static void update_max_trunk ( void   )  [static]

Definition at line 1256 of file chan_iax2.c.

References ARRAY_LEN, ast_log(), LOG_DEBUG, maxtrunkcall, option_debug, and TRUNK_CALL_START.

Referenced by iax2_destroy(), and make_trunk().

01257 {
01258    int max = TRUNK_CALL_START;
01259    int x;
01260 
01261    /* XXX Prolly don't need locks here XXX */
01262    for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) {
01263       if (iaxs[x]) {
01264          max = x + 1;
01265       }
01266    }
01267 
01268    maxtrunkcall = max;
01269    if (option_debug && iaxdebug)
01270       ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max);
01271 }

static int update_packet ( struct iax_frame f  )  [static]

Definition at line 2133 of file chan_iax2.c.

References ast_iax2_full_hdr::dcallno, f, IAX_FLAG_RETRANS, iaxs, ast_iax2_full_hdr::iseqno, and chan_iax2_pvt::iseqno.

Referenced by __attempt_transmit().

02134 {
02135    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02136    struct ast_iax2_full_hdr *fh = f->data;
02137    /* Mark this as a retransmission */
02138    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02139    /* Update iseqno */
02140    f->iseqno = iaxs[f->callno]->iseqno;
02141    fh->iseqno = f->iseqno;
02142    return 0;
02143 }

static int update_registry ( struct sockaddr_in *  sin,
int  callno,
char *  devtype,
int  fd,
unsigned short  refresh 
) [static]

Precondition:
iaxsl[callno] is locked
Note:
Since this function calls send_command_final(), the pvt struct for the given call number may disappear while executing this function.

Definition at line 6124 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(), EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), globalflags, 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(), realtime_update_peer(), register_peer_exten(), sched, send_command_final(), iax2_peer::sockfd, and VERBOSE_PREFIX_3.

Referenced by socket_process().

06125 {
06126    /* Called from IAX thread only, with proper iaxsl lock */
06127    struct iax_ie_data ied;
06128    struct iax2_peer *p;
06129    int msgcount;
06130    char data[80];
06131    int version;
06132    const char *peer_name;
06133    int res = -1;
06134 
06135    memset(&ied, 0, sizeof(ied));
06136 
06137    peer_name = ast_strdupa(iaxs[callno]->peer);
06138 
06139    /* SLD: Another find_peer call during registration - this time when we are really updating our registration */
06140    ast_mutex_unlock(&iaxsl[callno]);
06141    if (!(p = find_peer(peer_name, 1))) {
06142       ast_mutex_lock(&iaxsl[callno]);
06143       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
06144       return -1;
06145    }
06146    ast_mutex_lock(&iaxsl[callno]);
06147    if (!iaxs[callno])
06148       goto return_unref;
06149 
06150    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) {
06151       if (sin->sin_addr.s_addr) {
06152          time_t nowtime;
06153          time(&nowtime);
06154          realtime_update_peer(peer_name, sin, nowtime);
06155       } else {
06156          realtime_update_peer(peer_name, sin, 0);
06157       }
06158    }
06159    if (inaddrcmp(&p->addr, sin)) {
06160       if (iax2_regfunk)
06161          iax2_regfunk(p->name, 1);
06162       /* Stash the IP address from which they registered */
06163       memcpy(&p->addr, sin, sizeof(p->addr));
06164       snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry);
06165       if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) {
06166          ast_db_put("IAX/Registry", p->name, data);
06167          if  (option_verbose > 2)
06168             ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 
06169                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
06170          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name);
06171          register_peer_exten(p, 1);
06172          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06173       } else if (!ast_test_flag(p, IAX_TEMPONLY)) {
06174          if  (option_verbose > 2)
06175             ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 
06176                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED");
06177          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name);
06178          register_peer_exten(p, 0);
06179          ast_db_del("IAX/Registry", p->name);
06180          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06181       }
06182       /* Update the host */
06183       /* Verify that the host is really there */
06184       iax2_poke_peer(p, callno);
06185    }     
06186 
06187    /* Make sure our call still exists, an INVAL at the right point may make it go away */
06188    if (!iaxs[callno]) {
06189       res = 0;
06190       goto return_unref;
06191    }
06192 
06193    /* Store socket fd */
06194    p->sockfd = fd;
06195    /* Setup the expiry */
06196    if (p->expire > -1) {
06197       if (!ast_sched_del(sched, p->expire)) {
06198          p->expire = -1;
06199          peer_unref(p);
06200       }
06201    }
06202    /* treat an unspecified refresh interval as the minimum */
06203    if (!refresh)
06204       refresh = min_reg_expire;
06205    if (refresh > max_reg_expire) {
06206       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
06207          p->name, max_reg_expire, refresh);
06208       p->expiry = max_reg_expire;
06209    } else if (refresh < min_reg_expire) {
06210       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
06211          p->name, min_reg_expire, refresh);
06212       p->expiry = min_reg_expire;
06213    } else {
06214       p->expiry = refresh;
06215    }
06216    if (p->expiry && sin->sin_addr.s_addr) {
06217       p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
06218       if (p->expire == -1)
06219          peer_unref(p);
06220    }
06221    iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
06222    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag));
06223    if (sin->sin_addr.s_addr) {
06224       iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry);
06225       iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
06226       if (!ast_strlen_zero(p->mailbox)) {
06227          int new, old;
06228          ast_app_inboxcount(p->mailbox, &new, &old);
06229          if (new > 255)
06230             new = 255;
06231          if (old > 255)
06232             old = 255;
06233          msgcount = (old << 8) | new;
06234          iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
06235       }
06236       if (ast_test_flag(p, IAX_HASCALLERID)) {
06237          iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num);
06238          iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name);
06239       }
06240    }
06241    version = iax_check_version(devtype);
06242    if (version) 
06243       iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version);
06244 
06245    res = 0;
06246 
06247 return_unref:
06248    peer_unref(p);
06249 
06250    return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
06251 }

static int user_cmp_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Note:
The only member of the user passed here guaranteed to be set is the name field

Definition at line 1128 of file chan_iax2.c.

Referenced by load_module().

01129 {
01130    struct iax2_user *user = obj, *user2 = arg;
01131 
01132    return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0;
01133 }

static int user_delme_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 9756 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09757 {
09758    struct iax2_user *user = obj;
09759 
09760    ast_set_flag(user, IAX_DELME);
09761 
09762    return 0;
09763 }

static void user_destructor ( void *  obj  )  [static]

Definition at line 9520 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().

09521 {
09522    struct iax2_user *user = obj;
09523 
09524    ast_free_ha(user->ha);
09525    free_context(user->contexts);
09526    if(user->vars) {
09527       ast_variables_destroy(user->vars);
09528       user->vars = NULL;
09529    }
09530    ast_string_field_free_memory(user);
09531 }

static int user_hash_cb ( const void *  obj,
const int  flags 
) [static]

Note:
The only member of the user passed here guaranteed to be set is the name field

Definition at line 1118 of file chan_iax2.c.

References ast_str_hash().

Referenced by load_module().

01119 {
01120    const struct iax2_user *user = obj;
01121 
01122    return ast_str_hash(user->name);
01123 }

static struct iax2_user* user_ref ( struct iax2_user user  )  [inline, static]

Definition at line 1167 of file chan_iax2.c.

References ao2_ref().

01168 {
01169    ao2_ref(user, +1);
01170    return user;
01171 }

static struct iax2_user* user_unref ( struct iax2_user user  )  [inline, static]

Definition at line 1173 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().

01174 {
01175    ao2_ref(user, -1);
01176    return NULL;
01177 }

static void vnak_retransmit ( int  callno,
int  last 
) [static]

Definition at line 6440 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, f, iaxq, iaxs, and send_packet().

Referenced by socket_process().

06441 {
06442    struct iax_frame *f;
06443 
06444    AST_LIST_LOCK(&iaxq.queue);
06445    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06446       /* Send a copy immediately */
06447       if ((f->callno == callno) && iaxs[f->callno] &&
06448          ((unsigned char ) (f->oseqno - last) < 128) &&
06449          (f->retries >= 0)) {
06450          send_packet(f);
06451       }
06452    }
06453    AST_LIST_UNLOCK(&iaxq.queue);
06454 }


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

Definition at line 215 of file chan_iax2.c.

Referenced by __oh323_new(), ast_cdr_setaccount(), begin_dial(), build_device(), build_gateway(), check_user_full(), disa_exec(), features_call(), gtalk_new(), local_call(), mgcp_new(), sip_new(), skinny_new(), tds_log(), wait_for_answer(), and zt_new().

int adsi = 0 [static]

Definition at line 219 of file chan_iax2.c.

Referenced by build_gateway().

int amaflags = 0 [static]

Definition at line 218 of file chan_iax2.c.

Referenced by build_device(), and build_gateway().

int authdebug = 1 [static]

Definition at line 155 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 156 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 10857 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

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 10837 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 10842 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 10852 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 10847 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 10832 of file chan_iax2.c.

char context[80] = "default" [static]

Definition at line 142 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 10806 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 10798 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 10790 of file chan_iax2.c.

int defaultsockfd = -1 [static]

Definition at line 172 of file chan_iax2.c.

int delayreject = 0 [static]

Definition at line 220 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 274 of file chan_iax2.c.

struct ast_flags globalflags = { 0 } [static]

Definition at line 223 of file chan_iax2.c.

Referenced by __expire_registry(), __find_callno(), aji_create_client(), aji_load_config(), build_peer(), build_user(), find_or_create(), find_user(), find_user_realtime(), forward_message(), iax2_request(), iax2_trunk_queue(), load_config(), make_email_file(), notify_new_message(), populate_defaults(), send_trunk(), sendmail(), set_config(), set_config_destroy(), socket_process(), update_registry(), and vm_execmain().

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 201 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 221 of file chan_iax2.c.

enum { ... } iax2_flags

int(*) iax2_regfunk(const char *username, int onoff) = NULL

Definition at line 174 of file chan_iax2.c.

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 10748 of file chan_iax2.c.

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10722 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

Definition at line 863 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 10814 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 822 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 450 of file chan_iax2.c.

Referenced by __unload_module(), iax2_process_thread(), and iax2_process_thread_cleanup().

int iaxcompat = 0 [static]

Definition at line 157 of file chan_iax2.c.

int iaxdebug = 0 [static]

Definition at line 203 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 159 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 161 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 449 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 448 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

struct ast_custom_function iaxpeer_function

Definition at line 10658 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

struct ast_iax2_queue iaxq [static]

Referenced by __attempt_transmit(), __unload_module(), complete_transfer(), iax2_show_stats(), iax2_transmit(), load_module(), network_thread(), pvt_destructor(), socket_process(), and vnak_retransmit().

struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static]

Definition at line 809 of file chan_iax2.c.

Referenced by __attempt_transmit(), __auth_reject(), __auto_congest(), __auto_hangup(), __do_deliver(), __get_from_jb(), __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_do_register(), iax2_dprequest(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_poke_peer(), iax2_predestroy(), iax2_prov_app(), iax2_provision(), iax2_request(), iax2_show_channels(), iax2_start_transfer(), iax2_vnak(), iax2_write(), iax_showframe(), load_module(), 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_packet(), update_registry(), and vnak_retransmit().

ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static]

Definition at line 810 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 447 of file chan_iax2.c.

Referenced by iax2_show_threads(), set_config(), and start_network_thread().

int iaxtrunkdebug = 0 [static]

Definition at line 205 of file chan_iax2.c.

struct io_context* io [static]

Definition at line 198 of file chan_iax2.c.

int lagrq_time = 10 [static]

Definition at line 150 of file chan_iax2.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 144 of file chan_iax2.c.

struct timeval lastused[ARRAY_LEN(iaxs)] [static]

Definition at line 811 of file chan_iax2.c.

int max_reg_expire [static]

Definition at line 166 of file chan_iax2.c.

int max_retries = 4 [static]

Definition at line 148 of file chan_iax2.c.

int maxauthreq = 3 [static]

Definition at line 147 of file chan_iax2.c.

int maxjitterbuffer = 1000 [static]

Definition at line 151 of file chan_iax2.c.

int maxjitterinterps = 10 [static]

Definition at line 153 of file chan_iax2.c.

int maxnontrunkcall = 1 [static]

Definition at line 829 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_nontrunk().

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 828 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_trunk().

int min_reg_expire [static]

Definition at line 165 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 216 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

Definition at line 217 of file chan_iax2.c.

Referenced by build_device(), check_user_full(), create_addr_from_peer(), and sip_alloc().

struct ast_netsock_list* netsock [static]

Definition at line 170 of file chan_iax2.c.

Referenced by __unload_module(), ast_netsock_destroy(), load_module(), peer_set_srcaddr(), and set_config().

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 225 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 10810 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 10802 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 10794 of file chan_iax2.c.

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 171 of file chan_iax2.c.

Referenced by __unload_module(), load_module(), peer_set_srcaddr(), and set_config().

char* papp = "IAX2Provision" [static]

Definition at line 8763 of file chan_iax2.c.

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 8765 of file chan_iax2.c.

struct ao2_container* peers [static]

Definition at line 647 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(), register_request(), set_config(), socket_read(), unlink_peer(), and unregister_request().

int ping_time = 21 [static]

Definition at line 149 of file chan_iax2.c.

struct ast_codec_pref prefs [static]

Definition at line 138 of file chan_iax2.c.

Referenced by ast_best_codec(), ast_rtp_codec_setpref(), build_peer(), build_user(), check_access(), create_addr(), gtalk_create_member(), gtalk_load_config(), new_iax(), set_config(), set_local_capabilities(), and set_peer_capabilities().

char prune_realtime_usage[] [static]

Initial value:

"Usage: iax2 prune realtime [<peername>|all]\n"
"       Prunes object(s) from the cache\n"

Definition at line 10744 of file chan_iax2.c.

char* psyn = "Provision a calling IAXy with a given template" [static]

Definition at line 8764 of file chan_iax2.c.

char regcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 145 of file chan_iax2.c.

int resyncthreshold = 1000 [static]

Definition at line 152 of file chan_iax2.c.

struct sched_context* sched [static]

Definition at line 199 of file chan_iax2.c.

ast_cond_t sched_cond [static]

Definition at line 228 of file chan_iax2.c.

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 226 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 10736 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 10764 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 10782 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 10768 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 10740 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 10776 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10752 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 10786 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 10732 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 10772 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 10759 of file chan_iax2.c.

const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)" [static]

Definition at line 140 of file chan_iax2.c.

int test_losspct = 0 [static]

Definition at line 207 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 168 of file chan_iax2.c.

unsigned int tos = 0 [static]

Definition at line 163 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 154 of file chan_iax2.c.

struct ao2_container* users [static]

Definition at line 650 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(), 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().


Generated on Tue Nov 4 13:20:30 2008 for Asterisk - the Open Source PBX by  doxygen 1.4.7