Thu Oct 8 21:57:38 2009

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) }
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, struct chan_iax2_pvt *pvt)
static int authenticate_reply (struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, const char *override, const char *okey)
static int authenticate_request (int call_num)
static int authenticate_verify (struct chan_iax2_pvt *p, struct iax_ies *ies)
static int auto_congest (const void *data)
static int auto_hangup (const void *data)
static struct iax2_contextbuild_context (char *context)
static void build_ecx_key (const unsigned char *digest, struct chan_iax2_pvt *pvt)
static void build_encryption_keys (const unsigned char *digest, struct chan_iax2_pvt *pvt)
static struct iax2_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
struct 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 int last_authmethod = 0
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 668 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 664 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 678 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 666 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 670 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 672 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

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

Referenced by complete_dpreply(), and iax2_show_cache().

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

Definition at line 126 of file chan_iax2.c.

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

#define DEBUG_SCHED_MULTITHREAD

Definition at line 114 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 134 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 132 of file chan_iax2.c.

#define DEFAULT_FREQ_NOTOK   10 * 1000

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

Referenced by build_peer(), and handle_response_peerpoke().

#define DEFAULT_MAX_THREAD_COUNT   100

Definition at line 129 of file chan_iax2.c.

#define DEFAULT_MAXMS   2000

Definition at line 198 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

Definition at line 130 of file chan_iax2.c.

Referenced by __find_callno(), and complete_transfer().

#define DEFAULT_THREAD_COUNT   10

Definition at line 128 of file chan_iax2.c.

#define DEFAULT_TRUNKDATA   640 * 10

40ms, uncompressed linear * 10 channels

Definition at line 442 of file chan_iax2.c.

Referenced by iax2_trunk_queue().

#define FORMAT   "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n"

#define FORMAT   "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n"

#define FORMAT   "%-15.15s %-15d %-15d\n"

#define FORMAT   "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s"

#define FORMAT   "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n"

#define FORMAT2   "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n"

#define FORMAT2   "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n"

#define FORMAT2   "%-15.15s %-15.15s %-15.15s\n"

#define FORMAT2   "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s"

#define FORMAT2   "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n"

#define FORMATB   "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n"

#define GAMMA   (0.01)

Definition at line 139 of file chan_iax2.c.

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

Definition at line 363 of file chan_iax2.c.

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF

Definition at line 181 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 189 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 194 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 183 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 699 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 701 of file chan_iax2.c.

Referenced by iax2_process_thread().

#define IAX_IOSTATE_READY   1

Definition at line 700 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 702 of file chan_iax2.c.

Referenced by __schedule_action(), and iax2_process_thread().

#define IAX_TYPE_DYNAMIC   2

#define IAX_TYPE_POOL   1

Definition at line 704 of file chan_iax2.c.

Referenced by start_network_thread().

#define IPTOS_MINCOST   0x02

Definition at line 117 of file chan_iax2.c.

#define MAX_JITTER_BUFFER   50

Definition at line 439 of file chan_iax2.c.

#define MAX_PEER_BUCKETS   1

This module will get much higher performance when doing a lot of user and peer lookups if the number of buckets is increased from 1. However, to maintain old behavior for Asterisk 1.4, these are set to 1 by default. When using multiple buckets, search order through these containers is considered random, so you will not be able to depend on the order the entires are specified in iax.conf for matching order.

Definition at line 650 of file chan_iax2.c.

Referenced by load_module(), and set_config().

#define MAX_RETRY_TIME   10000

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

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 443 of file chan_iax2.c.

Referenced by iax2_trunk_queue(), and timing_read().

#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS

Definition at line 655 of file chan_iax2.c.

Referenced by load_module().

#define MEMORY_SIZE   100

Definition at line 131 of file chan_iax2.c.

#define MIN_JITTER_BUFFER   10

Definition at line 440 of file chan_iax2.c.

#define MIN_RETRY_TIME   100

Definition at line 436 of file chan_iax2.c.

Referenced by iax2_send().

#define MIN_REUSE_TIME   60

Definition at line 136 of file chan_iax2.c.

Referenced by __find_callno(), and make_trunk().

#define NEW_ALLOW   1

Definition at line 1436 of file chan_iax2.c.

Referenced by __find_callno(), and socket_process().

#define NEW_FORCE   2

#define NEW_PREVENT   0

Definition at line 1435 of file chan_iax2.c.

Referenced by socket_process().

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

#define SCHED_MULTITHREADED

Definition at line 110 of file chan_iax2.c.

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

#define TRUNK_CALL_START   ARRAY_LEN(iaxs) / 2

Definition at line 832 of file chan_iax2.c.

Referenced by __find_callno(), make_trunk(), update_max_nontrunk(), and update_max_trunk().

#define TS_GAP_FOR_JB_RESYNC   5000

Definition at line 448 of file chan_iax2.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
IAX_STATE_STARTED 
IAX_STATE_AUTHENTICATED 
IAX_STATE_TBD 

Definition at line 234 of file chan_iax2.c.

00234      {
00235    IAX_STATE_STARTED =        (1 << 0),
00236    IAX_STATE_AUTHENTICATED =  (1 << 1),
00237    IAX_STATE_TBD =            (1 << 2),
00238 } 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 245 of file chan_iax2.c.

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

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

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


Function Documentation

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

Definition at line 2167 of file chan_iax2.c.

References chan_iax2_pvt::addr, iax_frame::af, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, iax2_registry::callno, chan_iax2_pvt::error, f, iax_frame::final, ast_frame::frametype, ast_channel::hangupcause, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), iax2_sched_add(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iaxq, iaxs, iaxsl, LOG_WARNING, MAX_RETRY_TIME, iax_frame::oseqno, chan_iax2_pvt::owner, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_TIMEOUT, iax2_registry::regstate, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_command(), send_packet(), ast_frame::subclass, iax_frame::transfer, iax_frame::ts, update_packet(), and iax2_registry::us.

Referenced by attempt_transmit().

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

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

Definition at line 6425 of file chan_iax2.c.

References AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_FACILITY_REJECTED, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax_ie_data::buf, iax2_registry::callno, IAX_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, iax_ie_data::pos, and send_command_final().

Referenced by auth_reject().

06426 {
06427    /* Called from IAX thread only, without iaxs lock */
06428    int callno = (int)(long)(nothing);
06429    struct iax_ie_data ied;
06430    ast_mutex_lock(&iaxsl[callno]);
06431    if (iaxs[callno]) {
06432       memset(&ied, 0, sizeof(ied));
06433       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
06434          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
06435          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
06436       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
06437          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
06438          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
06439       }
06440       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
06441    }
06442    ast_mutex_unlock(&iaxsl[callno]);
06443 }

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

Definition at line 3122 of file chan_iax2.c.

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

Referenced by auto_congest().

03123 {
03124    int callno = PTR_TO_CALLNO(nothing);
03125    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
03126    ast_mutex_lock(&iaxsl[callno]);
03127    if (iaxs[callno]) {
03128       iaxs[callno]->initid = -1;
03129       iax2_queue_frame(callno, &f);
03130       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
03131    }
03132    ast_mutex_unlock(&iaxsl[callno]);
03133 }

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

Definition at line 6474 of file chan_iax2.c.

References AST_CAUSE_NO_USER_RESPONSE, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax_ie_data::buf, iax2_registry::callno, IAX_COMMAND_HANGUP, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, iax_ie_data::pos, and send_command_final().

Referenced by auto_hangup().

06475 {
06476    /* Called from IAX thread only, without iaxs lock */
06477    int callno = (int)(long)(nothing);
06478    struct iax_ie_data ied;
06479    ast_mutex_lock(&iaxsl[callno]);
06480    if (iaxs[callno]) {
06481       memset(&ied, 0, sizeof(ied));
06482       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
06483       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
06484       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
06485    }
06486    ast_mutex_unlock(&iaxsl[callno]);
06487 }

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

02024 {
02025    /* Just deliver the packet by using queueing.  This is called by
02026      the IAX thread with the iaxsl lock held. */
02027    struct iax_frame *fr = data;
02028    fr->retrans = -1;
02029    ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO);
02030    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
02031       iax2_queue_frame(fr->callno, &fr->af);
02032    /* Free our iax frame */
02033    iax2_frame_free(fr);
02034    /* And don't run again */
02035    return 0;
02036 }

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

Definition at line 6104 of file chan_iax2.c.

References iax2_peer::addr, ast_db_del(), ast_device_state_changed(), ast_log(), ast_test_flag, EVENT_FLAG_SYSTEM, iax2_peer::expire, iax2_peer::expiry, iax2_regfunk, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, LOG_DEBUG, manager_event(), option_debug, peer_unref(), realtime_update_peer(), register_peer_exten(), and unlink_peer().

Referenced by expire_registry().

06105 {
06106    struct iax2_peer *peer = (struct iax2_peer *) data;
06107 
06108    if (!peer)
06109       return;
06110 
06111    peer->expire = -1;
06112 
06113    if (option_debug)
06114       ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name);
06115    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
06116       realtime_update_peer(peer->name, &peer->addr, 0);
06117    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
06118    /* Reset the address */
06119    memset(&peer->addr, 0, sizeof(peer->addr));
06120    /* Reset expiry value */
06121    peer->expiry = min_reg_expire;
06122    if (!ast_test_flag(peer, IAX_TEMPONLY))
06123       ast_db_del("IAX/Registry", peer->name);
06124    register_peer_exten(peer, 0);
06125    ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
06126    if (iax2_regfunk)
06127       iax2_regfunk(peer->name, 0);
06128 
06129    if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
06130       unlink_peer(peer);
06131 
06132    peer_unref(peer);
06133 }

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

References chan_iax2_pvt::addr, chan_iax2_pvt::amaflags, ao2_find(), ao2_ref(), ast_copy_flags, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_string_field_set, chan_iax2_pvt::callno, DEFAULT_RETRY_TIME, chan_iax2_pvt::expiry, iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, iax_peercallno_pvts, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, match(), maxnontrunkcall, maxtrunkcall, MIN_REUSE_TIME, NEW_ALLOW, new_iax(), option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, chan_iax2_pvt::pingtime, send_lagrq(), send_ping(), chan_iax2_pvt::sockfd, store_by_peercallno(), TRUNK_CALL_START, and update_max_nontrunk().

Referenced by find_callno(), and find_callno_locked().

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

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

Definition at line 2564 of file chan_iax2.c.

References __do_deliver(), ast_codec_interp_len(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_tvadd(), iax2_registry::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, iaxs, iaxsl, chan_iax2_pvt::jb, JB_DROP, JB_EMPTY, jb_get(), JB_INTERP, jb_next(), JB_NOFRAME, JB_OK, chan_iax2_pvt::jbid, jb_frame::ms, ast_frame::offset, PTR_TO_CALLNO, chan_iax2_pvt::rxcore, ast_frame::samples, ast_frame::src, ast_frame::subclass, update_jbsched(), and chan_iax2_pvt::voiceformat.

Referenced by get_from_jb().

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

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

Definition at line 5797 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05798 {
05799    struct iax2_registry *reg = (struct iax2_registry *)data;
05800    reg->expire = -1;
05801    iax2_do_register(reg);
05802 }

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

Definition at line 8908 of file chan_iax2.c.

References ast_device_state_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_peer::callno, iax2_registry::callno, EVENT_FLAG_SYSTEM, iax2_destroy(), iax2_poke_peer_s(), iax2_sched_add(), iaxsl, iax2_peer::lastms, LOG_NOTICE, manager_event(), peer_ref(), peer_unref(), iax2_peer::pokeexpire, and iax2_peer::pokefreqnotok.

Referenced by iax2_poke_noanswer().

08909 {
08910    struct iax2_peer *peer = (struct iax2_peer *)data;
08911    int callno;
08912 
08913    if (peer->lastms > -1) {
08914       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08915       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08916       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08917    }
08918    if ((callno = peer->callno) > 0) {
08919       ast_mutex_lock(&iaxsl[callno]);
08920       iax2_destroy(callno);
08921       ast_mutex_unlock(&iaxsl[callno]);
08922    }
08923    peer->callno = 0;
08924    peer->lastms = -1;
08925    /* Try again quickly */
08926    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
08927    if (peer->pokeexpire == -1)
08928       peer_unref(peer);
08929 }

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

Definition at line 6537 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06538 {
06539    struct iax2_peer *peer = (struct iax2_peer *)data;
06540    iax2_poke_peer(peer, 0);
06541    peer_unref(peer);
06542 }

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

Definition at line 4551 of file chan_iax2.c.

References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_cli(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), iax2_peer::encmethods, FORMAT, FORMAT2, IAX_DYNAMIC, IAX_TRUNK, iax2_peer::mask, name, peer_status(), peer_unref(), peers, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

Referenced by iax2_show_peers(), and manager_iax2_show_peers().

04552 {
04553    regex_t regexbuf;
04554    int havepattern = 0;
04555    int total_peers = 0;
04556    int online_peers = 0;
04557    int offline_peers = 0;
04558    int unmonitored_peers = 0;
04559    struct ao2_iterator i;
04560 
04561 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
04562 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
04563 
04564    struct iax2_peer *peer = NULL;
04565    char name[256];
04566    int registeredonly=0;
04567    char *term = manager ? "\r\n" : "\n";
04568 
04569    switch (argc) {
04570    case 6:
04571       if (!strcasecmp(argv[3], "registered"))
04572          registeredonly = 1;
04573       else
04574          return RESULT_SHOWUSAGE;
04575       if (!strcasecmp(argv[4], "like")) {
04576          if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
04577             return RESULT_SHOWUSAGE;
04578          havepattern = 1;
04579       } else
04580          return RESULT_SHOWUSAGE;
04581       break;
04582    case 5:
04583       if (!strcasecmp(argv[3], "like")) {
04584          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04585             return RESULT_SHOWUSAGE;
04586          havepattern = 1;
04587       } else
04588          return RESULT_SHOWUSAGE;
04589       break;
04590    case 4:
04591       if (!strcasecmp(argv[3], "registered"))
04592          registeredonly = 1;
04593       else
04594          return RESULT_SHOWUSAGE;
04595       break;
04596    case 3:
04597       break;
04598    default:
04599       return RESULT_SHOWUSAGE;
04600    }
04601 
04602 
04603    if (s)
04604       astman_append(s, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04605    else
04606       ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04607 
04608    i = ao2_iterator_init(peers, 0);
04609    for (peer = ao2_iterator_next(&i); peer; 
04610       peer_unref(peer), peer = ao2_iterator_next(&i)) {
04611       char nm[20];
04612       char status[20];
04613       char srch[2000];
04614       int retstatus;
04615 
04616       if (registeredonly && !peer->addr.sin_addr.s_addr)
04617          continue;
04618       if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0))
04619          continue;
04620 
04621       if (!ast_strlen_zero(peer->username))
04622          snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
04623       else
04624          ast_copy_string(name, peer->name, sizeof(name));
04625       
04626       retstatus = peer_status(peer, status, sizeof(status));
04627       if (retstatus > 0)
04628          online_peers++;
04629       else if (!retstatus)
04630          offline_peers++;
04631       else
04632          unmonitored_peers++;
04633       
04634       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
04635       
04636       snprintf(srch, sizeof(srch), FORMAT, name, 
04637           peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04638           ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04639           nm,
04640           ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04641           peer->encmethods ? "(E)" : "   ", status, term);
04642       
04643       if (s)
04644          astman_append(s, FORMAT, name, 
04645                   peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)",
04646                   ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04647                   nm,
04648                   ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04649                   peer->encmethods ? "(E)" : "   ", status, term);
04650       else
04651          ast_cli(fd, FORMAT, name, 
04652             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04653             ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04654             nm,
04655             ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04656             peer->encmethods ? "(E)" : "   ", status, term);
04657       total_peers++;
04658    }
04659 
04660    if (s)
04661       astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04662    else
04663       ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04664 
04665    if (havepattern)
04666       regfree(&regexbuf);
04667 
04668    return RESULT_SUCCESS;
04669 #undef FORMAT
04670 #undef FORMAT2
04671 }

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

Definition at line 965 of file chan_iax2.c.

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

00966 {
00967    struct iax2_thread *thread = NULL;
00968    static time_t lasterror;
00969    static time_t t;
00970 
00971    thread = find_idle_thread();
00972 
00973    if (thread != NULL) {
00974       thread->schedfunc = func;
00975       thread->scheddata = data;
00976       thread->iostate = IAX_IOSTATE_SCHEDREADY;
00977 #ifdef DEBUG_SCHED_MULTITHREAD
00978       ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc));
00979 #endif
00980       signal_condition(&thread->lock, &thread->cond);
00981       return 0;
00982    }
00983    time(&t);
00984    if (t != lasterror && option_debug) 
00985       ast_log(LOG_DEBUG, "Out of idle IAX2 threads for scheduling!\n");
00986    lasterror = t;
00987 
00988    return -1;
00989 }

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

References ast_frame::data, ast_frame::datalen, ast_frame::frametype, iax2_send(), ast_frame::src, and ast_frame::subclass.

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

05054 {
05055    struct ast_frame f = { 0, };
05056 
05057    f.frametype = type;
05058    f.subclass = command;
05059    f.datalen = datalen;
05060    f.src = __FUNCTION__;
05061    f.data = (void *) data;
05062 
05063    return iax2_send(i, &f, ts, seqno, now, transfer, final);
05064 }

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

Definition at line 1045 of file chan_iax2.c.

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

Referenced by send_lagrq().

01046 {
01047    int callno = (long) data;
01048 
01049    ast_mutex_lock(&iaxsl[callno]);
01050 
01051    while (iaxs[callno] && iaxs[callno]->lagid > -1) {
01052       if (iaxs[callno]->peercallno) {
01053          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
01054       }
01055       iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
01056       break;
01057    }
01058 
01059    ast_mutex_unlock(&iaxsl[callno]);
01060 }

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

Definition at line 1005 of file chan_iax2.c.

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

Referenced by send_ping().

01006 {
01007    int callno = (long) data;
01008 
01009    ast_mutex_lock(&iaxsl[callno]);
01010 
01011    while (iaxs[callno] && iaxs[callno]->pingid != -1) {
01012       if (iaxs[callno]->peercallno) {
01013          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
01014       }
01015       iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
01016       break;
01017    }
01018 
01019    ast_mutex_unlock(&iaxsl[callno]);
01020 }

static int __unload_module ( void   )  [static]

Definition at line 11035 of file chan_iax2.c.

References ao2_ref(), ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_signal(), AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_release(), AST_PTHREADT_NULL, ast_unregister_application(), ast_unregister_switch(), cli_iax2, delete_users(), iax2_destroy(), iax2_switch, iax2_tech, iax_peercallno_pvts, iax_provision_unload(), iaxactivethreadcount, iaxq, iaxs, iaxsl, ast_firmware_list::lock, papp, peers, reload_firmware(), sched_context_destroy(), thread, users, and waresl.

Referenced by load_module(), and unload_module().

11036 {
11037    struct iax2_thread *thread = NULL;
11038    int x;
11039 
11040    /* Make sure threads do not hold shared resources when they are canceled */
11041    
11042    /* Grab the sched lock resource to keep it away from threads about to die */
11043    /* Cancel the network thread, close the net socket */
11044    if (netthreadid != AST_PTHREADT_NULL) {
11045       AST_LIST_LOCK(&iaxq.queue);
11046       ast_mutex_lock(&sched_lock);
11047       pthread_cancel(netthreadid);
11048       ast_cond_signal(&sched_cond);
11049       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
11050       AST_LIST_UNLOCK(&iaxq.queue);
11051       pthread_join(netthreadid, NULL);
11052    }
11053    if (schedthreadid != AST_PTHREADT_NULL) {
11054       ast_mutex_lock(&sched_lock);  
11055       pthread_cancel(schedthreadid);
11056       ast_cond_signal(&sched_cond);
11057       ast_mutex_unlock(&sched_lock);   
11058       pthread_join(schedthreadid, NULL);
11059    }
11060    
11061    /* Call for all threads to halt */
11062    AST_LIST_LOCK(&idle_list);
11063    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
11064       AST_LIST_REMOVE_CURRENT(&idle_list, list);
11065       pthread_cancel(thread->threadid);
11066    }
11067    AST_LIST_TRAVERSE_SAFE_END
11068    AST_LIST_UNLOCK(&idle_list);
11069 
11070    AST_LIST_LOCK(&active_list);
11071    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
11072       AST_LIST_REMOVE_CURRENT(&active_list, list);
11073       pthread_cancel(thread->threadid);
11074    }
11075    AST_LIST_TRAVERSE_SAFE_END
11076    AST_LIST_UNLOCK(&active_list);
11077 
11078    AST_LIST_LOCK(&dynamic_list);
11079         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
11080       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
11081       pthread_cancel(thread->threadid);
11082         }
11083    AST_LIST_TRAVERSE_SAFE_END
11084         AST_LIST_UNLOCK(&dynamic_list);
11085 
11086    AST_LIST_HEAD_DESTROY(&iaxq.queue);
11087 
11088    /* Wait for threads to exit */
11089    while(0 < iaxactivethreadcount)
11090       usleep(10000);
11091    
11092    ast_netsock_release(netsock);
11093    ast_netsock_release(outsock);
11094    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
11095       if (iaxs[x]) {
11096          iax2_destroy(x);
11097       }
11098    }
11099    ast_manager_unregister( "IAXpeers" );
11100    ast_manager_unregister( "IAXnetstats" );
11101    ast_unregister_application(papp);
11102    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
11103    ast_unregister_switch(&iax2_switch);
11104    ast_channel_unregister(&iax2_tech);
11105    delete_users();
11106    iax_provision_unload();
11107    sched_context_destroy(sched);
11108    reload_firmware(1);
11109 
11110    ast_mutex_destroy(&waresl.lock);
11111 
11112    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11113       ast_mutex_destroy(&iaxsl[x]);
11114    }
11115 
11116    ao2_ref(peers, -1);
11117    ao2_ref(users, -1);
11118    ao2_ref(iax_peercallno_pvts, -1);
11119 
11120    return 0;
11121 }

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

Definition at line 5105 of file chan_iax2.c.

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

Referenced by check_access().

05106 {
05107    while(con) {
05108       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
05109          return -1;
05110       con = con->next;
05111    }
05112    return 0;
05113 }

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

Definition at line 4879 of file chan_iax2.c.

References ARRAY_LEN, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, astman_append(), jb_info::current, iax_rr::delay, iax_rr::dropped, fmt, jb_info::frames_dropped, jb_info::frames_lost, jb_info::frames_ooo, chan_iax2_pvt::frames_received, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), iax_rr::jitter, jb_info::jitter, iax_rr::losscnt, iax_rr::losspct, jb_info::losspct, jb_info::min, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::pingtime, and chan_iax2_pvt::remote_rr.

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

04880 {
04881    int x;
04882    int numchans = 0;
04883    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04884       ast_mutex_lock(&iaxsl[x]);
04885       if (iaxs[x]) {
04886          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04887          char *fmt;
04888          jb_info jbinfo;
04889          
04890          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04891             jb_getinfo(iaxs[x]->jb, &jbinfo);
04892             localjitter = jbinfo.jitter;
04893             localdelay = jbinfo.current - jbinfo.min;
04894             locallost = jbinfo.frames_lost;
04895             locallosspct = jbinfo.losspct/1000;
04896             localdropped = jbinfo.frames_dropped;
04897             localooo = jbinfo.frames_ooo;
04898          } else {
04899             localjitter = -1;
04900             localdelay = 0;
04901             locallost = -1;
04902             locallosspct = -1;
04903             localdropped = 0;
04904             localooo = -1;
04905          }
04906          if (limit_fmt)
04907             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04908          else
04909             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04910          if (s)
04911             
04912             astman_append(s, fmt,
04913                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04914                      iaxs[x]->pingtime,
04915                      localjitter, 
04916                      localdelay,
04917                      locallost,
04918                      locallosspct,
04919                      localdropped,
04920                      localooo,
04921                      iaxs[x]->frames_received/1000,
04922                      iaxs[x]->remote_rr.jitter,
04923                      iaxs[x]->remote_rr.delay,
04924                      iaxs[x]->remote_rr.losscnt,
04925                      iaxs[x]->remote_rr.losspct,
04926                      iaxs[x]->remote_rr.dropped,
04927                      iaxs[x]->remote_rr.ooo,
04928                      iaxs[x]->remote_rr.packets/1000);
04929          else
04930             ast_cli(fd, fmt,
04931                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04932                iaxs[x]->pingtime,
04933                localjitter, 
04934                localdelay,
04935                locallost,
04936                locallosspct,
04937                localdropped,
04938                localooo,
04939                iaxs[x]->frames_received/1000,
04940                iaxs[x]->remote_rr.jitter,
04941                iaxs[x]->remote_rr.delay,
04942                iaxs[x]->remote_rr.losscnt,
04943                iaxs[x]->remote_rr.losspct,
04944                iaxs[x]->remote_rr.dropped,
04945                iaxs[x]->remote_rr.ooo,
04946                iaxs[x]->remote_rr.packets/1000
04947                );
04948          numchans++;
04949       }
04950       ast_mutex_unlock(&iaxsl[x]);
04951    }
04952    return numchans;
04953 }

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

Create new call, interface with the PBX core.

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

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

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

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02249 {
02250 #ifdef SCHED_MULTITHREADED
02251    if (schedule_action(__attempt_transmit, data))
02252 #endif      
02253       __attempt_transmit(data);
02254    return 0;
02255 }

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

Definition at line 6459 of file chan_iax2.c.

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

Referenced by socket_process().

06460 {
06461    /* Schedule sending the authentication failure in one second, to prevent
06462       guessing */
06463    if (iaxs[callno]) {
06464       iaxs[callno]->authfail = failcode;
06465       if (delayreject) {
06466          AST_SCHED_DEL(sched, iaxs[callno]->authid);
06467          iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06468       } else
06469          auth_reject((void *)(long)callno);
06470    }
06471    return 0;
06472 }

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

Definition at line 6445 of file chan_iax2.c.

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

Referenced by auth_fail().

06446 {
06447    int callno = (int)(long)(data);
06448    ast_mutex_lock(&iaxsl[callno]);
06449    if (iaxs[callno])
06450       iaxs[callno]->authid = -1;
06451    ast_mutex_unlock(&iaxsl[callno]);
06452 #ifdef SCHED_MULTITHREADED
06453    if (schedule_action(__auth_reject, data))
06454 #endif      
06455       __auth_reject(data);
06456    return 0;
06457 }

static int authenticate ( const char *  challenge,
const char *  secret,
const char *  keyn,
int  authmethods,
struct iax_ie_data ied,
struct sockaddr_in *  sin,
struct chan_iax2_pvt pvt 
) [static]

Definition at line 5665 of file chan_iax2.c.

References ast_inet_ntoa(), ast_key_get, AST_KEY_PRIVATE, ast_log(), ast_sign, ast_strlen_zero(), build_encryption_keys(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, iax_ie_append_str(), IAX_IE_MD5_RESULT, IAX_IE_PASSWORD, IAX_IE_RSA_RESULT, LOG_NOTICE, MD5Final(), MD5Init(), and MD5Update().

05666 {
05667    int res = -1;
05668    int x;
05669    if (!ast_strlen_zero(keyn)) {
05670       if (!(authmethods & IAX_AUTH_RSA)) {
05671          if (ast_strlen_zero(secret)) 
05672             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));
05673       } else if (ast_strlen_zero(challenge)) {
05674          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
05675       } else {
05676          char sig[256];
05677          struct ast_key *key;
05678          key = ast_key_get(keyn, AST_KEY_PRIVATE);
05679          if (!key) {
05680             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
05681          } else {
05682             if (ast_sign(key, (char*)challenge, sig)) {
05683                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
05684                res = -1;
05685             } else {
05686                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
05687                res = 0;
05688             }
05689          }
05690       }
05691    } 
05692    /* Fall back */
05693    if (res && !ast_strlen_zero(secret)) {
05694       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
05695          struct MD5Context md5;
05696          unsigned char digest[16];
05697          char digres[128];
05698          MD5Init(&md5);
05699          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
05700          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
05701          MD5Final(digest, &md5);
05702          /* If they support md5, authenticate with it.  */
05703          for (x=0;x<16;x++)
05704             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
05705          if (pvt) {
05706             build_encryption_keys(digest, pvt);
05707          }
05708          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
05709          res = 0;
05710       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
05711          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
05712          res = 0;
05713       } else
05714          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
05715    }
05716    return res;
05717 }

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

References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), authenticate(), iax_ies::authmethods, iax2_peer::authmethods, iax_ie_data::buf, chan_iax2_pvt::callno, iax2_registry::callno, iax_ies::challenge, chan_iax2_pvt::encmethods, iax_ies::encmethods, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, iaxs, iaxsl, iax2_peer::mask, merge_encryption(), peer_unref(), peers, iax_ie_data::pos, realtime_peer(), send_command(), and iax_ies::username.

Referenced by socket_process().

05724 {
05725    struct iax2_peer *peer = NULL;
05726    /* Start pessimistic */
05727    int res = -1;
05728    int authmethods = 0;
05729    struct iax_ie_data ied;
05730    uint16_t callno = p->callno;
05731 
05732    memset(&ied, 0, sizeof(ied));
05733    
05734    if (ies->username)
05735       ast_string_field_set(p, username, ies->username);
05736    if (ies->challenge)
05737       ast_string_field_set(p, challenge, ies->challenge);
05738    if (ies->authmethods)
05739       authmethods = ies->authmethods;
05740    if (authmethods & IAX_AUTH_MD5)
05741       merge_encryption(p, ies->encmethods);
05742    else
05743       p->encmethods = 0;
05744 
05745    /* Check for override RSA authentication first */
05746    if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) {
05747       /* Normal password authentication */
05748       res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, p);
05749    } else {
05750       struct ao2_iterator i = ao2_iterator_init(peers, 0);
05751       while ((peer = ao2_iterator_next(&i))) {
05752          if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
05753              /* No peer specified at our end, or this is the peer */
05754              && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
05755              /* No username specified in peer rule, or this is the right username */
05756              && (!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)))
05757              /* No specified host, or this is our host */
05758             ) {
05759             res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, p);
05760             if (!res) {
05761                peer_unref(peer);
05762                break;
05763             }
05764          }
05765          peer_unref(peer);
05766       }
05767       if (!peer) {
05768          /* We checked our list and didn't find one.  It's unlikely, but possible, 
05769             that we're trying to authenticate *to* a realtime peer */
05770          const char *peer_name = ast_strdupa(p->peer);
05771          ast_mutex_unlock(&iaxsl[callno]);
05772          if ((peer = realtime_peer(peer_name, NULL))) {
05773             ast_mutex_lock(&iaxsl[callno]);
05774             if (!(p = iaxs[callno])) {
05775                peer_unref(peer);
05776                return -1;
05777             }
05778             res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, p);
05779             peer_unref(peer);
05780          }
05781          if (!peer) {
05782             ast_mutex_lock(&iaxsl[callno]);
05783             if (!(p = iaxs[callno]))
05784                return -1;
05785          }
05786       }
05787    }
05788    if (ies->encmethods)
05789       ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
05790    if (!res)
05791       res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);
05792    return res;
05793 }

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

References ao2_find(), AST_CAUSE_CALL_REJECTED, AST_FRAME_IAX, ast_random(), ast_set_flag, ast_string_field_set, ast_test_flag, chan_iax2_pvt::authmethods, iax_ie_data::buf, iax2_user::curauthreq, chan_iax2_pvt::encmethods, IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_AUTHREQ, IAX_COMMAND_REJECT, IAX_ENCRYPTED, iax_ie_append_byte(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_ENCRYPTION, IAX_IE_USERNAME, IAX_MAXAUTHREQ, iaxs, iax2_user::maxauthreq, iax_ie_data::pos, send_command(), send_command_final(), user_unref(), and users.

Referenced by socket_process().

05378 {
05379    struct iax_ie_data ied;
05380    int res = -1, authreq_restrict = 0;
05381    char challenge[10];
05382    struct chan_iax2_pvt *p = iaxs[call_num];
05383 
05384    memset(&ied, 0, sizeof(ied));
05385 
05386    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
05387    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05388       struct iax2_user *user, tmp_user = {
05389          .name = p->username, 
05390       };
05391 
05392       user = ao2_find(users, &tmp_user, OBJ_POINTER);
05393       if (user) {
05394          if (user->curauthreq == user->maxauthreq)
05395             authreq_restrict = 1;
05396          else
05397             user->curauthreq++;
05398          user = user_unref(user);
05399       }
05400    }
05401 
05402    /* If the AUTHREQ limit test failed, send back an error */
05403    if (authreq_restrict) {
05404       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
05405       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
05406       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
05407       return 0;
05408    }
05409 
05410    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
05411    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
05412       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
05413       ast_string_field_set(p, challenge, challenge);
05414       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
05415       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
05416    }
05417    if (p->encmethods)
05418       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
05419 
05420    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
05421 
05422    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
05423 
05424    if (p->encmethods)
05425       ast_set_flag(p, IAX_ENCRYPTED);
05426 
05427    return res;
05428 }

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

Definition at line 5430 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, chan_iax2_pvt::authrej, iax2_user::curauthreq, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_MAXAUTHREQ, IAX_STATE_AUTHENTICATED, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, iax_ies::rsa_result, iax2_registry::secret, chan_iax2_pvt::state, strsep(), user_unref(), and users.

Referenced by socket_process().

05431 {
05432    char requeststr[256];
05433    char md5secret[256] = "";
05434    char secret[256] = "";
05435    char rsasecret[256] = "";
05436    int res = -1; 
05437    int x;
05438    struct iax2_user *user, tmp_user = {
05439       .name = p->username, 
05440    };
05441 
05442    if (p->authrej) {
05443       return res;
05444    }
05445    user = ao2_find(users, &tmp_user, OBJ_POINTER);
05446    if (user) {
05447       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05448          ast_atomic_fetchadd_int(&user->curauthreq, -1);
05449          ast_clear_flag(p, IAX_MAXAUTHREQ);
05450       }
05451       ast_string_field_set(p, host, user->name);
05452       user = user_unref(user);
05453    }
05454 
05455    if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
05456       return res;
05457    if (ies->password)
05458       ast_copy_string(secret, ies->password, sizeof(secret));
05459    if (ies->md5_result)
05460       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05461    if (ies->rsa_result)
05462       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05463    if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) {
05464       struct ast_key *key;
05465       char *keyn;
05466       char tmpkey[256];
05467       char *stringp=NULL;
05468       ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey));
05469       stringp=tmpkey;
05470       keyn = strsep(&stringp, ":");
05471       while(keyn) {
05472          key = ast_key_get(keyn, AST_KEY_PUBLIC);
05473          if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
05474             res = 0;
05475             break;
05476          } else if (!key)
05477             ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
05478          keyn = strsep(&stringp, ":");
05479       }
05480    } else if (p->authmethods & IAX_AUTH_MD5) {
05481       struct MD5Context md5;
05482       unsigned char digest[16];
05483       char *tmppw, *stringp;
05484       
05485       tmppw = ast_strdupa(p->secret);
05486       stringp = tmppw;
05487       while((tmppw = strsep(&stringp, ";"))) {
05488          MD5Init(&md5);
05489          MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge));
05490          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05491          MD5Final(digest, &md5);
05492          /* If they support md5, authenticate with it.  */
05493          for (x=0;x<16;x++)
05494             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05495          if (!strcasecmp(requeststr, md5secret)) {
05496             res = 0;
05497             break;
05498          }
05499       }
05500    } else if (p->authmethods & IAX_AUTH_PLAINTEXT) {
05501       if (!strcmp(secret, p->secret))
05502          res = 0;
05503    }
05504    return res;
05505 }

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

Definition at line 3135 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

03136 {
03137 #ifdef SCHED_MULTITHREADED
03138    if (schedule_action(__auto_congest, data))
03139 #endif      
03140       __auto_congest(data);
03141    return 0;
03142 }

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

Definition at line 6489 of file chan_iax2.c.

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

Referenced by iax2_dprequest(), and iax2_provision().

06490 {
06491    int callno = (int)(long)(data);
06492    ast_mutex_lock(&iaxsl[callno]);
06493    if (iaxs[callno]) {
06494       iaxs[callno]->autoid = -1;
06495    }
06496    ast_mutex_unlock(&iaxsl[callno]);
06497 #ifdef SCHED_MULTITHREADED
06498    if (schedule_action(__auto_hangup, data))
06499 #endif      
06500       __auto_hangup(data);
06501    return 0;
06502 }

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

Definition at line 9229 of file chan_iax2.c.

References ast_calloc, and iax2_context::context.

Referenced by build_user().

09230 {
09231    struct iax2_context *con;
09232 
09233    if ((con = ast_calloc(1, sizeof(*con))))
09234       ast_copy_string(con->context, context, sizeof(con->context));
09235    
09236    return con;
09237 }

static void build_ecx_key ( const unsigned char *  digest,
struct chan_iax2_pvt pvt 
) [static]

Definition at line 4129 of file chan_iax2.c.

References aes_decrypt_key128(), aes_encrypt_key128(), chan_iax2_pvt::ecx, and chan_iax2_pvt::mydcx.

Referenced by build_encryption_keys().

04130 {
04131    /* it is required to hold the corresponding decrypt key to our encrypt key
04132     * in the pvt struct because queued frames occasionally need to be decrypted and
04133     * re-encrypted when updated for a retransmission */
04134    aes_encrypt_key128(digest, &pvt->ecx);
04135    aes_decrypt_key128(digest, &pvt->mydcx);
04136 }

static void build_encryption_keys ( const unsigned char *  digest,
struct chan_iax2_pvt pvt 
) [static]

Definition at line 4123 of file chan_iax2.c.

References aes_decrypt_key128(), build_ecx_key(), and chan_iax2_pvt::dcx.

Referenced by authenticate(), and decrypt_frame().

04124 {
04125    build_ecx_key(digest, pvt);
04126    aes_decrypt_key128(digest, &pvt->dcx);
04127 }

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

Create peer structure based on configuration.

Definition at line 9375 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, ao2_alloc(), ao2_find(), ast_append_ha(), ast_callerid_split(), ast_clear_flag, ast_copy_flags, ast_dnsmgr_lookup(), ast_free_ha(), ast_get_ip(), ast_log(), ast_parse_allow_disallow(), AST_SCHED_DEL, ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), iax2_peer::authmethods, iax2_peer::capability, cid_name, cid_num, iax2_peer::defaddr, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, iax2_peer::dnsmgr, iax2_peer::encmethods, iax2_peer::expire, iax2_peer::expiry, get_auth_methods(), get_encrypt_methods(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mask, iax2_peer::maxms, ast_variable::name, ast_variable::next, peer_destructor(), peer_set_srcaddr(), peer_unref(), peers, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, prefs, iax2_peer::prefs, iax2_registry::secret, iax2_peer::smoothing, iax2_peer::sockfd, unlink_peer(), and ast_variable::value.

09376 {
09377    struct iax2_peer *peer = NULL;
09378    struct ast_ha *oldha = NULL;
09379    int maskfound=0;
09380    int found=0;
09381    int firstpass=1;
09382    struct iax2_peer tmp_peer = {
09383       .name = name,
09384    };
09385 
09386    if (!temponly) {
09387       peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
09388       if (peer && !ast_test_flag(peer, IAX_DELME))
09389          firstpass = 0;
09390    }
09391 
09392    if (peer) {
09393       found++;
09394       if (firstpass) {
09395          oldha = peer->ha;
09396          peer->ha = NULL;
09397       }
09398       unlink_peer(peer);
09399    } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) {
09400       peer->expire = -1;
09401       peer->pokeexpire = -1;
09402       peer->sockfd = defaultsockfd;
09403       if (ast_string_field_init(peer, 32))
09404          peer = peer_unref(peer);
09405    }
09406 
09407    if (peer) {
09408       if (firstpass) {
09409          ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
09410          peer->encmethods = iax2_encryption;
09411          peer->adsi = adsi;
09412          ast_string_field_set(peer,secret,"");
09413          if (!found) {
09414             ast_string_field_set(peer, name, name);
09415             peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
09416             peer->expiry = min_reg_expire;
09417          }
09418          peer->prefs = prefs;
09419          peer->capability = iax2_capability;
09420          peer->smoothing = 0;
09421          peer->pokefreqok = DEFAULT_FREQ_OK;
09422          peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
09423          ast_string_field_set(peer,context,"");
09424          ast_string_field_set(peer,peercontext,"");
09425          ast_clear_flag(peer, IAX_HASCALLERID);
09426          ast_string_field_set(peer, cid_name, "");
09427          ast_string_field_set(peer, cid_num, "");
09428       }
09429 
09430       if (!v) {
09431          v = alt;
09432          alt = NULL;
09433       }
09434       while(v) {
09435          if (!strcasecmp(v->name, "secret")) {
09436             ast_string_field_set(peer, secret, v->value);
09437          } else if (!strcasecmp(v->name, "mailbox")) {
09438             ast_string_field_set(peer, mailbox, v->value);
09439          } else if (!strcasecmp(v->name, "mohinterpret")) {
09440             ast_string_field_set(peer, mohinterpret, v->value);
09441          } else if (!strcasecmp(v->name, "mohsuggest")) {
09442             ast_string_field_set(peer, mohsuggest, v->value);
09443          } else if (!strcasecmp(v->name, "dbsecret")) {
09444             ast_string_field_set(peer, dbsecret, v->value);
09445          } else if (!strcasecmp(v->name, "trunk")) {
09446             ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK);   
09447             if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) {
09448                ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without zaptel timing\n", peer->name);
09449                ast_clear_flag(peer, IAX_TRUNK);
09450             }
09451          } else if (!strcasecmp(v->name, "auth")) {
09452             peer->authmethods = get_auth_methods(v->value);
09453          } else if (!strcasecmp(v->name, "encryption")) {
09454             peer->encmethods = get_encrypt_methods(v->value);
09455          } else if (!strcasecmp(v->name, "notransfer")) {
09456             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09457             ast_clear_flag(peer, IAX_TRANSFERMEDIA);  
09458             ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 
09459          } else if (!strcasecmp(v->name, "transfer")) {
09460             if (!strcasecmp(v->value, "mediaonly")) {
09461                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
09462             } else if (ast_true(v->value)) {
09463                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09464             } else 
09465                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09466          } else if (!strcasecmp(v->name, "jitterbuffer")) {
09467             ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF);  
09468          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
09469             ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF);   
09470          } else if (!strcasecmp(v->name, "host")) {
09471             if (!strcasecmp(v->value, "dynamic")) {
09472                /* They'll register with us */
09473                ast_set_flag(peer, IAX_DYNAMIC); 
09474                if (!found) {
09475                   /* Initialize stuff iff we're not found, otherwise
09476                      we keep going with what we had */
09477                   memset(&peer->addr.sin_addr, 0, 4);
09478                   if (peer->addr.sin_port) {
09479                      /* If we've already got a port, make it the default rather than absolute */
09480                      peer->defaddr.sin_port = peer->addr.sin_port;
09481                      peer->addr.sin_port = 0;
09482                   }
09483                }
09484             } else {
09485                /* Non-dynamic.  Make sure we become that way if we're not */
09486                AST_SCHED_DEL(sched, peer->expire);
09487                ast_clear_flag(peer, IAX_DYNAMIC);
09488                if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr))
09489                   return peer_unref(peer);
09490                if (!peer->addr.sin_port)
09491                   peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
09492             }
09493             if (!maskfound)
09494                inet_aton("255.255.255.255", &peer->mask);
09495          } else if (!strcasecmp(v->name, "defaultip")) {
09496             if (ast_get_ip(&peer->defaddr, v->value))
09497                return peer_unref(peer);
09498          } else if (!strcasecmp(v->name, "sourceaddress")) {
09499             peer_set_srcaddr(peer, v->value);
09500          } else if (!strcasecmp(v->name, "permit") ||
09501                   !strcasecmp(v->name, "deny")) {
09502             peer->ha = ast_append_ha(v->name, v->value, peer->ha);
09503          } else if (!strcasecmp(v->name, "mask")) {
09504             maskfound++;
09505             inet_aton(v->value, &peer->mask);
09506          } else if (!strcasecmp(v->name, "context")) {
09507             ast_string_field_set(peer, context, v->value);
09508          } else if (!strcasecmp(v->name, "regexten")) {
09509             ast_string_field_set(peer, regexten, v->value);
09510          } else if (!strcasecmp(v->name, "peercontext")) {
09511             ast_string_field_set(peer, peercontext, v->value);
09512          } else if (!strcasecmp(v->name, "port")) {
09513             if (ast_test_flag(peer, IAX_DYNAMIC))
09514                peer->defaddr.sin_port = htons(atoi(v->value));
09515             else
09516                peer->addr.sin_port = htons(atoi(v->value));
09517          } else if (!strcasecmp(v->name, "username")) {
09518             ast_string_field_set(peer, username, v->value);
09519          } else if (!strcasecmp(v->name, "allow")) {
09520             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1);
09521          } else if (!strcasecmp(v->name, "disallow")) {
09522             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0);
09523          } else if (!strcasecmp(v->name, "callerid")) {
09524             if (!ast_strlen_zero(v->value)) {
09525                char name2[80];
09526                char num2[80];
09527                ast_callerid_split(v->value, name2, 80, num2, 80);
09528                ast_string_field_set(peer, cid_name, name2);
09529                ast_string_field_set(peer, cid_num, num2);
09530                ast_set_flag(peer, IAX_HASCALLERID);
09531             } else {
09532                ast_clear_flag(peer, IAX_HASCALLERID);
09533                ast_string_field_set(peer, cid_name, "");
09534                ast_string_field_set(peer, cid_num, "");
09535             }
09536          } else if (!strcasecmp(v->name, "fullname")) {
09537             if (!ast_strlen_zero(v->value)) {
09538                ast_string_field_set(peer, cid_name, v->value);
09539                ast_set_flag(peer, IAX_HASCALLERID);
09540             } else {
09541                ast_string_field_set(peer, cid_name, "");
09542                if (ast_strlen_zero(peer->cid_num))
09543                   ast_clear_flag(peer, IAX_HASCALLERID);
09544             }
09545          } else if (!strcasecmp(v->name, "cid_number")) {
09546             if (!ast_strlen_zero(v->value)) {
09547                ast_string_field_set(peer, cid_num, v->value);
09548                ast_set_flag(peer, IAX_HASCALLERID);
09549             } else {
09550                ast_string_field_set(peer, cid_num, "");
09551                if (ast_strlen_zero(peer->cid_name))
09552                   ast_clear_flag(peer, IAX_HASCALLERID);
09553             }
09554          } else if (!strcasecmp(v->name, "sendani")) {
09555             ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 
09556          } else if (!strcasecmp(v->name, "inkeys")) {
09557             ast_string_field_set(peer, inkeys, v->value);
09558          } else if (!strcasecmp(v->name, "outkey")) {
09559             ast_string_field_set(peer, outkey, v->value);
09560          } else if (!strcasecmp(v->name, "qualify")) {
09561             if (!strcasecmp(v->value, "no")) {
09562                peer->maxms = 0;
09563             } else if (!strcasecmp(v->value, "yes")) {
09564                peer->maxms = DEFAULT_MAXMS;
09565             } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
09566                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);
09567                peer->maxms = 0;
09568             }
09569          } else if (!strcasecmp(v->name, "qualifysmoothing")) {
09570             peer->smoothing = ast_true(v->value);
09571          } else if (!strcasecmp(v->name, "qualifyfreqok")) {
09572             if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) {
09573                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);
09574             }
09575          } else if (!strcasecmp(v->name, "qualifyfreqnotok")) {
09576             if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) {
09577                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);
09578             } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok);
09579          } else if (!strcasecmp(v->name, "timezone")) {
09580             ast_string_field_set(peer, zonetag, v->value);
09581          } else if (!strcasecmp(v->name, "adsi")) {
09582             peer->adsi = ast_true(v->value);
09583          }/* else if (strcasecmp(v->name,"type")) */
09584          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09585          v = v->next;
09586          if (!v) {
09587             v = alt;
09588             alt = NULL;
09589          }
09590       }
09591       if (!peer->authmethods)
09592          peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09593       ast_clear_flag(peer, IAX_DELME); 
09594       /* Make sure these are IPv4 addresses */
09595       peer->addr.sin_family = AF_INET;
09596    }
09597    if (oldha)
09598       ast_free_ha(oldha);
09599    return peer;
09600 }

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

Create in-memory user structure from configuration.

Definition at line 9616 of file chan_iax2.c.

References iax2_user::adsi, iax2_user::amaflags, ao2_alloc(), ao2_find(), ao2_unlink(), ast_append_ha(), ast_callerid_split(), ast_cdr_amaflags2int(), ast_clear_flag, ast_copy_flags, ast_free_ha(), ast_log(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_strdupa, ast_string_field_build, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_new(), iax2_user::authmethods, build_context(), iax2_user::capability, cid_name, cid_num, cleanup(), iax2_user::contexts, iax2_user::curauthreq, iax2_user::encmethods, format, free_context(), get_auth_methods(), get_encrypt_methods(), iax2_user::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, iax2_context::next, prefs, iax2_user::prefs, iax2_registry::secret, user_destructor(), user_unref(), users, ast_variable::value, and iax2_user::vars.

09617 {
09618    struct iax2_user *user = NULL;
09619    struct iax2_context *con, *conl = NULL;
09620    struct ast_ha *oldha = NULL;
09621    struct iax2_context *oldcon = NULL;
09622    int format;
09623    int firstpass=1;
09624    int oldcurauthreq = 0;
09625    char *varname = NULL, *varval = NULL;
09626    struct ast_variable *tmpvar = NULL;
09627    struct iax2_user tmp_user = {
09628       .name = name,
09629    };
09630 
09631    if (!temponly) {
09632       user = ao2_find(users, &tmp_user, OBJ_POINTER);
09633       if (user && !ast_test_flag(user, IAX_DELME))
09634          firstpass = 0;
09635    }
09636 
09637    if (user) {
09638       if (firstpass) {
09639          oldcurauthreq = user->curauthreq;
09640          oldha = user->ha;
09641          oldcon = user->contexts;
09642          user->ha = NULL;
09643          user->contexts = NULL;
09644       }
09645       /* Already in the list, remove it and it will be added back (or FREE'd) */
09646       ao2_unlink(users, user);
09647    } else {
09648       user = ao2_alloc(sizeof(*user), user_destructor);
09649    }
09650    
09651    if (user) {
09652       if (firstpass) {
09653          ast_string_field_free_memory(user);
09654          memset(user, 0, sizeof(struct iax2_user));
09655          if (ast_string_field_init(user, 32)) {
09656             user = user_unref(user);
09657             goto cleanup;
09658          }
09659          user->maxauthreq = maxauthreq;
09660          user->curauthreq = oldcurauthreq;
09661          user->prefs = prefs;
09662          user->capability = iax2_capability;
09663          user->encmethods = iax2_encryption;
09664          user->adsi = adsi;
09665          ast_string_field_set(user, name, name);
09666          ast_string_field_set(user, language, language);
09667          ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP);   
09668          ast_clear_flag(user, IAX_HASCALLERID);
09669          ast_string_field_set(user, cid_name, "");
09670          ast_string_field_set(user, cid_num, "");
09671       }
09672       if (!v) {
09673          v = alt;
09674          alt = NULL;
09675       }
09676       while(v) {
09677          if (!strcasecmp(v->name, "context")) {
09678             con = build_context(v->value);
09679             if (con) {
09680                if (conl)
09681                   conl->next = con;
09682                else
09683                   user->contexts = con;
09684                conl = con;
09685             }
09686          } else if (!strcasecmp(v->name, "permit") ||
09687                   !strcasecmp(v->name, "deny")) {
09688             user->ha = ast_append_ha(v->name, v->value, user->ha);
09689          } else if (!strcasecmp(v->name, "setvar")) {
09690             varname = ast_strdupa(v->value);
09691             if (varname && (varval = strchr(varname,'='))) {
09692                *varval = '\0';
09693                varval++;
09694                if((tmpvar = ast_variable_new(varname, varval))) {
09695                   tmpvar->next = user->vars; 
09696                   user->vars = tmpvar;
09697                }
09698             }
09699          } else if (!strcasecmp(v->name, "allow")) {
09700             ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
09701          } else if (!strcasecmp(v->name, "disallow")) {
09702             ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0);
09703          } else if (!strcasecmp(v->name, "trunk")) {
09704             ast_set2_flag(user, ast_true(v->value), IAX_TRUNK);   
09705             if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) {
09706                ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without zaptel timing\n", user->name);
09707                ast_clear_flag(user, IAX_TRUNK);
09708             }
09709          } else if (!strcasecmp(v->name, "auth")) {
09710             user->authmethods = get_auth_methods(v->value);
09711          } else if (!strcasecmp(v->name, "encryption")) {
09712             user->encmethods = get_encrypt_methods(v->value);
09713          } else if (!strcasecmp(v->name, "notransfer")) {
09714             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09715             ast_clear_flag(user, IAX_TRANSFERMEDIA);  
09716             ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 
09717          } else if (!strcasecmp(v->name, "transfer")) {
09718             if (!strcasecmp(v->value, "mediaonly")) {
09719                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
09720             } else if (ast_true(v->value)) {
09721                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09722             } else 
09723                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09724          } else if (!strcasecmp(v->name, "codecpriority")) {
09725             if(!strcasecmp(v->value, "caller"))
09726                ast_set_flag(user, IAX_CODEC_USER_FIRST);
09727             else if(!strcasecmp(v->value, "disabled"))
09728                ast_set_flag(user, IAX_CODEC_NOPREFS);
09729             else if(!strcasecmp(v->value, "reqonly")) {
09730                ast_set_flag(user, IAX_CODEC_NOCAP);
09731                ast_set_flag(user, IAX_CODEC_NOPREFS);
09732             }
09733          } else if (!strcasecmp(v->name, "jitterbuffer")) {
09734             ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF);
09735          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
09736             ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF);
09737          } else if (!strcasecmp(v->name, "dbsecret")) {
09738             ast_string_field_set(user, dbsecret, v->value);
09739          } else if (!strcasecmp(v->name, "secret")) {
09740             if (!ast_strlen_zero(user->secret)) {
09741                char *old = ast_strdupa(user->secret);
09742 
09743                ast_string_field_build(user, secret, "%s;%s", old, v->value);
09744             } else
09745                ast_string_field_set(user, secret, v->value);
09746          } else if (!strcasecmp(v->name, "callerid")) {
09747             if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) {
09748                char name2[80];
09749                char num2[80];
09750                ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
09751                ast_string_field_set(user, cid_name, name2);
09752                ast_string_field_set(user, cid_num, num2);
09753                ast_set_flag(user, IAX_HASCALLERID);
09754             } else {
09755                ast_clear_flag(user, IAX_HASCALLERID);
09756                ast_string_field_set(user, cid_name, "");
09757                ast_string_field_set(user, cid_num, "");
09758             }
09759          } else if (!strcasecmp(v->name, "fullname")) {
09760             if (!ast_strlen_zero(v->value)) {
09761                ast_string_field_set(user, cid_name, v->value);
09762                ast_set_flag(user, IAX_HASCALLERID);
09763             } else {
09764                ast_string_field_set(user, cid_name, "");
09765                if (ast_strlen_zero(user->cid_num))
09766                   ast_clear_flag(user, IAX_HASCALLERID);
09767             }
09768          } else if (!strcasecmp(v->name, "cid_number")) {
09769             if (!ast_strlen_zero(v->value)) {
09770                ast_string_field_set(user, cid_num, v->value);
09771                ast_set_flag(user, IAX_HASCALLERID);
09772             } else {
09773                ast_string_field_set(user, cid_num, "");
09774                if (ast_strlen_zero(user->cid_name))
09775                   ast_clear_flag(user, IAX_HASCALLERID);
09776             }
09777          } else if (!strcasecmp(v->name, "accountcode")) {
09778             ast_string_field_set(user, accountcode, v->value);
09779          } else if (!strcasecmp(v->name, "mohinterpret")) {
09780             ast_string_field_set(user, mohinterpret, v->value);
09781          } else if (!strcasecmp(v->name, "mohsuggest")) {
09782             ast_string_field_set(user, mohsuggest, v->value);
09783          } else if (!strcasecmp(v->name, "language")) {
09784             ast_string_field_set(user, language, v->value);
09785          } else if (!strcasecmp(v->name, "amaflags")) {
09786             format = ast_cdr_amaflags2int(v->value);
09787             if (format < 0) {
09788                ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
09789             } else {
09790                user->amaflags = format;
09791             }
09792          } else if (!strcasecmp(v->name, "inkeys")) {
09793             ast_string_field_set(user, inkeys, v->value);
09794          } else if (!strcasecmp(v->name, "maxauthreq")) {
09795             user->maxauthreq = atoi(v->value);
09796             if (user->maxauthreq < 0)
09797                user->maxauthreq = 0;
09798          } else if (!strcasecmp(v->name, "adsi")) {
09799             user->adsi = ast_true(v->value);
09800          }/* else if (strcasecmp(v->name,"type")) */
09801          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09802          v = v->next;
09803          if (!v) {
09804             v = alt;
09805             alt = NULL;
09806          }
09807       }
09808       if (!user->authmethods) {
09809          if (!ast_strlen_zero(user->secret)) {
09810             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09811             if (!ast_strlen_zero(user->inkeys))
09812                user->authmethods |= IAX_AUTH_RSA;
09813          } else if (!ast_strlen_zero(user->inkeys)) {
09814             user->authmethods = IAX_AUTH_RSA;
09815          } else {
09816             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09817          }
09818       }
09819       ast_clear_flag(user, IAX_DELME);
09820    }
09821 cleanup:
09822    if (oldha)
09823       ast_free_ha(oldha);
09824    if (oldcon)
09825       free_context(oldcon);
09826    return user;
09827 }

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

Definition at line 10332 of file chan_iax2.c.

References ARRAY_LEN, AST_FRAME_IAX, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), iax_ie_data::buf, iax2_registry::callno, chan_iax2_pvt::capability, parsed_dial_string::context, create_addr(), parsed_dial_string::exten, find_callno_locked(), IAX_CAPABILITY_FULLBANDWIDTH, IAX_COMMAND_NEW, iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CAPABILITY, IAX_IE_FORMAT, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, iaxs, iaxsl, parsed_dial_string::key, LOG_DEBUG, LOG_WARNING, NEW_FORCE, option_debug, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, iax_ie_data::pos, iax2_registry::secret, send_command(), create_addr_info::sockfd, and parsed_dial_string::username.

Referenced by find_cache().

10333 {
10334    struct sockaddr_in sin;
10335    int x;
10336    int callno;
10337    struct iax_ie_data ied;
10338    struct create_addr_info cai;
10339    struct parsed_dial_string pds;
10340    char *tmpstr;
10341 
10342    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
10343       /* Look for an *exact match* call.  Once a call is negotiated, it can only
10344          look up entries for a single context */
10345       if (!ast_mutex_trylock(&iaxsl[x])) {
10346          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
10347             return x;
10348          ast_mutex_unlock(&iaxsl[x]);
10349       }
10350    }
10351 
10352    /* No match found, we need to create a new one */
10353 
10354    memset(&cai, 0, sizeof(cai));
10355    memset(&ied, 0, sizeof(ied));
10356    memset(&pds, 0, sizeof(pds));
10357 
10358    tmpstr = ast_strdupa(data);
10359    parse_dial_string(tmpstr, &pds);
10360 
10361    if (ast_strlen_zero(pds.peer)) {
10362       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data);
10363       return -1;
10364    }
10365 
10366    /* Populate our address from the given */
10367    if (create_addr(pds.peer, NULL, &sin, &cai))
10368       return -1;
10369 
10370    if (option_debug)
10371       ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
10372          pds.peer, pds.username, pds.password, pds.context);
10373 
10374    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
10375    if (callno < 1) {
10376       ast_log(LOG_WARNING, "Unable to create call\n");
10377       return -1;
10378    }
10379 
10380    ast_string_field_set(iaxs[callno], dproot, data);
10381    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
10382 
10383    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
10384    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
10385    /* the string format is slightly different from a standard dial string,
10386       because the context appears in the 'exten' position
10387    */
10388    if (pds.exten)
10389       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
10390    if (pds.username)
10391       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
10392    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
10393    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
10394    /* Keep password handy */
10395    if (pds.password)
10396       ast_string_field_set(iaxs[callno], secret, pds.password);
10397    if (pds.key)
10398       ast_string_field_set(iaxs[callno], outkey, pds.key);
10399    /* Start the call going */
10400    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
10401 
10402    return callno;
10403 }

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

Definition at line 3991 of file chan_iax2.c.

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

03992 {
03993    /* Returns where in "receive time" we are.  That is, how many ms
03994       since we received (or would have received) the frame with timestamp 0 */
03995    int ms;
03996 #ifdef IAXTESTS
03997    int jit;
03998 #endif /* IAXTESTS */
03999    /* Setup rxcore if necessary */
04000    if (ast_tvzero(p->rxcore)) {
04001       p->rxcore = ast_tvnow();
04002       if (option_debug && iaxdebug)
04003          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
04004                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
04005       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
04006 #if 1
04007       if (option_debug && iaxdebug)
04008          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
04009                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
04010 #endif
04011    }
04012 
04013    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
04014 #ifdef IAXTESTS
04015    if (test_jit) {
04016       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
04017          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
04018          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
04019             jit = -jit;
04020          ms += jit;
04021       }
04022    }
04023    if (test_late) {
04024       ms += test_late;
04025       test_late = 0;
04026    }
04027 #endif /* IAXTESTS */
04028    return ms;
04029 }

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

Definition at line 3862 of file chan_iax2.c.

References AST_FRAME_CNG, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_tvadd(), ast_tvsub(), chan_iax2_pvt::callno, ast_frame::delivery, ast_frame::frametype, iaxs, chan_iax2_pvt::lastsent, LOG_DEBUG, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, chan_iax2_pvt::offset, option_debug, chan_iax2_pvt::peercallno, and ast_frame::samples.

Referenced by iax2_send(), and socket_process().

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

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

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

03819 {
03820    unsigned long int mssincetx; /* unsigned to handle overflows */
03821    long int ms, pred;
03822 
03823    tpeer->trunkact = *tv;
03824    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03825    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03826       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03827       tpeer->txtrunktime = *tv;
03828       tpeer->lastsent = 999999;
03829    }
03830    /* Update last transmit time now */
03831    tpeer->lasttxtime = *tv;
03832    
03833    /* Calculate ms offset */
03834    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03835    /* Predict from last value */
03836    pred = tpeer->lastsent + sampms;
03837    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03838       ms = pred;
03839    
03840    /* We never send the same timestamp twice, so fudge a little if we must */
03841    if (ms == tpeer->lastsent)
03842       ms = tpeer->lastsent + 1;
03843    tpeer->lastsent = ms;
03844    return ms;
03845 }

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

Definition at line 5116 of file chan_iax2.c.

References iax2_user::adsi, chan_iax2_pvt::adsi, iax_ies::adsicpe, chan_iax2_pvt::amaflags, iax2_user::amaflags, ao2_iterator_init(), ao2_iterator_next(), apply_context(), ast_apply_ha(), ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_inet_ntoa(), ast_log(), AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, ast_set2_flag, ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_variable_new(), iax2_user::authmethods, chan_iax2_pvt::authmethods, chan_iax2_pvt::authrej, iax_ies::called_context, iax_ies::called_number, iax_ies::calling_ani, iax_ies::calling_name, iax_ies::calling_number, chan_iax2_pvt::calling_pres, iax_ies::calling_pres, chan_iax2_pvt::calling_tns, iax_ies::calling_tns, chan_iax2_pvt::calling_ton, iax_ies::calling_ton, iax2_user::capability, chan_iax2_pvt::capability, iax_ies::capability, cid_name, cid_num, iax_ies::codec_prefs, iax2_context::context, iax2_user::contexts, iax_ies::dnid, iax2_user::encmethods, chan_iax2_pvt::encmethods, exten, iax_ies::format, iax2_user::ha, iax2_getpeertrunk(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_MAXAUTHREQ, IAX_NOTRANSFER, IAX_PROTO_VERSION, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iax_ies::language, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, chan_iax2_pvt::peeradsicpe, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_user::prefs, chan_iax2_pvt::prefs, prefs, iax_ies::rdnis, realtime_user(), iax2_registry::secret, user_unref(), iax_ies::username, users, ast_variable::value, chan_iax2_pvt::vars, iax2_user::vars, and iax_ies::version.

Referenced by socket_process().

05117 {
05118    /* Start pessimistic */
05119    int res = -1;
05120    int version = 2;
05121    struct iax2_user *user = NULL, *best = NULL;
05122    int bestscore = 0;
05123    int gotcapability = 0;
05124    struct ast_variable *v = NULL, *tmpvar = NULL;
05125    struct ao2_iterator i;
05126 
05127    if (!iaxs[callno])
05128       return res;
05129    if (ies->called_number)
05130       ast_string_field_set(iaxs[callno], exten, ies->called_number);
05131    if (ies->calling_number) {
05132       ast_shrink_phone_number(ies->calling_number);
05133       ast_string_field_set(iaxs[callno], cid_num, ies->calling_number);
05134    }
05135    if (ies->calling_name)
05136       ast_string_field_set(iaxs[callno], cid_name, ies->calling_name);
05137    if (ies->calling_ani)
05138       ast_string_field_set(iaxs[callno], ani, ies->calling_ani);
05139    if (ies->dnid)
05140       ast_string_field_set(iaxs[callno], dnid, ies->dnid);
05141    if (ies->rdnis)
05142       ast_string_field_set(iaxs[callno], rdnis, ies->rdnis);
05143    if (ies->called_context)
05144       ast_string_field_set(iaxs[callno], context, ies->called_context);
05145    if (ies->language)
05146       ast_string_field_set(iaxs[callno], language, ies->language);
05147    if (ies->username)
05148       ast_string_field_set(iaxs[callno], username, ies->username);
05149    if (ies->calling_ton > -1)
05150       iaxs[callno]->calling_ton = ies->calling_ton;
05151    if (ies->calling_tns > -1)
05152       iaxs[callno]->calling_tns = ies->calling_tns;
05153    if (ies->calling_pres > -1)
05154       iaxs[callno]->calling_pres = ies->calling_pres;
05155    if (ies->format)
05156       iaxs[callno]->peerformat = ies->format;
05157    if (ies->adsicpe)
05158       iaxs[callno]->peeradsicpe = ies->adsicpe;
05159    if (ies->capability) {
05160       gotcapability = 1;
05161       iaxs[callno]->peercapability = ies->capability;
05162    } 
05163    if (ies->version)
05164       version = ies->version;
05165 
05166    /* Use provided preferences until told otherwise for actual preferences */
05167    if(ies->codec_prefs) {
05168       ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
05169       ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
05170    }
05171 
05172    if (!gotcapability) 
05173       iaxs[callno]->peercapability = iaxs[callno]->peerformat;
05174    if (version > IAX_PROTO_VERSION) {
05175       ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 
05176          ast_inet_ntoa(sin->sin_addr), version);
05177       return res;
05178    }
05179    /* Search the userlist for a compatible entry, and fill in the rest */
05180    i = ao2_iterator_init(users, 0);
05181    while ((user = ao2_iterator_next(&i))) {
05182       if ((ast_strlen_zero(iaxs[callno]->username) ||          /* No username specified */
05183          !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */
05184          && ast_apply_ha(user->ha, sin)   /* Access is permitted from this IP */
05185          && (ast_strlen_zero(iaxs[callno]->context) ||         /* No context specified */
05186               apply_context(user->contexts, iaxs[callno]->context))) {        /* Context is permitted */
05187          if (!ast_strlen_zero(iaxs[callno]->username)) {
05188             /* Exact match, stop right now. */
05189             if (best)
05190                user_unref(best);
05191             best = user;
05192             break;
05193          } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) {
05194             /* No required authentication */
05195             if (user->ha) {
05196                /* There was host authentication and we passed, bonus! */
05197                if (bestscore < 4) {
05198                   bestscore = 4;
05199                   if (best)
05200                      user_unref(best);
05201                   best = user;
05202                   continue;
05203                }
05204             } else {
05205                /* No host access, but no secret, either, not bad */
05206                if (bestscore < 3) {
05207                   bestscore = 3;
05208                   if (best)
05209                      user_unref(best);
05210                   best = user;
05211                   continue;
05212                }
05213             }
05214          } else {
05215             if (user->ha) {
05216                /* Authentication, but host access too, eh, it's something.. */
05217                if (bestscore < 2) {
05218                   bestscore = 2;
05219                   if (best)
05220                      user_unref(best);
05221                   best = user;
05222                   continue;
05223                }
05224             } else {
05225                /* Authentication and no host access...  This is our baseline */
05226                if (bestscore < 1) {
05227                   bestscore = 1;
05228                   if (best)
05229                      user_unref(best);
05230                   best = user;
05231                   continue;
05232                }
05233             }
05234          }
05235       }
05236       user_unref(user);
05237    }
05238    user = best;
05239    if (!user && !ast_strlen_zero(iaxs[callno]->username)) {
05240       user = realtime_user(iaxs[callno]->username, sin);
05241       if (user && !ast_strlen_zero(iaxs[callno]->context) &&         /* No context specified */
05242           !apply_context(user->contexts, iaxs[callno]->context)) {      /* Context is permitted */
05243          user = user_unref(user);
05244       }
05245    }
05246    if (user) {
05247       /* We found our match (use the first) */
05248       /* copy vars */
05249       for (v = user->vars ; v ; v = v->next) {
05250          if((tmpvar = ast_variable_new(v->name, v->value))) {
05251             tmpvar->next = iaxs[callno]->vars; 
05252             iaxs[callno]->vars = tmpvar;
05253          }
05254       }
05255       /* If a max AUTHREQ restriction is in place, activate it */
05256       if (user->maxauthreq > 0)
05257          ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ);
05258       iaxs[callno]->prefs = user->prefs;
05259       ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST);
05260       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS);
05261       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP);
05262       iaxs[callno]->encmethods = user->encmethods;
05263       /* Store the requested username if not specified */
05264       if (ast_strlen_zero(iaxs[callno]->username))
05265          ast_string_field_set(iaxs[callno], username, user->name);
05266       /* Store whether this is a trunked call, too, of course, and move if appropriate */
05267       ast_copy_flags(iaxs[callno], user, IAX_TRUNK);
05268       iaxs[callno]->capability = user->capability;
05269       /* And use the default context */
05270       if (ast_strlen_zero(iaxs[callno]->context)) {
05271          if (user->contexts)
05272             ast_string_field_set(iaxs[callno], context, user->contexts->context);
05273          else
05274             ast_string_field_set(iaxs[callno], context, context);
05275       }
05276       /* And any input keys */
05277       ast_string_field_set(iaxs[callno], inkeys, user->inkeys);
05278       /* And the permitted authentication methods */
05279       iaxs[callno]->authmethods = user->authmethods;
05280       iaxs[callno]->adsi = user->adsi;
05281       /* If they have callerid, override the given caller id.  Always store the ANI */
05282       if (!ast_strlen_zero(iaxs[callno]->cid_num) || !ast_strlen_zero(iaxs[callno]->cid_name)) {
05283          if (ast_test_flag(user, IAX_HASCALLERID)) {
05284             iaxs[callno]->calling_tns = 0;
05285             iaxs[callno]->calling_ton = 0;
05286             ast_string_field_set(iaxs[callno], cid_num, user->cid_num);
05287             ast_string_field_set(iaxs[callno], cid_name, user->cid_name);
05288             iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
05289          }
05290          if (ast_strlen_zero(iaxs[callno]->ani))
05291             ast_string_field_set(iaxs[callno], ani, user->cid_num);
05292       } else {
05293          iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE;
05294       }
05295       if (!ast_strlen_zero(user->accountcode))
05296          ast_string_field_set(iaxs[callno], accountcode, user->accountcode);
05297       if (!ast_strlen_zero(user->mohinterpret))
05298          ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret);
05299       if (!ast_strlen_zero(user->mohsuggest))
05300          ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest);
05301       if (user->amaflags)
05302          iaxs[callno]->amaflags = user->amaflags;
05303       if (!ast_strlen_zero(user->language))
05304          ast_string_field_set(iaxs[callno], language, user->language);
05305       ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);   
05306       /* Keep this check last */
05307       if (!ast_strlen_zero(user->dbsecret)) {
05308          char *family, *key=NULL;
05309          char buf[80];
05310          family = ast_strdupa(user->dbsecret);
05311          key = strchr(family, '/');
05312          if (key) {
05313             *key = '\0';
05314             key++;
05315          }
05316          if (!key || ast_db_get(family, key, buf, sizeof(buf)))
05317             ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret);
05318          else
05319             ast_string_field_set(iaxs[callno], secret, buf);
05320       } else
05321          ast_string_field_set(iaxs[callno], secret, user->secret);
05322       res = 0;
05323       user = user_unref(user);
05324    } else {
05325        /* user was not found, but we should still fake an AUTHREQ.
05326         * Set authmethods to the last known authmethod used by the system
05327         * Set a fake secret, it's not looked at, just required to attempt authentication.
05328         * Set authrej so the AUTHREP is rejected without even looking at its contents */
05329       iaxs[callno]->authmethods = last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
05330       ast_string_field_set(iaxs[callno], secret, "badsecret");
05331       iaxs[callno]->authrej = 1;
05332       if (!ast_strlen_zero(iaxs[callno]->username)) {
05333          /* only send the AUTHREQ if a username was specified. */
05334          res = 0;
05335       }
05336    }
05337    ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);  
05338    return res;
05339 }

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

Definition at line 6847 of file chan_iax2.c.

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

Referenced by socket_process().

06848 {
06849    unsigned int ourver;
06850    char rsi[80];
06851    snprintf(rsi, sizeof(rsi), "si-%s", si);
06852    if (iax_provision_version(&ourver, rsi, 1))
06853       return 0;
06854    if (option_debug)
06855       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06856    if (ourver != ver) 
06857       iax2_provision(sin, sockfd, NULL, rsi, 1);
06858    return 0;
06859 }

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

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

Referenced by peer_set_srcaddr().

09256 {
09257    int sd;
09258    int res;
09259    
09260    sd = socket(AF_INET, SOCK_DGRAM, 0);
09261    if (sd < 0) {
09262       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
09263       return -1;
09264    }
09265 
09266    res = bind(sd, sa, salen);
09267    if (res < 0) {
09268       if (option_debug)
09269          ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
09270       close(sd);
09271       return 1;
09272    }
09273 
09274    close(sd);
09275    return 0;
09276 }

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

Definition at line 5842 of file chan_iax2.c.

References ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_UNKNOWN, iax_ies::called_number, iax2_dpcache::callno, chan_iax2_pvt::dpentries, iax_ies::dpstatus, iax2_dpcache::expiry, expiry, iax2_dpcache::exten, exten, iax2_dpcache::flags, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax2_dpcache::orig, iax2_dpcache::peer, iax_ies::refresh, and iax2_dpcache::waiters.

Referenced by socket_process().

05843 {
05844    char exten[256] = "";
05845    int status = CACHE_FLAG_UNKNOWN;
05846    int expiry = iaxdefaultdpcache;
05847    int x;
05848    int matchmore = 0;
05849    struct iax2_dpcache *dp, *prev;
05850    
05851    if (ies->called_number)
05852       ast_copy_string(exten, ies->called_number, sizeof(exten));
05853 
05854    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
05855       status = CACHE_FLAG_EXISTS;
05856    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
05857       status = CACHE_FLAG_CANEXIST;
05858    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
05859       status = CACHE_FLAG_NONEXISTENT;
05860 
05861    if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
05862       /* Don't really do anything with this */
05863    }
05864    if (ies->refresh)
05865       expiry = ies->refresh;
05866    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
05867       matchmore = CACHE_FLAG_MATCHMORE;
05868    ast_mutex_lock(&dpcache_lock);
05869    prev = NULL;
05870    dp = pvt->dpentries;
05871    while(dp) {
05872       if (!strcmp(dp->exten, exten)) {
05873          /* Let them go */
05874          if (prev)
05875             prev->peer = dp->peer;
05876          else
05877             pvt->dpentries = dp->peer;
05878          dp->peer = NULL;
05879          dp->callno = 0;
05880          dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
05881          if (dp->flags & CACHE_FLAG_PENDING) {
05882             dp->flags &= ~CACHE_FLAG_PENDING;
05883             dp->flags |= status;
05884             dp->flags |= matchmore;
05885          }
05886          /* Wake up waiters */
05887          for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
05888             if (dp->waiters[x] > -1)
05889                write(dp->waiters[x], "asdf", 4);
05890       }
05891       prev = dp;
05892       dp = dp->peer;
05893    }
05894    ast_mutex_unlock(&dpcache_lock);
05895    return 0;
05896 }

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

Definition at line 2410 of file chan_iax2.c.

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

02411 {
02412    int which = 0;
02413    struct iax2_peer *peer;
02414    char *res = NULL;
02415    int wordlen = strlen(word);
02416    struct ao2_iterator i;
02417 
02418    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02419    if (pos != 3)
02420       return NULL;
02421 
02422    i = ao2_iterator_init(peers, 0);
02423    while ((peer = ao2_iterator_next(&i))) {
02424       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02425          res = ast_strdup(peer->name);
02426          peer_unref(peer);
02427          break;
02428       }
02429       peer_unref(peer);
02430    }
02431 
02432    return res;
02433 }

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

Definition at line 5898 of file chan_iax2.c.

References chan_iax2_pvt::addr, chan_iax2_pvt::aseqno, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), iax_frame::callno, iax_ies::callno, jb_frame::data, DEFAULT_RETRY_TIME, iax2_frame_free(), iaxq, iaxs, chan_iax2_pvt::iseqno, chan_iax2_pvt::jb, jb_getall(), JB_OK, jb_reset(), chan_iax2_pvt::lag, chan_iax2_pvt::last, chan_iax2_pvt::lastsent, LOG_WARNING, chan_iax2_pvt::nextpred, chan_iax2_pvt::offset, chan_iax2_pvt::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, remove_by_peercallno(), iax_frame::retries, chan_iax2_pvt::rseqno, chan_iax2_pvt::rxcore, store_by_peercallno(), chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, TRANSFER_NONE, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, chan_iax2_pvt::videoformat, and chan_iax2_pvt::voiceformat.

Referenced by socket_process().

05899 {
05900    int peercallno = 0;
05901    struct chan_iax2_pvt *pvt = iaxs[callno];
05902    struct iax_frame *cur;
05903    jb_frame frame;
05904 
05905    if (ies->callno)
05906       peercallno = ies->callno;
05907 
05908    if (peercallno < 1) {
05909       ast_log(LOG_WARNING, "Invalid transfer request\n");
05910       return -1;
05911    }
05912    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
05913    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
05914    /* Reset sequence numbers */
05915    pvt->oseqno = 0;
05916    pvt->rseqno = 0;
05917    pvt->iseqno = 0;
05918    pvt->aseqno = 0;
05919 
05920    if (pvt->peercallno) {
05921       remove_by_peercallno(pvt);
05922    }
05923    pvt->peercallno = peercallno;
05924    store_by_peercallno(pvt);
05925 
05926    pvt->transferring = TRANSFER_NONE;
05927    pvt->svoiceformat = -1;
05928    pvt->voiceformat = 0;
05929    pvt->svideoformat = -1;
05930    pvt->videoformat = 0;
05931    pvt->transfercallno = -1;
05932    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
05933    memset(&pvt->offset, 0, sizeof(pvt->offset));
05934    /* reset jitterbuffer */
05935    while(jb_getall(pvt->jb,&frame) == JB_OK)
05936       iax2_frame_free(frame.data);
05937    jb_reset(pvt->jb);
05938    pvt->lag = 0;
05939    pvt->last = 0;
05940    pvt->lastsent = 0;
05941    pvt->nextpred = 0;
05942    pvt->pingtime = DEFAULT_RETRY_TIME;
05943    AST_LIST_LOCK(&iaxq.queue);
05944    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
05945       /* We must cancel any packets that would have been transmitted
05946          because now we're talking to someone new.  It's okay, they
05947          were transmitted to someone that didn't care anyway. */
05948       if (callno == cur->callno) 
05949          cur->retries = -1;
05950    }
05951    AST_LIST_UNLOCK(&iaxq.queue);
05952    return 0; 
05953 }

static unsigned char compress_subclass ( int  subclass  )  [static]

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

01072 {
01073    int x;
01074    int power=-1;
01075    /* If it's 128 or smaller, just return it */
01076    if (subclass < IAX_FLAG_SC_LOG)
01077       return subclass;
01078    /* Otherwise find its power */
01079    for (x = 0; x < IAX_MAX_SHIFT; x++) {
01080       if (subclass & (1 << x)) {
01081          if (power > -1) {
01082             ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass);
01083             return 0;
01084          } else
01085             power = x;
01086       }
01087    }
01088    return power | IAX_FLAG_SC_LOG;
01089 }

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

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

06862 {
06863    jb_info stats;
06864    jb_getinfo(pvt->jb, &stats);
06865    
06866    memset(iep, 0, sizeof(*iep));
06867 
06868    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06869    if(stats.frames_in == 0) stats.frames_in = 1;
06870    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06871    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06872    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06873    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06874    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06875 }

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

Definition at line 3027 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ast_clear_flag, ast_codec_pref_convert(), ast_codec_pref_prepend(), ast_copy_flags, ast_db_get(), ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::capability, create_addr_info::capability, create_addr_info::context, iax2_peer::defaddr, iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, hp, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_peer::lastms, LOG_DEBUG, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, create_addr_info::outkey, peer_unref(), create_addr_info::peercontext, iax2_peer::prefs, create_addr_info::prefs, prefs, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, and create_addr_info::username.

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

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

Definition at line 4186 of file chan_iax2.c.

References AST_FRAME_VIDEO, ast_log(), ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, ast_frame::frametype, IAX_FLAG_FULL, LOG_DEBUG, memcpy_decrypt(), option_debug, ast_iax2_full_hdr::scallno, ast_frame::subclass, ast_iax2_full_hdr::type, and uncompress_subclass().

Referenced by decrypt_frame(), and update_packet().

04187 {
04188    int padding;
04189    unsigned char *workspace;
04190 
04191    workspace = alloca(*datalen);
04192    memset(f, 0, sizeof(*f));
04193    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04194       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04195       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
04196          return -1;
04197       /* Decrypt */
04198       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
04199 
04200       padding = 16 + (workspace[15] & 0xf);
04201       if (option_debug && iaxdebug)
04202          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
04203       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
04204          return -1;
04205 
04206       *datalen -= padding;
04207       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04208       f->frametype = fh->type;
04209       if (f->frametype == AST_FRAME_VIDEO) {
04210          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
04211       } else {
04212          f->subclass = uncompress_subclass(fh->csub);
04213       }
04214    } else {
04215       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04216       if (option_debug && iaxdebug)
04217          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
04218       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
04219          return -1;
04220       /* Decrypt */
04221       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
04222       padding = 16 + (workspace[15] & 0x0f);
04223       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
04224          return -1;
04225       *datalen -= padding;
04226       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04227    }
04228    return 0;
04229 }

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

Definition at line 4272 of file chan_iax2.c.

References ast_set_flag, ast_strdupa, ast_test_flag, build_encryption_keys(), decode_frame(), IAX_KEYPOPULATED, iaxs, MD5Final(), MD5Init(), MD5Update(), iax2_registry::secret, and strsep().

Referenced by socket_process().

04273 {
04274    int res=-1;
04275    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04276       /* Search for possible keys, given secrets */
04277       struct MD5Context md5;
04278       unsigned char digest[16];
04279       char *tmppw, *stringp;
04280       
04281       tmppw = ast_strdupa(iaxs[callno]->secret);
04282       stringp = tmppw;
04283       while ((tmppw = strsep(&stringp, ";"))) {
04284          MD5Init(&md5);
04285          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04286          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04287          MD5Final(digest, &md5);
04288          build_encryption_keys(digest, iaxs[callno]);
04289          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04290          if (!res) {
04291             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04292             break;
04293          }
04294       }
04295    } else 
04296       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04297    return res;
04298 }

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

06924 {
06925    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06926    struct ast_iax2_full_hdr *fh, *cur_fh;
06927 
06928    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06929       return;
06930 
06931    pkt_buf->len = from_here->buf_len;
06932    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06933 
06934    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06935    ast_mutex_lock(&to_here->lock);
06936    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06937       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06938       if (fh->oseqno < cur_fh->oseqno) {
06939          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06940          break;
06941       }
06942    }
06943    AST_LIST_TRAVERSE_SAFE_END
06944 
06945    if (!cur_pkt_buf)
06946       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06947    
06948    ast_mutex_unlock(&to_here->lock);
06949 }

static void delete_users ( void   )  [static]

Definition at line 9847 of file chan_iax2.c.

References ao2_callback(), ast_dnsmgr_release(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, free, iax2_destroy(), iaxs, iaxsl, peer_delme_cb(), peers, chan_iax2_pvt::reg, user_delme_cb(), and users.

09848 {
09849    struct iax2_registry *reg;
09850 
09851    ao2_callback(users, 0, user_delme_cb, NULL);
09852 
09853    AST_LIST_LOCK(&registrations);
09854    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09855       ast_sched_del(sched, reg->expire);
09856       if (reg->callno) {
09857          ast_mutex_lock(&iaxsl[reg->callno]);
09858          if (iaxs[reg->callno]) {
09859             iaxs[reg->callno]->reg = NULL;
09860             iax2_destroy(reg->callno);
09861          }
09862          ast_mutex_unlock(&iaxsl[reg->callno]);
09863       }
09864       if (reg->dnsmgr)
09865          ast_dnsmgr_release(reg->dnsmgr);
09866       free(reg);
09867    }
09868    AST_LIST_UNLOCK(&registrations);
09869 
09870    ao2_callback(peers, 0, peer_delme_cb, NULL);
09871 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1750 of file chan_iax2.c.

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

Referenced by reload_firmware().

01751 {
01752    /* Close firmware */
01753    if (cur->fwh) {
01754       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01755    }
01756    close(cur->fd);
01757    free(cur);
01758 }

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

Definition at line 6695 of file chan_iax2.c.

References ast_canmatch_extension(), ast_exists_extension(), AST_FRAME_IAX, ast_ignore_pattern(), ast_matchmore_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), iax_ie_data::buf, IAX_COMMAND_DPREP, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_NUMBER, IAX_IE_DPSTATUS, IAX_IE_REFRESH, iaxs, iaxsl, iax_ie_data::pos, and send_command().

Referenced by dp_lookup_thread(), and socket_process().

06696 {
06697    unsigned short dpstatus = 0;
06698    struct iax_ie_data ied1;
06699    int mm;
06700 
06701    memset(&ied1, 0, sizeof(ied1));
06702    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06703    /* Must be started */
06704    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06705       dpstatus = IAX_DPSTATUS_EXISTS;
06706    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06707       dpstatus = IAX_DPSTATUS_CANEXIST;
06708    } else {
06709       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06710    }
06711    if (ast_ignore_pattern(context, callednum))
06712       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06713    if (mm)
06714       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06715    if (!skiplock)
06716       ast_mutex_lock(&iaxsl[callno]);
06717    if (iaxs[callno]) {
06718       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06719       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06720       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06721       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06722    }
06723    if (!skiplock)
06724       ast_mutex_unlock(&iaxsl[callno]);
06725 }

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

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

06728 {
06729    /* Look up for dpreq */
06730    struct dpreq_data *dpr = data;
06731    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06732    if (dpr->callerid)
06733       free(dpr->callerid);
06734    free(dpr);
06735    return NULL;
06736 }

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

Definition at line 4231 of file chan_iax2.c.

References ast_log(), ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, IAX_FLAG_FULL, LOG_DEBUG, memcpy_encrypt(), option_debug, ast_iax2_full_hdr::scallno, and ast_iax2_full_hdr::type.

Referenced by iax2_send(), and update_packet().

04232 {
04233    int padding;
04234    unsigned char *workspace;
04235    workspace = alloca(*datalen + 32);
04236    if (!workspace)
04237       return -1;
04238    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04239       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04240       if (option_debug && iaxdebug)
04241          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
04242       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
04243       padding = 16 + (padding & 0xf);
04244       memcpy(workspace, poo, padding);
04245       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04246       workspace[15] &= 0xf0;
04247       workspace[15] |= (padding & 0xf);
04248       if (option_debug && iaxdebug)
04249          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]);
04250       *datalen += padding;
04251       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
04252       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
04253          memcpy(poo, workspace + *datalen - 32, 32);
04254    } else {
04255       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04256       if (option_debug && iaxdebug)
04257          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
04258       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
04259       padding = 16 + (padding & 0xf);
04260       memcpy(workspace, poo, padding);
04261       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04262       workspace[15] &= 0xf0;
04263       workspace[15] |= (padding & 0x0f);
04264       *datalen += padding;
04265       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
04266       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
04267          memcpy(poo, workspace + *datalen - 32, 32);
04268    }
04269    return 0;
04270 }

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

Definition at line 6135 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

06136 {
06137 #ifdef SCHED_MULTITHREADED
06138    if (schedule_action(__expire_registry, data))
06139 #endif      
06140       __expire_registry(data);
06141    return 0;
06142 }

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

Definition at line 10405 of file chan_iax2.c.

References ast_calloc, ast_channel_defer_dtmf(), ast_channel_undefer_dtmf(), ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_test_flag, ast_waitfor_nandfds(), CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, cache_get_callno_locked(), iax2_dpcache::callno, iax2_registry::callno, dpcache, chan_iax2_pvt::dpentries, iax2_dpcache::expiry, iax2_dpcache::exten, f, iax2_dpcache::flags, free, iax2_dprequest(), IAX_STATE_STARTED, iaxs, iaxsl, LOG_WARNING, iax2_dpcache::next, iax2_dpcache::orig, iax2_dpcache::peer, iax2_dpcache::peercontext, and iax2_dpcache::waiters.

Referenced by iax2_canmatch(), iax2_exec(), iax2_exists(), and iax2_matchmore().

10406 {
10407    struct iax2_dpcache *dp, *prev = NULL, *next;
10408    struct timeval tv;
10409    int x;
10410    int com[2];
10411    int timeout;
10412    int old=0;
10413    int outfd;
10414    int abort;
10415    int callno;
10416    struct ast_channel *c;
10417    struct ast_frame *f;
10418    gettimeofday(&tv, NULL);
10419    dp = dpcache;
10420    while(dp) {
10421       next = dp->next;
10422       /* Expire old caches */
10423       if (ast_tvcmp(tv, dp->expiry) > 0) {
10424             /* It's expired, let it disappear */
10425             if (prev)
10426                prev->next = dp->next;
10427             else
10428                dpcache = dp->next;
10429             if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) {
10430                /* Free memory and go again */
10431                free(dp);
10432             } else {
10433                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);
10434             }
10435             dp = next;
10436             continue;
10437       }
10438       /* We found an entry that matches us! */
10439       if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 
10440          break;
10441       prev = dp;
10442       dp = next;
10443    }
10444    if (!dp) {
10445       /* No matching entry.  Create a new one. */
10446       /* First, can we make a callno? */
10447       callno = cache_get_callno_locked(data);
10448       if (callno < 0) {
10449          ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data);
10450          return NULL;
10451       }
10452       if (!(dp = ast_calloc(1, sizeof(*dp)))) {
10453          ast_mutex_unlock(&iaxsl[callno]);
10454          return NULL;
10455       }
10456       ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext));
10457       ast_copy_string(dp->exten, exten, sizeof(dp->exten));
10458       gettimeofday(&dp->expiry, NULL);
10459       dp->orig = dp->expiry;
10460       /* Expires in 30 mins by default */
10461       dp->expiry.tv_sec += iaxdefaultdpcache;
10462       dp->next = dpcache;
10463       dp->flags = CACHE_FLAG_PENDING;
10464       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10465          dp->waiters[x] = -1;
10466       dpcache = dp;
10467       dp->peer = iaxs[callno]->dpentries;
10468       iaxs[callno]->dpentries = dp;
10469       /* Send the request if we're already up */
10470       if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
10471          iax2_dprequest(dp, callno);
10472       ast_mutex_unlock(&iaxsl[callno]);
10473    }
10474    /* By here we must have a dp */
10475    if (dp->flags & CACHE_FLAG_PENDING) {
10476       /* Okay, here it starts to get nasty.  We need a pipe now to wait
10477          for a reply to come back so long as it's pending */
10478       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) {
10479          /* Find an empty slot */
10480          if (dp->waiters[x] < 0)
10481             break;
10482       }
10483       if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) {
10484          ast_log(LOG_WARNING, "No more waiter positions available\n");
10485          return NULL;
10486       }
10487       if (pipe(com)) {
10488          ast_log(LOG_WARNING, "Unable to create pipe for comm\n");
10489          return NULL;
10490       }
10491       dp->waiters[x] = com[1];
10492       /* Okay, now we wait */
10493       timeout = iaxdefaulttimeout * 1000;
10494       /* Temporarily unlock */
10495       ast_mutex_unlock(&dpcache_lock);
10496       /* Defer any dtmf */
10497       if (chan)
10498          old = ast_channel_defer_dtmf(chan);
10499       abort = 0;
10500       while(timeout) {
10501          c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
10502          if (outfd > -1) {
10503             break;
10504          }
10505          if (c) {
10506             f = ast_read(c);
10507             if (f)
10508                ast_frfree(f);
10509             else {
10510                /* Got hung up on, abort! */
10511                break;
10512                abort = 1;
10513             }
10514          }
10515       }
10516       if (!timeout) {
10517          ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
10518       }
10519       ast_mutex_lock(&dpcache_lock);
10520       dp->waiters[x] = -1;
10521       close(com[1]);
10522       close(com[0]);
10523       if (abort) {
10524          /* Don't interpret anything, just abort.  Not sure what th epoint
10525            of undeferring dtmf on a hung up channel is but hey whatever */
10526          if (!old && chan)
10527             ast_channel_undefer_dtmf(chan);
10528          return NULL;
10529       }
10530       if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
10531          /* Now to do non-independent analysis the results of our wait */
10532          if (dp->flags & CACHE_FLAG_PENDING) {
10533             /* Still pending... It's a timeout.  Wake everybody up.  Consider it no longer
10534                pending.  Don't let it take as long to timeout. */
10535             dp->flags &= ~CACHE_FLAG_PENDING;
10536             dp->flags |= CACHE_FLAG_TIMEOUT;
10537             /* Expire after only 60 seconds now.  This is designed to help reduce backlog in heavily loaded
10538                systems without leaving it unavailable once the server comes back online */
10539             dp->expiry.tv_sec = dp->orig.tv_sec + 60;
10540             for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10541                if (dp->waiters[x] > -1)
10542                   write(dp->waiters[x], "asdf", 4);
10543          }
10544       }
10545       /* Our caller will obtain the rest */
10546       if (!old && chan)
10547          ast_channel_undefer_dtmf(chan);
10548    }
10549    return dp;  
10550 }

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

References __find_callno().

Referenced by iax2_poke_peer(), and socket_process().

01650                                                                                                                                     {
01651 
01652    return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame);
01653 }

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

References __find_callno().

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

01655                                                                                                                                            {
01656 
01657    return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame);
01658 }

static struct iax2_thread* find_idle_thread ( void   )  [static, read]

Definition at line 916 of file chan_iax2.c.

References ast_calloc, ast_cond_init(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_init(), ast_pthread_create, iax2_thread::ffinfo, free, iax2_process_thread(), IAX_TYPE_DYNAMIC, iaxdynamicthreadcount, iaxmaxthreadcount, and thread.

Referenced by __schedule_action(), and socket_read().

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

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

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

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

01150 {
01151    struct iax2_peer *peer = NULL;
01152    struct iax2_peer tmp_peer = {
01153       .name = name,
01154    };
01155 
01156    peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
01157 
01158    /* Now go for realtime if applicable */
01159    if(!peer && realtime)
01160       peer = realtime_peer(name, NULL);
01161 
01162    return peer;
01163 }

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

Definition at line 4031 of file chan_iax2.c.

References iax2_trunk_peer::addr, ast_calloc, ast_inet_ntoa(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), inaddrcmp(), iax2_trunk_peer::lastsent, iax2_trunk_peer::lock, LOG_DEBUG, iax2_trunk_peer::next, option_debug, iax2_trunk_peer::sockfd, tpeers, and iax2_trunk_peer::trunkact.

Referenced by iax2_trunk_queue(), and socket_process().

04032 {
04033    struct iax2_trunk_peer *tpeer;
04034    
04035    /* Finds and locks trunk peer */
04036    ast_mutex_lock(&tpeerlock);
04037    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
04038       /* We don't lock here because tpeer->addr *never* changes */
04039       if (!inaddrcmp(&tpeer->addr, sin)) {
04040          ast_mutex_lock(&tpeer->lock);
04041          break;
04042       }
04043    }
04044    if (!tpeer) {
04045       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
04046          ast_mutex_init(&tpeer->lock);
04047          tpeer->lastsent = 9999;
04048          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
04049          tpeer->trunkact = ast_tvnow();
04050          ast_mutex_lock(&tpeer->lock);
04051          tpeer->next = tpeers;
04052          tpeer->sockfd = fd;
04053          tpeers = tpeer;
04054 #ifdef SO_NO_CHECK
04055          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
04056 #endif
04057          if (option_debug)
04058             ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
04059       }
04060    }
04061    ast_mutex_unlock(&tpeerlock);
04062    return tpeer;
04063 }

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

Definition at line 3847 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03848 {
03849    long ms; /* NOT unsigned */
03850    if (ast_tvzero(iaxs[callno]->rxcore)) {
03851       /* Initialize rxcore time if appropriate */
03852       gettimeofday(&iaxs[callno]->rxcore, NULL);
03853       /* Round to nearest 20ms so traces look pretty */
03854       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03855    }
03856    /* Calculate difference between trunk and channel */
03857    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03858    /* Return as the sum of trunk time and the difference between trunk and real time */
03859    return ms + ts;
03860 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 9014 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

09015 {
09016    struct iax2_context *conl;
09017    while(con) {
09018       conl = con;
09019       con = con->next;
09020       free(conl);
09021    }
09022 }

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

Todo:
: will be removed after the 1.4 relese

Definition at line 10674 of file chan_iax2.c.

References iax2_peer::addr, iax2_registry::addr, ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strdupa, ast_test_flag, iax2_registry::callno, iax2_peer::capability, iax2_peer::expire, find_peer(), iax2_tech, IAX_DYNAMIC, iaxs, peer_status(), peer_unref(), iax2_peer::prefs, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.

10675 {
10676    struct iax2_peer *peer;
10677    char *peername, *colname;
10678 
10679    peername = ast_strdupa(data);
10680 
10681    /* if our channel, return the IP address of the endpoint of current channel */
10682    if (!strcmp(peername,"CURRENTCHANNEL")) {
10683            unsigned short callno;
10684       if (chan->tech != &iax2_tech)
10685          return -1;
10686       callno = PTR_TO_CALLNO(chan->tech_pvt);   
10687       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
10688       return 0;
10689    }
10690 
10691    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
10692       *colname++ = '\0';
10693    else if ((colname = strchr(peername, '|')))
10694       *colname++ = '\0';
10695    else
10696       colname = "ip";
10697 
10698    if (!(peer = find_peer(peername, 1)))
10699       return -1;
10700 
10701    if (!strcasecmp(colname, "ip")) {
10702       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
10703    } else  if (!strcasecmp(colname, "status")) {
10704       peer_status(peer, buf, len); 
10705    } else  if (!strcasecmp(colname, "mailbox")) {
10706       ast_copy_string(buf, peer->mailbox, len);
10707    } else  if (!strcasecmp(colname, "context")) {
10708       ast_copy_string(buf, peer->context, len);
10709    } else  if (!strcasecmp(colname, "expire")) {
10710       snprintf(buf, len, "%d", peer->expire);
10711    } else  if (!strcasecmp(colname, "dynamic")) {
10712       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
10713    } else  if (!strcasecmp(colname, "callerid_name")) {
10714       ast_copy_string(buf, peer->cid_name, len);
10715    } else  if (!strcasecmp(colname, "callerid_num")) {
10716       ast_copy_string(buf, peer->cid_num, len);
10717    } else  if (!strcasecmp(colname, "codecs")) {
10718       ast_getformatname_multiple(buf, len -1, peer->capability);
10719    } else  if (!strncasecmp(colname, "codec[", 6)) {
10720       char *codecnum, *ptr;
10721       int index = 0, codec = 0;
10722       
10723       codecnum = strchr(colname, '[');
10724       *codecnum = '\0';
10725       codecnum++;
10726       if ((ptr = strchr(codecnum, ']'))) {
10727          *ptr = '\0';
10728       }
10729       index = atoi(codecnum);
10730       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
10731          ast_copy_string(buf, ast_getformatname(codec), len);
10732       }
10733    }
10734 
10735    peer_unref(peer);
10736 
10737    return 0;
10738 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 9239 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

09240 {
09241    int methods = 0;
09242    if (strstr(value, "rsa"))
09243       methods |= IAX_AUTH_RSA;
09244    if (strstr(value, "md5"))
09245       methods |= IAX_AUTH_MD5;
09246    if (strstr(value, "plaintext"))
09247       methods |= IAX_AUTH_PLAINTEXT;
09248    return methods;
09249 }

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

Definition at line 1031 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

01032 {
01033    int e;
01034    if (!strcasecmp(s, "aes128"))
01035       e = IAX_ENCRYPT_AES128;
01036    else if (ast_true(s))
01037       e = IAX_ENCRYPT_AES128;
01038    else
01039       e = 0;
01040    return e;
01041 }

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

Definition at line 2641 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02642 {
02643 #ifdef SCHED_MULTITHREADED
02644    if (schedule_action(__get_from_jb, data))
02645 #endif      
02646       __get_from_jb(data);
02647    return 0;
02648 }

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

Definition at line 6893 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

06894 {
06895    struct iax2_pkt_buf *pkt_buf;
06896 
06897    ast_mutex_lock(&thread->lock);
06898 
06899    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06900       ast_mutex_unlock(&thread->lock);
06901 
06902       thread->buf = pkt_buf->buf;
06903       thread->buf_len = pkt_buf->len;
06904       thread->buf_size = pkt_buf->len + 1;
06905       
06906       socket_process(thread);
06907 
06908       thread->buf = NULL;
06909       ast_free(pkt_buf);
06910 
06911       ast_mutex_lock(&thread->lock);
06912    }
06913 
06914    ast_mutex_unlock(&thread->lock);
06915 }

static int handle_error ( void   )  [static]

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

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

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

Acknowledgment received for OUR registration.

Definition at line 5956 of file chan_iax2.c.

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

Referenced by socket_process().

05957 {
05958    struct iax2_registry *reg;
05959    /* Start pessimistic */
05960    char peer[256] = "";
05961    char msgstatus[60];
05962    int refresh = 60;
05963    char ourip[256] = "<Unspecified>";
05964    struct sockaddr_in oldus;
05965    struct sockaddr_in us;
05966    int oldmsgs;
05967 
05968    memset(&us, 0, sizeof(us));
05969    if (ies->apparent_addr)
05970       bcopy(ies->apparent_addr, &us, sizeof(us));
05971    if (ies->username)
05972       ast_copy_string(peer, ies->username, sizeof(peer));
05973    if (ies->refresh)
05974       refresh = ies->refresh;
05975    if (ies->calling_number) {
05976       /* We don't do anything with it really, but maybe we should */
05977    }
05978    reg = iaxs[callno]->reg;
05979    if (!reg) {
05980       ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer);
05981       return -1;
05982    }
05983    memcpy(&oldus, &reg->us, sizeof(oldus));
05984    oldmsgs = reg->messages;
05985    if (inaddrcmp(&reg->addr, sin)) {
05986       ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr));
05987       return -1;
05988    }
05989    memcpy(&reg->us, &us, sizeof(reg->us));
05990    if (ies->msgcount >= 0)
05991       reg->messages = ies->msgcount & 0xffff;      /* only low 16 bits are used in the transmission of the IE */
05992    /* always refresh the registration at the interval requested by the server
05993       we are registering to
05994    */
05995    reg->refresh = refresh;
05996    AST_SCHED_DEL(sched, reg->expire);
05997    reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
05998    if (inaddrcmp(&oldus, &reg->us) || (reg->messages != oldmsgs)) {
05999       if (option_verbose > 2) {
06000          if (reg->messages > 255)
06001             snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8);
06002          else if (reg->messages > 1)
06003             snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages);
06004          else if (reg->messages > 0)
06005             snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n");
06006          else
06007             snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n");
06008          snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
06009          ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus);
06010       }
06011       manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr));
06012    }
06013    reg->regstate = REG_STATE_REGISTERED;
06014    return 0;
06015 }

static int iax2_answer ( struct ast_channel c  )  [static]

Definition at line 3647 of file chan_iax2.c.

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

03648 {
03649    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03650    if (option_debug)
03651       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03652    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03653 }

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

References ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_check_hangup(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_getformatname_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), AST_SOFTHANGUP_DEV, ast_test_flag, ast_verbose(), ast_waitfor_n(), ast_write(), chan_iax2_pvt::bridgecallno, f, ast_frame::frametype, iax2_start_transfer(), iax2_tech, IAX_LINGER_TIMEOUT, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, iaxs, iaxsl, lock_both(), LOG_WARNING, ast_channel::nativeformats, option_verbose, PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, TRANSFER_RELEASED, tv, unlock_both(), and VERBOSE_PREFIX_3.

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

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

Definition at line 3241 of file chan_iax2.c.

References ast_channel::_state, create_addr_info::adsi, chan_iax2_pvt::adsi, ast_channel::adsicpe, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PRES_NUMBER_NOT_AVAILABLE, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, auto_congest(), iax_ie_data::buf, iax2_registry::callno, CALLNO_TO_PTR, capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, create_addr_info::context, ast_channel::context, parsed_dial_string::context, create_addr(), chan_iax2_pvt::encmethods, create_addr_info::encmethods, parsed_dial_string::exten, iax2_datetime(), iax2_sched_add(), IAX_COMMAND_NEW, IAX_IE_ADSICPE, iax_ie_append(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTOANSWER, IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CALLING_ANI, IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_CALLINGPRES, IAX_IE_CALLINGTNS, IAX_IE_CALLINGTON, IAX_IE_CAPABILITY, IAX_IE_CODEC_PREFS, IAX_IE_DATETIME, IAX_IE_DNID, IAX_IE_ENCRYPTION, IAX_IE_FORMAT, IAX_IE_LANGUAGE, IAX_IE_RDNIS, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, IAX_SENDANI, iaxs, iaxsl, chan_iax2_pvt::initid, parsed_dial_string::key, LOG_WARNING, chan_iax2_pvt::maxtime, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, parsed_dial_string::options, create_addr_info::outkey, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, create_addr_info::peercontext, chan_iax2_pvt::pingtime, parsed_dial_string::port, iax_ie_data::pos, create_addr_info::prefs, PTR_TO_CALLNO, iax2_registry::secret, create_addr_info::secret, send_command(), create_addr_info::sockfd, chan_iax2_pvt::sockfd, ast_channel::tech_pvt, create_addr_info::timezone, create_addr_info::username, and parsed_dial_string::username.

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

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

10577 {
10578    int res = 0;
10579    struct iax2_dpcache *dp;
10580 #if 0
10581    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10582 #endif
10583    if ((priority != 1) && (priority != 2))
10584       return 0;
10585    ast_mutex_lock(&dpcache_lock);
10586    dp = find_cache(chan, data, context, exten, priority);
10587    if (dp) {
10588       if (dp->flags & CACHE_FLAG_CANEXIST)
10589          res= 1;
10590    }
10591    ast_mutex_unlock(&dpcache_lock);
10592    if (!dp) {
10593       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10594    }
10595    return res;
10596 }

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

Definition at line 3144 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

03145 {
03146    time_t t;
03147    struct tm tm;
03148    unsigned int tmp;
03149    time(&t);
03150    if (!ast_strlen_zero(tz))
03151       ast_localtime(&t, &tm, tz);
03152    else
03153       ast_localtime(&t, &tm, NULL);
03154    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
03155    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
03156    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
03157    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
03158    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
03159    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
03160    return tmp;
03161 }

static void iax2_destroy ( int  callno  )  [static]

Definition at line 1289 of file chan_iax2.c.

References ao2_ref(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, lastused, ast_channel::lock, LOG_DEBUG, option_debug, chan_iax2_pvt::owner, chan_iax2_pvt::peercallno, remove_by_peercallno(), and update_max_trunk().

Referenced by __attempt_transmit(), __iax2_poke_noanswer(), __unload_module(), delete_users(), iax2_do_register(), iax2_hangup(), iax2_poke_peer(), peer_destructor(), and socket_process().

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

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1219 of file chan_iax2.c.

References ao2_find(), ast_clear_flag, AST_SCHED_DEL, ast_test_flag, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, iax2_user::curauthreq, IAX_MAXAUTHREQ, chan_iax2_pvt::initid, chan_iax2_pvt::jbid, chan_iax2_pvt::lagid, chan_iax2_pvt::pingid, user_unref(), and users.

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

01220 {
01221    /* Decrement AUTHREQ count if needed */
01222    if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
01223       struct iax2_user *user;
01224       struct iax2_user tmp_user = {
01225          .name = pvt->username,
01226       };
01227 
01228       user = ao2_find(users, &tmp_user, OBJ_POINTER);
01229       if (user) {
01230          ast_atomic_fetchadd_int(&user->curauthreq, -1);
01231          user = user_unref(user);       
01232       }
01233 
01234       ast_clear_flag(pvt, IAX_MAXAUTHREQ);
01235    }
01236 
01237    /* No more pings or lagrq's */
01238    AST_SCHED_DEL(sched, pvt->pingid);
01239    AST_SCHED_DEL(sched, pvt->lagid);
01240    AST_SCHED_DEL(sched, pvt->autoid);
01241    AST_SCHED_DEL(sched, pvt->authid);
01242    AST_SCHED_DEL(sched, pvt->initid);
01243    AST_SCHED_DEL(sched, pvt->jbid);
01244 }

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

Definition at line 10763 of file chan_iax2.c.

References iax2_peer::addr, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::defaddr, find_peer(), iax2_peer::historicms, iax2_peer::lastms, LOG_DEBUG, LOG_WARNING, iax2_peer::maxms, option_debug, parse_dial_string(), parsed_dial_string::peer, and peer_unref().

10764 {
10765    struct parsed_dial_string pds;
10766    char *tmp = ast_strdupa(data);
10767    struct iax2_peer *p;
10768    int res = AST_DEVICE_INVALID;
10769 
10770    memset(&pds, 0, sizeof(pds));
10771    parse_dial_string(tmp, &pds);
10772 
10773    if (ast_strlen_zero(pds.peer)) {
10774       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
10775       return res;
10776    }
10777    
10778    if (option_debug > 2)
10779       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
10780 
10781    /* SLD: FIXME: second call to find_peer during registration */
10782    if (!(p = find_peer(pds.peer, 1)))
10783       return res;
10784 
10785    res = AST_DEVICE_UNAVAILABLE;
10786    if (option_debug > 2) 
10787       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
10788          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
10789    
10790    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
10791        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
10792       /* Peer is registered, or have default IP address
10793          and a valid registration */
10794       if (p->historicms == 0 || p->historicms <= p->maxms)
10795          /* let the core figure out whether it is in use or not */
10796          res = AST_DEVICE_UNKNOWN;  
10797    }
10798 
10799    peer_unref(p);
10800 
10801    return res;
10802 }

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

Definition at line 2760 of file chan_iax2.c.

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

02761 {
02762    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02763 }

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

Definition at line 2765 of file chan_iax2.c.

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

02766 {
02767    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02768 }

static int iax2_do_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 < 2 || argc > 3)
04970       return RESULT_SHOWUSAGE;
04971    iaxdebug = 1;
04972    ast_cli(fd, "IAX2 Debugging Enabled\n");
04973    return RESULT_SUCCESS;
04974 }

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

Definition at line 4985 of file chan_iax2.c.

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

04986 {
04987    if (argc < 3 || argc > 4)
04988       return RESULT_SHOWUSAGE;
04989    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04990    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04991    return RESULT_SUCCESS;
04992 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 8733 of file chan_iax2.c.

References iax2_registry::addr, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax_ie_data::buf, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno_locked(), iax2_destroy(), iax2_do_register_s(), iax2_sched_add(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, iaxsl, LOG_DEBUG, LOG_WARNING, NEW_FORCE, option_debug, iax_ie_data::pos, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, send_command(), and iax2_registry::username.

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

08734 {
08735    struct iax_ie_data ied;
08736    if (option_debug && iaxdebug)
08737       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
08738 
08739    if (reg->dnsmgr && 
08740        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
08741       /* Maybe the IP has changed, force DNS refresh */
08742       ast_dnsmgr_refresh(reg->dnsmgr);
08743    }
08744    
08745    /*
08746     * if IP has Changed, free allocated call to create a new one with new IP
08747     * call has the pointer to IP and must be updated to the new one
08748     */
08749    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
08750       ast_mutex_lock(&iaxsl[reg->callno]);
08751       iax2_destroy(reg->callno);
08752       ast_mutex_unlock(&iaxsl[reg->callno]);
08753       reg->callno = 0;
08754    }
08755    if (!reg->addr.sin_addr.s_addr) {
08756       if (option_debug && iaxdebug)
08757          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
08758       /* Setup the next registration attempt */
08759       AST_SCHED_DEL(sched, reg->expire);
08760       reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08761       return -1;
08762    }
08763 
08764    if (!reg->callno) {
08765       if (option_debug)
08766          ast_log(LOG_DEBUG, "Allocate call number\n");
08767       reg->callno = find_callno_locked(0, 0, &reg->addr, NEW_FORCE, defaultsockfd, 0);
08768       if (reg->callno < 1) {
08769          ast_log(LOG_WARNING, "Unable to create call for registration\n");
08770          return -1;
08771       } else if (option_debug)
08772          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
08773       iaxs[reg->callno]->reg = reg;
08774       ast_mutex_unlock(&iaxsl[reg->callno]);
08775    }
08776    /* Schedule the next registration attempt */
08777    AST_SCHED_DEL(sched, reg->expire);
08778    /* Setup the next registration a little early */
08779    reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08780    /* Send the request */
08781    memset(&ied, 0, sizeof(ied));
08782    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
08783    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
08784    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
08785    reg->regstate = REG_STATE_REGSENT;
08786    return 0;
08787 }

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

Definition at line 5804 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05805 {
05806 #ifdef SCHED_MULTITHREADED
05807    if (schedule_action(__iax2_do_register_s, data))
05808 #endif      
05809       __iax2_do_register_s(data);
05810    return 0;
05811 }

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

Definition at line 4976 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04977 {
04978    if (argc < 3 || argc > 4)
04979       return RESULT_SHOWUSAGE;
04980    iaxtrunkdebug = 1;
04981    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04982    return RESULT_SUCCESS;
04983 }

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

Definition at line 6504 of file chan_iax2.c.

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

Referenced by find_cache(), and socket_process().

06505 {
06506    struct iax_ie_data ied;
06507    /* Auto-hangup with 30 seconds of inactivity */
06508    AST_SCHED_DEL(sched, iaxs[callno]->autoid);
06509    iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06510    memset(&ied, 0, sizeof(ied));
06511    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06512    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06513    dp->flags |= CACHE_FLAG_TRANSMITTED;
06514 }

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

10623 {
10624    char odata[256];
10625    char req[256];
10626    char *ncontext;
10627    struct iax2_dpcache *dp;
10628    struct ast_app *dial;
10629 #if 0
10630    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);
10631 #endif
10632    if (priority == 2) {
10633       /* Indicate status, can be overridden in dialplan */
10634       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
10635       if (dialstatus) {
10636          dial = pbx_findapp(dialstatus);
10637          if (dial) 
10638             pbx_exec(chan, dial, "");
10639       }
10640       return -1;
10641    } else if (priority != 1)
10642       return -1;
10643    ast_mutex_lock(&dpcache_lock);
10644    dp = find_cache(chan, data, context, exten, priority);
10645    if (dp) {
10646       if (dp->flags & CACHE_FLAG_EXISTS) {
10647          ast_copy_string(odata, data, sizeof(odata));
10648          ncontext = strchr(odata, '/');
10649          if (ncontext) {
10650             *ncontext = '\0';
10651             ncontext++;
10652             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
10653          } else {
10654             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
10655          }
10656          if (option_verbose > 2)
10657             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
10658       } else {
10659          ast_mutex_unlock(&dpcache_lock);
10660          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
10661          return -1;
10662       }
10663    }
10664    ast_mutex_unlock(&dpcache_lock);
10665    dial = pbx_findapp("Dial");
10666    if (dial) {
10667       return pbx_exec(chan, dial, req);
10668    } else {
10669       ast_log(LOG_WARNING, "No dial application registered\n");
10670    }
10671    return -1;
10672 }

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

10554 {
10555    struct iax2_dpcache *dp;
10556    int res = 0;
10557 #if 0
10558    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10559 #endif
10560    if ((priority != 1) && (priority != 2))
10561       return 0;
10562    ast_mutex_lock(&dpcache_lock);
10563    dp = find_cache(chan, data, context, exten, priority);
10564    if (dp) {
10565       if (dp->flags & CACHE_FLAG_EXISTS)
10566          res= 1;
10567    }
10568    ast_mutex_unlock(&dpcache_lock);
10569    if (!dp) {
10570       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10571    }
10572    return res;
10573 }

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

Definition at line 2787 of file chan_iax2.c.

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

02788 {
02789    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02790    ast_mutex_lock(&iaxsl[callno]);
02791    if (iaxs[callno])
02792       iaxs[callno]->owner = newchan;
02793    else
02794       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02795    ast_mutex_unlock(&iaxsl[callno]);
02796    return 0;
02797 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

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

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

01190 {
01191    struct iax2_peer *peer = NULL;
01192    int res = 0;
01193    struct ao2_iterator i;
01194 
01195    i = ao2_iterator_init(peers, 0);
01196    while ((peer = ao2_iterator_next(&i))) {
01197       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
01198           (peer->addr.sin_port == sin.sin_port)) {
01199          ast_copy_string(host, peer->name, len);
01200          peer_unref(peer);
01201          res = 1;
01202          break;
01203       }
01204       peer_unref(peer);
01205    }
01206 
01207    if (!peer) {
01208       peer = realtime_peer(NULL, &sin);
01209       if (peer) {
01210          ast_copy_string(host, peer->name, len);
01211          peer_unref(peer);
01212          res = 1;
01213       }
01214    }
01215 
01216    return res;
01217 }

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

03723 {
03724    struct iax2_peer *peer;
03725    int res = 0;
03726    struct ao2_iterator i;
03727 
03728    i = ao2_iterator_init(peers, 0);
03729    while ((peer = ao2_iterator_next(&i))) {
03730       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03731           (peer->addr.sin_port == sin.sin_port)) {
03732          res = ast_test_flag(peer, IAX_TRUNK);
03733          peer_unref(peer);
03734          break;
03735       }
03736       peer_unref(peer);
03737    }
03738 
03739    return res;
03740 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 3388 of file chan_iax2.c.

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

03389 {
03390    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03391    int alreadygone;
03392    struct iax_ie_data ied;
03393    memset(&ied, 0, sizeof(ied));
03394    ast_mutex_lock(&iaxsl[callno]);
03395    if (callno && iaxs[callno]) {
03396       if (option_debug)
03397          ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
03398       alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
03399       /* Send the hangup unless we have had a transmission error or are already gone */
03400       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
03401       if (!iaxs[callno]->error && !alreadygone) {
03402          send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
03403          if (!iaxs[callno]) {
03404             ast_mutex_unlock(&iaxsl[callno]);
03405             return 0;
03406          }
03407       }
03408       /* Explicitly predestroy it */
03409       iax2_predestroy(callno);
03410       /* If we were already gone to begin with, destroy us now */
03411       if (alreadygone && iaxs[callno]) {
03412          if (option_debug)
03413             ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
03414          iax2_destroy(callno);
03415       }
03416    }
03417    ast_mutex_unlock(&iaxsl[callno]);
03418    if (option_verbose > 2) 
03419       ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
03420    return 0;
03421 }

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

Definition at line 3655 of file chan_iax2.c.

References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, DEADLOCK_AVOIDANCE, iaxs, iaxsl, LOG_DEBUG, option_debug, chan_iax2_pvt::peercallno, PTR_TO_CALLNO, send_command(), and ast_channel::tech_pvt.

03656 {
03657    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03658    struct chan_iax2_pvt *pvt;
03659    int res = 0;
03660 
03661    if (option_debug && iaxdebug)
03662       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03663 
03664    ast_mutex_lock(&iaxsl[callno]);
03665    pvt = iaxs[callno];
03666 
03667    if (!pvt->peercallno) {
03668       /* We don't know the remote side's call number, yet.  :( */
03669       int count = 10;
03670       while (count-- && pvt && !pvt->peercallno) {
03671          DEADLOCK_AVOIDANCE(&iaxsl[callno]);
03672          pvt = iaxs[callno];
03673       }
03674       if (!pvt->peercallno) {
03675          res = -1;
03676          goto done;
03677       }
03678    }
03679 
03680    switch (condition) {
03681    case AST_CONTROL_HOLD:
03682       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03683          ast_moh_start(c, data, pvt->mohinterpret);
03684          goto done;
03685       }
03686       break;
03687    case AST_CONTROL_UNHOLD:
03688       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03689          ast_moh_stop(c);
03690          goto done;
03691       }
03692    }
03693 
03694    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03695 
03696 done:
03697    ast_mutex_unlock(&iaxsl[callno]);
03698 
03699    return res;
03700 }

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

10600 {
10601    int res = 0;
10602    struct iax2_dpcache *dp;
10603 #if 0
10604    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10605 #endif
10606    if ((priority != 1) && (priority != 2))
10607       return 0;
10608    ast_mutex_lock(&dpcache_lock);
10609    dp = find_cache(chan, data, context, exten, priority);
10610    if (dp) {
10611       if (dp->flags & CACHE_FLAG_MATCHMORE)
10612          res= 1;
10613    }
10614    ast_mutex_unlock(&dpcache_lock);
10615    if (!dp) {
10616       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10617    }
10618    return res;
10619 }

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

Definition at line 4994 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04995 {
04996    if (argc < 3 || argc > 4)
04997       return RESULT_SHOWUSAGE;
04998    iaxdebug = 0;
04999    ast_cli(fd, "IAX2 Debugging Disabled\n");
05000    return RESULT_SUCCESS;
05001 }

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

Definition at line 5012 of file chan_iax2.c.

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

05013 {
05014    if (argc < 4 || argc > 5)
05015       return RESULT_SHOWUSAGE;
05016    jb_setoutput(jb_error_output, jb_warning_output, NULL);
05017    jb_debug_output("\n");
05018    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
05019    return RESULT_SUCCESS;
05020 }

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

Definition at line 5003 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

05004 {
05005    if (argc < 4 || argc > 5)
05006       return RESULT_SHOWUSAGE;
05007    iaxtrunkdebug = 0;
05008    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
05009    return RESULT_SUCCESS;
05010 }

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

Definition at line 8931 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08932 {
08933    struct iax2_peer *peer = (struct iax2_peer *)data;
08934    peer->pokeexpire = -1;
08935 #ifdef SCHED_MULTITHREADED
08936    if (schedule_action(__iax2_poke_noanswer, data))
08937 #endif      
08938       __iax2_poke_noanswer(data);
08939    peer_unref(peer);
08940    return 0;
08941 }

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

Definition at line 8952 of file chan_iax2.c.

References iax2_peer::addr, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), iax2_peer::callno, iax2_registry::callno, DEFAULT_MAXMS, iax2_peer::dnsmgr, find_callno(), iax2_peer::historicms, iax2_destroy(), iax2_poke_noanswer(), iax2_sched_add(), IAX_COMMAND_POKE, iaxs, iaxsl, iax2_peer::lastms, LOG_NOTICE, LOG_WARNING, iax2_peer::maxms, NEW_FORCE, peer_ref(), peer_unref(), chan_iax2_pvt::peerpoke, chan_iax2_pvt::pingtime, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, send_command(), and iax2_peer::sockfd.

Referenced by __iax2_poke_peer_s(), iax2_poke_peer_cb(), poke_all_peers(), reg_source_db(), and update_registry().

08953 {
08954    int callno;
08955    if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) {
08956       /* IF we have no IP without dnsmgr, or this isn't to be monitored, return
08957         immediately after clearing things out */
08958       peer->lastms = 0;
08959       peer->historicms = 0;
08960       peer->pokeexpire = -1;
08961       peer->callno = 0;
08962       return 0;
08963    }
08964 
08965    /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */
08966    if ((callno = peer->callno) > 0) {
08967       ast_log(LOG_NOTICE, "Still have a callno...\n");
08968       ast_mutex_lock(&iaxsl[callno]);
08969       iax2_destroy(callno);
08970       ast_mutex_unlock(&iaxsl[callno]);
08971    }
08972    if (heldcall)
08973       ast_mutex_unlock(&iaxsl[heldcall]);
08974    callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0);
08975    if (heldcall)
08976       ast_mutex_lock(&iaxsl[heldcall]);
08977    if (peer->callno < 1) {
08978       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
08979       return -1;
08980    }
08981 
08982    /* Speed up retransmission times for this qualify call */
08983    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
08984    iaxs[peer->callno]->peerpoke = peer;
08985    
08986    /* Remove any pending pokeexpire task */
08987    if (peer->pokeexpire > -1) {
08988       if (!ast_sched_del(sched, peer->pokeexpire)) {
08989          peer->pokeexpire = -1;
08990          peer_unref(peer);
08991       }
08992    }
08993 
08994    /* Queue up a new task to handle no reply */
08995    /* If the host is already unreachable then use the unreachable interval instead */
08996    if (peer->lastms < 0) {
08997       peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
08998    } else
08999       peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
09000 
09001    if (peer->pokeexpire == -1)
09002       peer_unref(peer);
09003 
09004    /* And send the poke */
09005    ast_mutex_lock(&iaxsl[callno]);
09006    if (iaxs[callno]) {
09007       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
09008    }
09009    ast_mutex_unlock(&iaxsl[callno]);
09010 
09011    return 0;
09012 }

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

Definition at line 8943 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

08944 {
08945    struct iax2_peer *peer = obj;
08946 
08947    iax2_poke_peer(peer, 0);
08948 
08949    return 0;
08950 }

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

Definition at line 6544 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

06545 {
06546    struct iax2_peer *peer = (struct iax2_peer *)data;
06547    peer->pokeexpire = -1;
06548 #ifdef SCHED_MULTITHREADED
06549    if (schedule_action(__iax2_poke_peer_s, data))
06550 #endif      
06551       __iax2_poke_peer_s(data);
06552    return 0;
06553 }

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

02123 {
02124    struct ast_channel *c;
02125    struct chan_iax2_pvt *pvt = iaxs[callno];
02126 
02127    if (!pvt)
02128       return -1;
02129    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
02130       iax2_destroy_helper(pvt);
02131       ast_set_flag(pvt, IAX_ALREADYGONE); 
02132    }
02133    c = pvt->owner;
02134    if (c) {
02135       c->tech_pvt = NULL;
02136       iax2_queue_hangup(callno);
02137       pvt->owner = NULL;
02138       ast_module_unref(ast_module_info->self);
02139    }
02140    return 0;
02141 }

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

Note:
For some reason, idle threads are exiting without being removed from an idle list, which is causing memory corruption. Forcibly remove it from the list, if it's there.

Definition at line 8608 of file chan_iax2.c.

References ast_cond_timedwait(), ast_cond_wait(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_tvadd(), handle_deferred_full_frames(), iax2_process_thread_cleanup(), IAX_IOSTATE_IDLE, IAX_IOSTATE_PROCESSING, IAX_IOSTATE_READY, IAX_IOSTATE_SCHEDREADY, IAX_TYPE_DYNAMIC, iaxactivethreadcount, iaxdynamicthreadcount, insert_idle_thread(), socket_process(), t, and thread.

Referenced by find_idle_thread(), and start_network_thread().

08609 {
08610    struct iax2_thread *thread = data;
08611    struct timeval tv;
08612    struct timespec ts;
08613    int put_into_idle = 0;
08614 
08615    ast_atomic_fetchadd_int(&iaxactivethreadcount,1);
08616    pthread_cleanup_push(iax2_process_thread_cleanup, data);
08617    for(;;) {
08618       /* Wait for something to signal us to be awake */
08619       ast_mutex_lock(&thread->lock);
08620 
08621       /* Flag that we're ready to accept signals */
08622       thread->ready_for_signal = 1;
08623       
08624       /* Put into idle list if applicable */
08625       if (put_into_idle)
08626          insert_idle_thread(thread);
08627 
08628       if (thread->type == IAX_TYPE_DYNAMIC) {
08629          struct iax2_thread *t = NULL;
08630          /* Wait to be signalled or time out */
08631          tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08632          ts.tv_sec = tv.tv_sec;
08633          ts.tv_nsec = tv.tv_usec * 1000;
08634          if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
08635             /* This thread was never put back into the available dynamic
08636              * thread list, so just go away. */
08637             if (!put_into_idle) {
08638                ast_mutex_unlock(&thread->lock);
08639                break;
08640             }
08641             AST_LIST_LOCK(&dynamic_list);
08642             /* Account for the case where this thread is acquired *right* after a timeout */
08643             if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list)))
08644                iaxdynamicthreadcount--;
08645             AST_LIST_UNLOCK(&dynamic_list);
08646             if (t) {
08647                /* This dynamic thread timed out waiting for a task and was
08648                 * not acquired immediately after the timeout, 
08649                 * so it's time to go away. */
08650                ast_mutex_unlock(&thread->lock);
08651                break;
08652             }
08653             /* Someone grabbed our thread *right* after we timed out.
08654              * Wait for them to set us up with something to do and signal
08655              * us to continue. */
08656             tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08657             ts.tv_sec = tv.tv_sec;
08658             ts.tv_nsec = tv.tv_usec * 1000;
08659             if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT)
08660             {
08661                ast_mutex_unlock(&thread->lock);
08662                break;
08663             }
08664          }
08665       } else {
08666          ast_cond_wait(&thread->cond, &thread->lock);
08667       }
08668 
08669       /* Go back into our respective list */
08670       put_into_idle = 1;
08671 
08672       ast_mutex_unlock(&thread->lock);
08673 
08674       if (thread->iostate == IAX_IOSTATE_IDLE)
08675          continue;
08676 
08677       /* Add ourselves to the active list now */
08678       AST_LIST_LOCK(&active_list);
08679       AST_LIST_INSERT_HEAD(&active_list, thread, list);
08680       AST_LIST_UNLOCK(&active_list);
08681 
08682       /* See what we need to do */
08683       switch(thread->iostate) {
08684       case IAX_IOSTATE_READY:
08685          thread->actions++;
08686          thread->iostate = IAX_IOSTATE_PROCESSING;
08687          socket_process(thread);
08688          handle_deferred_full_frames(thread);
08689          break;
08690       case IAX_IOSTATE_SCHEDREADY:
08691          thread->actions++;
08692          thread->iostate = IAX_IOSTATE_PROCESSING;
08693 #ifdef SCHED_MULTITHREADED
08694          thread->schedfunc(thread->scheddata);
08695 #endif      
08696          break;
08697       }
08698       time(&thread->checktime);
08699       thread->iostate = IAX_IOSTATE_IDLE;
08700 #ifdef DEBUG_SCHED_MULTITHREAD
08701       thread->curfunc[0]='\0';
08702 #endif      
08703 
08704       /* Now... remove ourselves from the active list, and return to the idle list */
08705       AST_LIST_LOCK(&active_list);
08706       AST_LIST_REMOVE(&active_list, thread, list);
08707       AST_LIST_UNLOCK(&active_list);
08708 
08709       /* Make sure another frame didn't sneak in there after we thought we were done. */
08710       handle_deferred_full_frames(thread);
08711    }
08712 
08713    /*!\note For some reason, idle threads are exiting without being removed
08714     * from an idle list, which is causing memory corruption.  Forcibly remove
08715     * it from the list, if it's there.
08716     */
08717    AST_LIST_LOCK(&idle_list);
08718    AST_LIST_REMOVE(&idle_list, thread, list);
08719    AST_LIST_UNLOCK(&idle_list);
08720 
08721    AST_LIST_LOCK(&dynamic_list);
08722    AST_LIST_REMOVE(&dynamic_list, thread, list);
08723    AST_LIST_UNLOCK(&dynamic_list);
08724 
08725    /* I am exiting here on my own volition, I need to clean up my own data structures
08726    * Assume that I am no longer in any of the lists (idle, active, or dynamic)
08727    */
08728    pthread_cleanup_pop(1);
08729 
08730    return NULL;
08731 }

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8599 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08600 {
08601    struct iax2_thread *thread = data;
08602    ast_mutex_destroy(&thread->lock);
08603    ast_cond_destroy(&thread->cond);
08604    free(thread);
08605    ast_atomic_dec_and_test(&iaxactivethreadcount);
08606 }

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

Definition at line 8886 of file chan_iax2.c.

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

08887 {
08888    int force = 0;
08889    int res;
08890    if (argc < 4)
08891       return RESULT_SHOWUSAGE;
08892    if ((argc > 4)) {
08893       if (!strcasecmp(argv[4], "forced"))
08894          force = 1;
08895       else
08896          return RESULT_SHOWUSAGE;
08897    }
08898    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08899    if (res < 0)
08900       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08901    else if (res < 1)
08902       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08903    else
08904       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08905    return RESULT_SUCCESS;
08906 }

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

Definition at line 8789 of file chan_iax2.c.

References iax_prov_complete_template().

08790 {
08791    if (pos != 3)
08792       return NULL;
08793    return iax_prov_complete_template(line, word, pos, state);
08794 }

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

Definition at line 8796 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_mutex_unlock(), AST_SCHED_DEL, ast_set_flag, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, iax2_registry::callno, create_addr(), find_callno_locked(), iax2_sched_add(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), iaxs, iaxsl, LOG_DEBUG, NEW_FORCE, option_debug, iax_ie_data::pos, send_command(), and create_addr_info::sockfd.

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

08797 {
08798    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
08799       is found for template */
08800    struct iax_ie_data provdata;
08801    struct iax_ie_data ied;
08802    unsigned int sig;
08803    struct sockaddr_in sin;
08804    int callno;
08805    struct create_addr_info cai;
08806 
08807    memset(&cai, 0, sizeof(cai));
08808 
08809    if (option_debug)
08810       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
08811 
08812    if (iax_provision_build(&provdata, &sig, template, force)) {
08813       if (option_debug)
08814          ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
08815       return 0;
08816    }
08817 
08818    if (end) {
08819       memcpy(&sin, end, sizeof(sin));
08820       cai.sockfd = sockfd;
08821    } else if (create_addr(dest, NULL, &sin, &cai))
08822       return -1;
08823 
08824    /* Build the rest of the message */
08825    memset(&ied, 0, sizeof(ied));
08826    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
08827 
08828    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
08829    if (!callno)
08830       return -1;
08831 
08832    if (iaxs[callno]) {
08833       /* Schedule autodestruct in case they don't ever give us anything back */
08834       AST_SCHED_DEL(sched, iaxs[callno]->autoid);
08835       iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
08836       ast_set_flag(iaxs[callno], IAX_PROVISION);
08837       /* Got a call number now, so go ahead and send the provisioning information */
08838       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
08839    }
08840    ast_mutex_unlock(&iaxsl[callno]);
08841 
08842    return 1;
08843 }

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

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

02258 {
02259    struct iax2_peer *peer;
02260 
02261    if (argc != 4)
02262         return RESULT_SHOWUSAGE;
02263    if (!strcmp(argv[3],"all")) {
02264       reload_config();
02265       ast_cli(fd, "OK cache is flushed.\n");
02266    } else if ((peer = find_peer(argv[3], 0))) {
02267       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
02268          ast_set_flag(peer, IAX_RTAUTOCLEAR);
02269          expire_registry(peer_ref(peer));
02270          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
02271       } else {
02272          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
02273       }
02274       peer_unref(peer);
02275    } else {
02276       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
02277    }
02278    
02279    return RESULT_SUCCESS;
02280 }

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

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

Referenced by socket_process().

01734 {
01735    for (;;) {
01736       if (iaxs[callno] && iaxs[callno]->owner) {
01737          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01738             /* Avoid deadlock by pausing and trying again */
01739             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01740          } else {
01741             ast_queue_control_data(iaxs[callno]->owner, control, data, datalen);
01742             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01743             break;
01744          }
01745       } else
01746          break;
01747    }
01748    return 0;
01749 }

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

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

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

01671 {
01672    for (;;) {
01673       if (iaxs[callno] && iaxs[callno]->owner) {
01674          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01675             /* Avoid deadlock by pausing and trying again */
01676             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01677          } else {
01678             ast_queue_frame(iaxs[callno]->owner, f);
01679             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01680             break;
01681          }
01682       } else
01683          break;
01684    }
01685    return 0;
01686 }

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

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

Referenced by iax2_predestroy().

01702 {
01703    for (;;) {
01704       if (iaxs[callno] && iaxs[callno]->owner) {
01705          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01706             /* Avoid deadlock by pausing and trying again */
01707             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01708          } else {
01709             ast_queue_hangup(iaxs[callno]->owner);
01710             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01711             break;
01712          }
01713       } else
01714          break;
01715    }
01716    return 0;
01717 }

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

Definition at line 3449 of file chan_iax2.c.

References ast_log(), ast_null_frame, LOG_NOTICE, and option_verbose.

03450 {
03451    if (option_verbose > 3)
03452        ast_log(LOG_NOTICE, "I should never be called!\n");
03453    return &ast_null_frame;
03454 }

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

Definition at line 6017 of file chan_iax2.c.

References iax2_registry::addr, ast_calloc, ast_dnsmgr_lookup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), copy(), iax2_registry::dnsmgr, iax2_registry::expire, free, hostname, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, LOG_WARNING, iax2_registry::refresh, iax2_registry::secret, strsep(), and iax2_registry::username.

Referenced by set_config().

06018 {
06019    struct iax2_registry *reg;
06020    char copy[256];
06021    char *username, *hostname, *secret;
06022    char *porta;
06023    char *stringp=NULL;
06024    
06025    if (!value)
06026       return -1;
06027    ast_copy_string(copy, value, sizeof(copy));
06028    stringp=copy;
06029    username = strsep(&stringp, "@");
06030    hostname = strsep(&stringp, "@");
06031    if (!hostname) {
06032       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
06033       return -1;
06034    }
06035    stringp=username;
06036    username = strsep(&stringp, ":");
06037    secret = strsep(&stringp, ":");
06038    stringp=hostname;
06039    hostname = strsep(&stringp, ":");
06040    porta = strsep(&stringp, ":");
06041    
06042    if (porta && !atoi(porta)) {
06043       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
06044       return -1;
06045    }
06046    if (!(reg = ast_calloc(1, sizeof(*reg))))
06047       return -1;
06048    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
06049       free(reg);
06050       return -1;
06051    }
06052    ast_copy_string(reg->username, username, sizeof(reg->username));
06053    if (secret)
06054       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
06055    reg->expire = -1;
06056    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
06057    reg->addr.sin_family = AF_INET;
06058    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
06059    AST_LIST_LOCK(&registrations);
06060    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
06061    AST_LIST_UNLOCK(&registrations);
06062    
06063    return 0;
06064 }

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

Definition at line 10322 of file chan_iax2.c.

References reload_config().

10323 {
10324    return reload_config();
10325 }

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

Definition at line 9024 of file chan_iax2.c.

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

09025 {
09026    int callno;
09027    int res;
09028    int fmt, native;
09029    struct sockaddr_in sin;
09030    struct ast_channel *c;
09031    struct parsed_dial_string pds;
09032    struct create_addr_info cai;
09033    char *tmpstr;
09034 
09035    memset(&pds, 0, sizeof(pds));
09036    tmpstr = ast_strdupa(data);
09037    parse_dial_string(tmpstr, &pds);
09038 
09039    if (ast_strlen_zero(pds.peer)) {
09040       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
09041       return NULL;
09042    }
09043           
09044    memset(&cai, 0, sizeof(cai));
09045    cai.capability = iax2_capability;
09046 
09047    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
09048    
09049    /* Populate our address from the given */
09050    if (create_addr(pds.peer, NULL, &sin, &cai)) {
09051       *cause = AST_CAUSE_UNREGISTERED;
09052       return NULL;
09053    }
09054 
09055    if (pds.port)
09056       sin.sin_port = htons(atoi(pds.port));
09057 
09058    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
09059    if (callno < 1) {
09060       ast_log(LOG_WARNING, "Unable to create call\n");
09061       *cause = AST_CAUSE_CONGESTION;
09062       return NULL;
09063    }
09064 
09065    /* If this is a trunk, update it now */
09066    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
09067    if (ast_test_flag(&cai, IAX_TRUNK)) {
09068       int new_callno;
09069       if ((new_callno = make_trunk(callno, 1)) != -1)
09070          callno = new_callno;
09071    }
09072    iaxs[callno]->maxtime = cai.maxtime;
09073    if (cai.found)
09074       ast_string_field_set(iaxs[callno], host, pds.peer);
09075 
09076    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
09077 
09078    ast_mutex_unlock(&iaxsl[callno]);
09079 
09080    if (c) {
09081       /* Choose a format we can live with */
09082       if (c->nativeformats & format) 
09083          c->nativeformats &= format;
09084       else {
09085          native = c->nativeformats;
09086          fmt = format;
09087          res = ast_translator_best_choice(&fmt, &native);
09088          if (res < 0) {
09089             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
09090                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
09091             ast_hangup(c);
09092             return NULL;
09093          }
09094          c->nativeformats = native;
09095       }
09096       c->readformat = ast_best_codec(c->nativeformats);
09097       c->writeformat = c->readformat;
09098    }
09099 
09100    return c;
09101 }

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

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

References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_test_flag, calc_timestamp(), ast_iax2_mini_hdr::callno, ast_iax2_video_hdr::callno, chan_iax2_pvt::callno, iax_frame::callno, compress_subclass(), ast_iax2_full_hdr::csub, iax_frame::data, ast_frame::data, iax_frame::datalen, ast_frame::datalen, ast_iax2_full_hdr::dcallno, iax_frame::dcallno, DIRECTION_OUTGRESS, iax_frame::ecx, chan_iax2_pvt::ecx, chan_iax2_pvt::encmethods, iax_frame::encmethods, encrypt_frame(), iax_frame::final, ast_frame::frametype, iax2_transmit(), iax2_trunk_queue(), IAX_COMMAND_ACK, IAX_ENCRYPTED, IAX_FLAG_FULL, iax_frame_new(), iax_frame_wrap(), IAX_KEYPOPULATED, iax_showframe(), IAX_TRUNK, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, chan_iax2_pvt::lastsent, chan_iax2_pvt::lastvsent, LOG_WARNING, MAX_RETRY_TIME, MIN_RETRY_TIME, chan_iax2_pvt::mydcx, iax_frame::mydcx, ast_iax2_full_hdr::oseqno, chan_iax2_pvt::oseqno, iax_frame::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, iax_frame::retries, iax_frame::retrytime, ast_iax2_full_hdr::scallno, iax_frame::semirand, chan_iax2_pvt::semirand, send_packet(), ast_frame::subclass, chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, iax_frame::transfer, TRANSFER_MEDIAPASS, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, ast_iax2_mini_hdr::ts, ast_iax2_video_hdr::ts, ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_full_hdr::type, and ast_iax2_video_hdr::zeros.

Referenced by __send_command(), iax2_write(), and socket_process().

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

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

Definition at line 2782 of file chan_iax2.c.

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

02783 {
02784    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02785 }

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

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

Definition at line 2770 of file chan_iax2.c.

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

02771 {
02772    
02773    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02774       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02775 }

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

Definition at line 3423 of file chan_iax2.c.

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

03424 {
03425    struct ast_option_header *h;
03426    int res;
03427 
03428    switch (option) {
03429    case AST_OPTION_TXGAIN:
03430    case AST_OPTION_RXGAIN:
03431       /* these two cannot be sent, because they require a result */
03432       errno = ENOSYS;
03433       return -1;
03434    default:
03435       if (!(h = ast_malloc(datalen + sizeof(*h))))
03436          return -1;
03437 
03438       h->flag = AST_OPTION_FLAG_REQUEST;
03439       h->option = htons(option);
03440       memcpy(h->data, data, datalen);
03441       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03442                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03443                  datalen + sizeof(*h), -1);
03444       free(h);
03445       return res;
03446    }
03447 }

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

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

02462 {
02463    struct iax2_dpcache *dp;
02464    char tmp[1024], *pc;
02465    int s;
02466    int x,y;
02467    struct timeval tv;
02468    gettimeofday(&tv, NULL);
02469    ast_mutex_lock(&dpcache_lock);
02470    dp = dpcache;
02471    ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02472    while(dp) {
02473       s = dp->expiry.tv_sec - tv.tv_sec;
02474       tmp[0] = '\0';
02475       if (dp->flags & CACHE_FLAG_EXISTS)
02476          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02477       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02478          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02479       if (dp->flags & CACHE_FLAG_CANEXIST)
02480          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02481       if (dp->flags & CACHE_FLAG_PENDING)
02482          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02483       if (dp->flags & CACHE_FLAG_TIMEOUT)
02484          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02485       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02486          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02487       if (dp->flags & CACHE_FLAG_MATCHMORE)
02488          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02489       if (dp->flags & CACHE_FLAG_UNKNOWN)
02490          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02491       /* Trim trailing pipe */
02492       if (!ast_strlen_zero(tmp))
02493          tmp[strlen(tmp) - 1] = '\0';
02494       else
02495          ast_copy_string(tmp, "(none)", sizeof(tmp));
02496       y=0;
02497       pc = strchr(dp->peercontext, '@');
02498       if (!pc)
02499          pc = dp->peercontext;
02500       else
02501          pc++;
02502       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
02503          if (dp->waiters[x] > -1)
02504             y++;
02505       if (s > 0)
02506          ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02507       else
02508          ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02509       dp = dp->next;
02510    }
02511    ast_mutex_unlock(&dpcache_lock);
02512    return RESULT_SUCCESS;
02513 }

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

Definition at line 4832 of file chan_iax2.c.

References iax2_registry::addr, ARRAY_LEN, ast_cli(), ast_getformatname(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, jb_info::current, iax_rr::delay, FORMAT, FORMAT2, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), jb_info::jitter, jb_info::min, chan_iax2_pvt::remote_rr, RESULT_SHOWUSAGE, RESULT_SUCCESS, and S_OR.

04833 {
04834 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04835 #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"
04836 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04837    int x;
04838    int numchans = 0;
04839 
04840    if (argc != 3)
04841       return RESULT_SHOWUSAGE;
04842    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04843    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04844       ast_mutex_lock(&iaxsl[x]);
04845       if (iaxs[x]) {
04846          int lag, jitter, localdelay;
04847          jb_info jbinfo;
04848          
04849          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04850             jb_getinfo(iaxs[x]->jb, &jbinfo);
04851             jitter = jbinfo.jitter;
04852             localdelay = jbinfo.current - jbinfo.min;
04853          } else {
04854             jitter = -1;
04855             localdelay = 0;
04856          }
04857          lag = iaxs[x]->remote_rr.delay;
04858          ast_cli(fd, FORMAT,
04859             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04860             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04861             S_OR(iaxs[x]->username, "(None)"),
04862             iaxs[x]->callno, iaxs[x]->peercallno,
04863             iaxs[x]->oseqno, iaxs[x]->iseqno,
04864             lag,
04865             jitter,
04866             localdelay,
04867             ast_getformatname(iaxs[x]->voiceformat) );
04868          numchans++;
04869       }
04870       ast_mutex_unlock(&iaxsl[x]);
04871    }
04872    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04873    return RESULT_SUCCESS;
04874 #undef FORMAT
04875 #undef FORMAT2
04876 #undef FORMATB
04877 }

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

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

04744 {
04745 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04746 #if !defined(__FreeBSD__)
04747 #define FORMAT "%-15.15s  %-15d %-15d\n"
04748 #else /* __FreeBSD__ */
04749 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04750 #endif /* __FreeBSD__ */
04751    struct iax_firmware *cur;
04752    if ((argc != 3) && (argc != 4))
04753       return RESULT_SHOWUSAGE;
04754    ast_mutex_lock(&waresl.lock);
04755    
04756    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04757    for (cur = waresl.wares;cur;cur = cur->next) {
04758       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04759          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04760             (int)ntohl(cur->fwh->datalen));
04761    }
04762    ast_mutex_unlock(&waresl.lock);
04763    return RESULT_SUCCESS;
04764 #undef FORMAT
04765 #undef FORMAT2
04766 }

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

Definition at line 4955 of file chan_iax2.c.

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

04956 {
04957    int numchans = 0;
04958    if (argc != 3)
04959       return RESULT_SHOWUSAGE;
04960    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04961    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04962    numchans = ast_cli_netstats(NULL, fd, 1);
04963    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04964    return RESULT_SUCCESS;
04965 }

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

Show one peer in detail.

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

02352 {
02353    char status[30];
02354    char cbuf[256];
02355    struct iax2_peer *peer;
02356    char codec_buf[512];
02357    int x = 0, codec = 0, load_realtime = 0;
02358 
02359    if (argc < 4)
02360       return RESULT_SHOWUSAGE;
02361 
02362    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0;
02363 
02364    peer = find_peer(argv[3], load_realtime);
02365    if (peer) {
02366       ast_cli(fd,"\n\n");
02367       ast_cli(fd, "  * Name       : %s\n", peer->name);
02368       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
02369       ast_cli(fd, "  Context      : %s\n", peer->context);
02370       ast_cli(fd, "  Mailbox      : %s\n", peer->mailbox);
02371       ast_cli(fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No");
02372       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
02373       ast_cli(fd, "  Expire       : %d\n", peer->expire);
02374       ast_cli(fd, "  ACL          : %s\n", (peer->ha?"Yes":"No"));
02375       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));
02376       ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
02377       ast_cli(fd, "  Username     : %s\n", peer->username);
02378       ast_cli(fd, "  Codecs       : ");
02379       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
02380       ast_cli(fd, "%s\n", codec_buf);
02381 
02382       ast_cli(fd, "  Codec Order  : (");
02383       for(x = 0; x < 32 ; x++) {
02384          codec = ast_codec_pref_index(&peer->prefs,x);
02385          if(!codec)
02386             break;
02387          ast_cli(fd, "%s", ast_getformatname(codec));
02388          if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1))
02389             ast_cli(fd, "|");
02390       }
02391 
02392       if (!x)
02393          ast_cli(fd, "none");
02394       ast_cli(fd, ")\n");
02395 
02396       ast_cli(fd, "  Status       : ");
02397       peer_status(peer, status, sizeof(status));   
02398       ast_cli(fd, "%s\n",status);
02399       ast_cli(fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
02400       ast_cli(fd,"\n");
02401       peer_unref(peer);
02402    } else {
02403       ast_cli(fd,"Peer %s not found.\n", argv[3]);
02404       ast_cli(fd,"\n");
02405    }
02406 
02407    return RESULT_SUCCESS;
02408 }

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

Definition at line 4732 of file chan_iax2.c.

References __iax2_show_peers().

04733 {
04734    return __iax2_show_peers(0, fd, NULL, argc, argv);
04735 }

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

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

04805 {
04806 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04807 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04808    struct iax2_registry *reg = NULL;
04809 
04810    char host[80];
04811    char perceived[80];
04812    if (argc != 3)
04813       return RESULT_SHOWUSAGE;
04814    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04815    AST_LIST_LOCK(&registrations);
04816    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04817       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04818       if (reg->us.sin_addr.s_addr) 
04819          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04820       else
04821          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04822       ast_cli(fd, FORMAT, host, 
04823                (reg->dnsmgr) ? "Y" : "N", 
04824                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04825    }
04826    AST_LIST_UNLOCK(&registrations);
04827    return RESULT_SUCCESS;
04828 #undef FORMAT
04829 #undef FORMAT2
04830 }

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

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

02436 {
02437    struct iax_frame *cur;
02438    int cnt = 0, dead=0, final=0;
02439 
02440    if (argc != 3)
02441       return RESULT_SHOWUSAGE;
02442 
02443    AST_LIST_LOCK(&iaxq.queue);
02444    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02445       if (cur->retries < 0)
02446          dead++;
02447       if (cur->final)
02448          final++;
02449       cnt++;
02450    }
02451    AST_LIST_UNLOCK(&iaxq.queue);
02452 
02453    ast_cli(fd, "    IAX Statistics\n");
02454    ast_cli(fd, "---------------------\n");
02455    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02456    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02457    
02458    return RESULT_SUCCESS;
02459 }

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

Definition at line 4673 of file chan_iax2.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, IAX_TYPE_DYNAMIC, iaxthreadcount, RESULT_SHOWUSAGE, RESULT_SUCCESS, t, and thread.

04674 {
04675    struct iax2_thread *thread = NULL;
04676    time_t t;
04677    int threadcount = 0, dynamiccount = 0;
04678    char type;
04679 
04680    if (argc != 3)
04681       return RESULT_SHOWUSAGE;
04682       
04683    ast_cli(fd, "IAX2 Thread Information\n");
04684    time(&t);
04685    ast_cli(fd, "Idle Threads:\n");
04686    AST_LIST_LOCK(&idle_list);
04687    AST_LIST_TRAVERSE(&idle_list, thread, list) {
04688 #ifdef DEBUG_SCHED_MULTITHREAD
04689       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04690          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04691 #else
04692       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
04693          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04694 #endif
04695       threadcount++;
04696    }
04697    AST_LIST_UNLOCK(&idle_list);
04698    ast_cli(fd, "Active Threads:\n");
04699    AST_LIST_LOCK(&active_list);
04700    AST_LIST_TRAVERSE(&active_list, thread, list) {
04701       if (thread->type == IAX_TYPE_DYNAMIC)
04702          type = 'D';
04703       else
04704          type = 'P';
04705 #ifdef DEBUG_SCHED_MULTITHREAD
04706       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04707          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04708 #else
04709       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04710          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04711 #endif
04712       threadcount++;
04713    }
04714    AST_LIST_UNLOCK(&active_list);
04715    ast_cli(fd, "Dynamic Threads:\n");
04716         AST_LIST_LOCK(&dynamic_list);
04717         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04718 #ifdef DEBUG_SCHED_MULTITHREAD
04719                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04720                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04721 #else
04722                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04723                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04724 #endif
04725       dynamiccount++;
04726         }
04727         AST_LIST_UNLOCK(&dynamic_list);
04728    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04729    return RESULT_SUCCESS;
04730 }

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

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

04491 {
04492    regex_t regexbuf;
04493    int havepattern = 0;
04494 
04495 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
04496 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
04497 
04498    struct iax2_user *user = NULL;
04499    char auth[90];
04500    char *pstr = "";
04501    struct ao2_iterator i;
04502 
04503    switch (argc) {
04504    case 5:
04505       if (!strcasecmp(argv[3], "like")) {
04506          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04507             return RESULT_SHOWUSAGE;
04508          havepattern = 1;
04509       } else
04510          return RESULT_SHOWUSAGE;
04511    case 3:
04512       break;
04513    default:
04514       return RESULT_SHOWUSAGE;
04515    }
04516 
04517    ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
04518    i = ao2_iterator_init(users, 0);
04519    for (user = ao2_iterator_next(&i); user; 
04520       user_unref(user), user = ao2_iterator_next(&i)) {
04521       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
04522          continue;
04523       
04524       if (!ast_strlen_zero(user->secret)) {
04525          ast_copy_string(auth,user->secret,sizeof(auth));
04526       } else if (!ast_strlen_zero(user->inkeys)) {
04527          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
04528       } else
04529          ast_copy_string(auth, "-no secret-", sizeof(auth));
04530       
04531       if(ast_test_flag(user,IAX_CODEC_NOCAP))
04532          pstr = "REQ Only";
04533       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
04534          pstr = "Disabled";
04535       else
04536          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
04537       
04538       ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
04539          user->contexts ? user->contexts->context : context,
04540          user->ha ? "Yes" : "No", pstr);
04541    }
04542 
04543    if (havepattern)
04544       regfree(&regexbuf);
04545 
04546    return RESULT_SUCCESS;
04547 #undef FORMAT
04548 #undef FORMAT2
04549 }

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

Definition at line 3456 of file chan_iax2.c.

References iax2_registry::addr, AST_FRAME_IAX, ast_random(), iax_ie_data::buf, IAX_COMMAND_TXREQ, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), IAX_IE_CALLNO, IAX_IE_TRANSFERID, iaxs, iax_ie_data::pos, send_command(), TRANSFER_BEGIN, TRANSFER_MBEGIN, and chan_iax2_pvt::transferring.

Referenced by iax2_bridge().

03457 {
03458    int res;
03459    struct iax_ie_data ied0;
03460    struct iax_ie_data ied1;
03461    unsigned int transferid = (unsigned int)ast_random();
03462    memset(&ied0, 0, sizeof(ied0));
03463    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03464    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03465    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03466 
03467    memset(&ied1, 0, sizeof(ied1));
03468    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03469    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03470    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03471    
03472    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03473    if (res)
03474       return -1;
03475    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03476    if (res)
03477       return -1;
03478    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03479    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03480    return 0;
03481 }

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

Definition at line 2282 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02283 {
02284        if (argc != 4)
02285                return RESULT_SHOWUSAGE;
02286 
02287        test_losspct = atoi(argv[3]);
02288 
02289        return RESULT_SUCCESS;
02290 }

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

Definition at line 3702 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), iax_ie_data::buf, iax2_registry::callno, IAX_COMMAND_TRANSFER, iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, LOG_DEBUG, option_debug, iax_ie_data::pos, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.

03703 {
03704    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03705    struct iax_ie_data ied;
03706    char tmp[256], *context;
03707    ast_copy_string(tmp, dest, sizeof(tmp));
03708    context = strchr(tmp, '@');
03709    if (context) {
03710       *context = '\0';
03711       context++;
03712    }
03713    memset(&ied, 0, sizeof(ied));
03714    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03715    if (context)
03716       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03717    if (option_debug)
03718       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03719    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03720 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

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

02742 {
02743    /* Lock the queue and place this packet at the end */
02744    /* By setting this to 0, the network thread will send it for us, and
02745       queue retransmission if necessary */
02746    fr->sentyet = 0;
02747    AST_LIST_LOCK(&iaxq.queue);
02748    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02749    iaxq.count++;
02750    AST_LIST_UNLOCK(&iaxq.queue);
02751    /* Wake up the network and scheduler thread */
02752    if (netthreadid != AST_PTHREADT_NULL)
02753       pthread_kill(netthreadid, SIGURG);
02754    signal_condition(&sched_lock, &sched_cond);
02755    return 0;
02756 }

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

Definition at line 6599 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06600 {
06601    /* Drop when trunk is about 5 seconds idle */
06602    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06603       return 1;
06604    return 0;
06605 }

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

Definition at line 4065 of file chan_iax2.c.

References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, ast_iax2_meta_trunk_entry::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, iax2_trunk_peer::calls, ast_frame::data, ast_frame::datalen, DEFAULT_TRUNKDATA, f, find_tpeer(), IAX2_TRUNK_PREFACE, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_DEBUG, LOG_WARNING, MAX_TRUNKDATA, ast_iax2_meta_trunk_mini::mini, option_debug, chan_iax2_pvt::sockfd, iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdataalloc, iax2_trunk_peer::trunkdatalen, iax_frame::ts, and ast_iax2_mini_hdr::ts.

Referenced by iax2_send().

04066 {
04067    struct ast_frame *f;
04068    struct iax2_trunk_peer *tpeer;
04069    void *tmp, *ptr;
04070    struct ast_iax2_meta_trunk_entry *met;
04071    struct ast_iax2_meta_trunk_mini *mtm;
04072 
04073    f = &fr->af;
04074    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
04075    if (tpeer) {
04076       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
04077          /* Need to reallocate space */
04078          if (tpeer->trunkdataalloc < MAX_TRUNKDATA) {
04079             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
04080                ast_mutex_unlock(&tpeer->lock);
04081                return -1;
04082             }
04083             
04084             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
04085             tpeer->trunkdata = tmp;
04086             if (option_debug)
04087                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);
04088          } else {
04089             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));
04090             ast_mutex_unlock(&tpeer->lock);
04091             return -1;
04092          }
04093       }
04094 
04095       /* Append to meta frame */
04096       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
04097       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
04098          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
04099          mtm->len = htons(f->datalen);
04100          mtm->mini.callno = htons(pvt->callno);
04101          mtm->mini.ts = htons(0xffff & fr->ts);
04102          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
04103          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
04104       } else {
04105          met = (struct ast_iax2_meta_trunk_entry *)ptr;
04106          /* Store call number and length in meta header */
04107          met->callno = htons(pvt->callno);
04108          met->len = htons(f->datalen);
04109          /* Advance pointers/decrease length past trunk entry header */
04110          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
04111          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
04112       }
04113       /* Copy actual trunk data */
04114       memcpy(ptr, f->data, f->datalen);
04115       tpeer->trunkdatalen += f->datalen;
04116 
04117       tpeer->calls++;
04118       ast_mutex_unlock(&tpeer->lock);
04119    }
04120    return 0;
04121 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6516 of file chan_iax2.c.

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

Referenced by socket_process().

06517 {
06518    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06519 }

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

Definition at line 5022 of file chan_iax2.c.

References AST_FRAME_NULL, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, errno, error(), ast_frame::frametype, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, iaxs, iaxsl, LOG_DEBUG, option_debug, PTR_TO_CALLNO, and ast_channel::tech_pvt.

05023 {
05024    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
05025    int res = -1;
05026    ast_mutex_lock(&iaxsl[callno]);
05027    if (iaxs[callno]) {
05028    /* If there's an outstanding error, return failure now */
05029       if (!iaxs[callno]->error) {
05030          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
05031             res = 0;
05032             /* Don't waste bandwidth sending null frames */
05033          else if (f->frametype == AST_FRAME_NULL)
05034             res = 0;
05035          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
05036             res = 0;
05037          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
05038             res = 0;
05039          else
05040          /* Simple, just queue for transmission */
05041             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
05042       } else {
05043          if (option_debug)
05044             ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
05045       }
05046    }
05047    /* If it's already gone, just return */
05048    ast_mutex_unlock(&iaxsl[callno]);
05049    return res;
05050 }

static int iax_check_version ( char *  dev  )  [static]

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

01906 {
01907    int res = 0;
01908    struct iax_firmware *cur;
01909    if (!ast_strlen_zero(dev)) {
01910       ast_mutex_lock(&waresl.lock);
01911       cur = waresl.wares;
01912       while(cur) {
01913          if (!strcmp(dev, (char *)cur->fwh->devname)) {
01914             res = ntohs(cur->fwh->version);
01915             break;
01916          }
01917          cur = cur->next;
01918       }
01919       ast_mutex_unlock(&waresl.lock);
01920    }
01921    return res;
01922 }

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

Definition at line 767 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

00768 {
00769    if (iaxdebug)
00770       ast_verbose("%s", data);
00771 }

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

Definition at line 773 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

00774 {
00775    ast_log(LOG_WARNING, "%s", data);
00776 }

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

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

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

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

Definition at line 6787 of file chan_iax2.c.

References ast_channel::amaflags, ast_calloc, ast_channel_alloc(), ast_channel_masquerade(), ast_do_masquerade(), ast_hangup(), ast_log(), ast_pthread_create_background, AST_STATE_DOWN, iax_dual::chan1, iax_dual::chan2, ast_channel::context, ast_channel::exten, free, iax_park_thread(), LOG_WARNING, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.

Referenced by socket_process().

06788 {
06789    struct iax_dual *d;
06790    struct ast_channel *chan1m, *chan2m;
06791    pthread_t th;
06792    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
06793    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
06794    if (chan2m && chan1m) {
06795       /* Make formats okay */
06796       chan1m->readformat = chan1->readformat;
06797       chan1m->writeformat = chan1->writeformat;
06798       ast_channel_masquerade(chan1m, chan1);
06799       /* Setup the extensions and such */
06800       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
06801       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
06802       chan1m->priority = chan1->priority;
06803       
06804       /* We make a clone of the peer channel too, so we can play
06805          back the announcement */
06806       /* Make formats okay */
06807       chan2m->readformat = chan2->readformat;
06808       chan2m->writeformat = chan2->writeformat;
06809       ast_channel_masquerade(chan2m, chan2);
06810       /* Setup the extensions and such */
06811       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
06812       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
06813       chan2m->priority = chan2->priority;
06814       if (ast_do_masquerade(chan2m)) {
06815          ast_log(LOG_WARNING, "Masquerade failed :(\n");
06816          ast_hangup(chan2m);
06817          return -1;
06818       }
06819    } else {
06820       if (chan1m)
06821          ast_hangup(chan1m);
06822       if (chan2m)
06823          ast_hangup(chan2m);
06824       return -1;
06825    }
06826    if ((d = ast_calloc(1, sizeof(*d)))) {
06827       pthread_attr_t attr;
06828 
06829       pthread_attr_init(&attr);
06830       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06831 
06832       d->chan1 = chan1m;
06833       d->chan2 = chan2m;
06834       if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
06835          pthread_attr_destroy(&attr);
06836          return 0;
06837       }
06838       pthread_attr_destroy(&attr);
06839       free(d);
06840    }
06841    return -1;
06842 }

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

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

06768 {
06769    struct ast_channel *chan1, *chan2;
06770    struct iax_dual *d;
06771    struct ast_frame *f;
06772    int ext;
06773    int res;
06774    d = stuff;
06775    chan1 = d->chan1;
06776    chan2 = d->chan2;
06777    free(d);
06778    f = ast_read(chan1);
06779    if (f)
06780       ast_frfree(f);
06781    res = ast_park_call(chan1, chan2, 0, &ext);
06782    ast_hangup(chan2);
06783    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06784    return NULL;
06785 }

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

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

01420 {
01421    struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable);
01422    if (new) {
01423       size_t afdatalen = new->afdatalen;
01424       memcpy(new, fr, sizeof(*new));
01425       iax_frame_wrap(new, &fr->af);
01426       new->afdatalen = afdatalen;
01427       new->data = NULL;
01428       new->datalen = 0;
01429       new->direction = DIRECTION_INGRESS;
01430       new->retrans = -1;
01431    }
01432    return new;
01433 }

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

Definition at line 901 of file chan_iax2.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, and IAX_TYPE_DYNAMIC.

Referenced by iax2_process_thread().

00902 {
00903    if (thread->type == IAX_TYPE_DYNAMIC) {
00904       AST_LIST_LOCK(&dynamic_list);
00905       AST_LIST_INSERT_TAIL(&dynamic_list, thread, list);
00906       AST_LIST_UNLOCK(&dynamic_list);
00907    } else {
00908       AST_LIST_LOCK(&idle_list);
00909       AST_LIST_INSERT_TAIL(&idle_list, thread, list);
00910       AST_LIST_UNLOCK(&idle_list);
00911    }
00912 
00913    return;
00914 }

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

Definition at line 802 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

00803 {
00804    va_list args;
00805    char buf[1024];
00806 
00807    va_start(args, fmt);
00808    vsnprintf(buf, 1024, fmt, args);
00809    va_end(args);
00810 
00811    ast_verbose(buf);
00812 }

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

Definition at line 778 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

00779 {
00780    va_list args;
00781    char buf[1024];
00782 
00783    va_start(args, fmt);
00784    vsnprintf(buf, 1024, fmt, args);
00785    va_end(args);
00786 
00787    ast_log(LOG_ERROR, buf);
00788 }

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

Definition at line 790 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

00791 {
00792    va_list args;
00793    char buf[1024];
00794 
00795    va_start(args, fmt);
00796    vsnprintf(buf, 1024, fmt, args);
00797    va_end(args);
00798 
00799    ast_log(LOG_WARNING, buf);
00800 }

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 11158 of file chan_iax2.c.

References __unload_module(), ao2_callback(), ao2_container_alloc(), ao2_ref(), ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_custom_function_register(), AST_LIST_HEAD_INIT, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, ast_mutex_init(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_register_application(), ast_register_switch(), ast_verbose(), cli_iax2, config, errno, iax2_do_register(), iax2_poke_peer_cb(), iax2_prov_app(), iax2_switch, iax2_tech, iax_debug_output(), iax_error_output(), IAX_MAX_CALLS, iax_peercallno_pvts, iax_provision_reload(), iax_set_error(), iax_set_output(), iaxpeer_function, iaxq, iaxs, iaxsl, io_context_create(), jb_error_output(), jb_setoutput(), jb_warning_output(), ast_firmware_list::lock, LOG_ERROR, LOG_WARNING, manager_iax2_show_netstats(), manager_iax2_show_peers(), MAX_PEER_BUCKETS, MAX_USER_BUCKETS, option_verbose, papp, pdescrip, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), peers, psyn, pvt_cmp_cb(), pvt_hash_cb(), reload_firmware(), sched_context_create(), set_config(), start_network_thread(), user_cmp_cb(), user_hash_cb(), users, VERBOSE_PREFIX_2, and waresl.

11159 {
11160    char *config = "iax.conf";
11161    int res = 0;
11162    int x;
11163    struct iax2_registry *reg = NULL;
11164 
11165    peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
11166    if (!peers)
11167       return AST_MODULE_LOAD_FAILURE;
11168    users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
11169    if (!users) {
11170       ao2_ref(peers, -1);
11171       return AST_MODULE_LOAD_FAILURE;
11172    }
11173    iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb);
11174    if (!iax_peercallno_pvts) {
11175       ao2_ref(peers, -1);
11176       ao2_ref(users, -1);
11177       return AST_MODULE_LOAD_FAILURE;
11178    }
11179 
11180    ast_custom_function_register(&iaxpeer_function);
11181 
11182    iax_set_output(iax_debug_output);
11183    iax_set_error(iax_error_output);
11184    jb_setoutput(jb_error_output, jb_warning_output, NULL);
11185    
11186 #ifdef HAVE_ZAPTEL
11187 #ifdef ZT_TIMERACK
11188    timingfd = open("/dev/zap/timer", O_RDWR);
11189    if (timingfd < 0)
11190 #endif
11191       timingfd = open("/dev/zap/pseudo", O_RDWR);
11192    if (timingfd < 0) 
11193       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
11194 #endif      
11195 
11196    memset(iaxs, 0, sizeof(iaxs));
11197 
11198    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11199       ast_mutex_init(&iaxsl[x]);
11200    }
11201    
11202    ast_cond_init(&sched_cond, NULL);
11203 
11204    io = io_context_create();
11205    sched = sched_context_create();
11206    
11207    if (!io || !sched) {
11208       ast_log(LOG_ERROR, "Out of memory\n");
11209       return -1;
11210    }
11211 
11212    netsock = ast_netsock_list_alloc();
11213    if (!netsock) {
11214       ast_log(LOG_ERROR, "Could not allocate netsock list.\n");
11215       return -1;
11216    }
11217    ast_netsock_init(netsock);
11218 
11219    outsock = ast_netsock_list_alloc();
11220    if (!outsock) {
11221       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
11222       return -1;
11223    }
11224    ast_netsock_init(outsock);
11225 
11226    ast_mutex_init(&waresl.lock);
11227 
11228    AST_LIST_HEAD_INIT(&iaxq.queue);
11229    
11230    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
11231 
11232    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
11233    
11234    ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" );
11235    ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" );
11236 
11237    if(set_config(config, 0) == -1)
11238       return AST_MODULE_LOAD_DECLINE;
11239 
11240    if (ast_channel_register(&iax2_tech)) {
11241       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
11242       __unload_module();
11243       return -1;
11244    }
11245 
11246    if (ast_register_switch(&iax2_switch)) 
11247       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
11248 
11249    res = start_network_thread();
11250    if (!res) {
11251       if (option_verbose > 1) 
11252          ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n");
11253    } else {
11254       ast_log(LOG_ERROR, "Unable to start network thread\n");
11255       ast_netsock_release(netsock);
11256       ast_netsock_release(outsock);
11257    }
11258 
11259    AST_LIST_LOCK(&registrations);
11260    AST_LIST_TRAVERSE(&registrations, reg, entry)
11261       iax2_do_register(reg);
11262    AST_LIST_UNLOCK(&registrations); 
11263 
11264    ao2_callback(peers, 0, peer_set_sock_cb, NULL);
11265    ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
11266 
11267    reload_firmware(0);
11268    iax_provision_reload();
11269    return res;
11270 }

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

Definition at line 3483 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03484 {
03485    ast_mutex_lock(&iaxsl[callno0]);
03486    while (ast_mutex_trylock(&iaxsl[callno1])) {
03487       DEADLOCK_AVOIDANCE(&iaxsl[callno0]);
03488    }
03489 }

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

Definition at line 1473 of file chan_iax2.c.

References ARRAY_LEN, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, chan_iax2_pvt::callno, iax2_sched_add(), iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, MIN_REUSE_TIME, option_debug, chan_iax2_pvt::pingid, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().

Referenced by iax2_request(), and socket_process().

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

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

Definition at line 4736 of file chan_iax2.c.

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

Referenced by load_module().

04737 {
04738    ast_cli_netstats(s, -1, 0);
04739    astman_append(s, "\r\n");
04740    return RESULT_SUCCESS;
04741 }

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

Definition at line 4769 of file chan_iax2.c.

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

Referenced by load_module().

04770 {
04771    char *a[] = { "iax2", "show", "users" };
04772    int ret;
04773    const char *id = astman_get_header(m,"ActionID");
04774 
04775    if (!ast_strlen_zero(id))
04776       astman_append(s, "ActionID: %s\r\n",id);
04777    ret = __iax2_show_peers(1, -1, s, 3, a );
04778    astman_append(s, "\r\n\r\n" );
04779    return ret;
04780 } /* /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 1439 of file chan_iax2.c.

References chan_iax2_pvt::addr, chan_iax2_pvt::callno, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, TRANSFER_MEDIAPASS, chan_iax2_pvt::transfercallno, and chan_iax2_pvt::transferring.

Referenced by __find_callno(), ao2_callback(), ast_parse_device_state(), check_blacklist(), find_command(), get_sip_pvt_byid_locked(), handle_updates(), pbx_find_extension(), pvt_cmp_cb(), realtime_switch_common(), and softhangup_exec().

01440 {
01441    if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01442       (cur->addr.sin_port == sin->sin_port)) {
01443       /* This is the main host */
01444       if ( (cur->peercallno == 0 || cur->peercallno == callno) &&
01445           (check_dcallno ? dcallno == cur->callno : 1) ) {
01446          /* That's us.  Be sure we keep track of the peer call number */
01447          return 1;
01448       }
01449    }
01450    if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01451        (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {
01452       /* We're transferring */
01453       if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno))
01454          return 1;
01455    }
01456    return 0;
01457 }

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

Definition at line 4138 of file chan_iax2.c.

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

Referenced by decode_frame().

04139 {
04140 #if 0
04141    /* Debug with "fake encryption" */
04142    int x;
04143    if (len % 16)
04144       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04145    for (x=0;x<len;x++)
04146       dst[x] = src[x] ^ 0xff;
04147 #else 
04148    unsigned char lastblock[16] = { 0 };
04149    int x;
04150    while(len > 0) {
04151       aes_decrypt(src, dst, dcx);
04152       for (x=0;x<16;x++)
04153          dst[x] ^= lastblock[x];
04154       memcpy(lastblock, src, sizeof(lastblock));
04155       dst += 16;
04156       src += 16;
04157       len -= 16;
04158    }
04159 #endif
04160 }

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

Definition at line 4162 of file chan_iax2.c.

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

Referenced by encrypt_frame().

04163 {
04164 #if 0
04165    /* Debug with "fake encryption" */
04166    int x;
04167    if (len % 16)
04168       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04169    for (x=0;x<len;x++)
04170       dst[x] = src[x] ^ 0xff;
04171 #else
04172    unsigned char curblock[16] = { 0 };
04173    int x;
04174    while(len > 0) {
04175       for (x=0;x<16;x++)
04176          curblock[x] ^= src[x];
04177       aes_encrypt(curblock, dst, ecx);
04178       memcpy(curblock, dst, sizeof(curblock)); 
04179       dst += 16;
04180       src += 16;
04181       len -= 16;
04182    }
04183 #endif
04184 }

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

Definition at line 5359 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05360 {
05361    /* Select exactly one common encryption if there are any */
05362    p->encmethods &= enc;
05363    if (p->encmethods) {
05364       if (p->encmethods & IAX_ENCRYPT_AES128)
05365          p->encmethods = IAX_ENCRYPT_AES128;
05366       else
05367          p->encmethods = 0;
05368    }
05369 }

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

Definition at line 9131 of file chan_iax2.c.

References ast_io_add(), AST_IO_IN, AST_IO_PRI, ast_io_wait(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, f, iax2_sched_add(), iax_frame_free(), iaxq, iaxs, iaxsl, LOG_DEBUG, option_debug, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_packet(), iax_frame::sentyet, and timing_read().

Referenced by start_network_thread().

09132 {
09133    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
09134       from the network, and queue them for delivery to the channels */
09135    int res, count, wakeup;
09136    struct iax_frame *f;
09137 
09138    if (timingfd > -1)
09139       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
09140    
09141    for(;;) {
09142       pthread_testcancel();
09143 
09144       /* Go through the queue, sending messages which have not yet been
09145          sent, and scheduling retransmissions if appropriate */
09146       AST_LIST_LOCK(&iaxq.queue);
09147       count = 0;
09148       wakeup = -1;
09149       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
09150          if (f->sentyet)
09151             continue;
09152          
09153          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
09154          if (ast_mutex_trylock(&iaxsl[f->callno])) {
09155             wakeup = 1;
09156             continue;
09157          }
09158 
09159          f->sentyet++;
09160 
09161          if (iaxs[f->callno]) {
09162             send_packet(f);
09163             count++;
09164          } 
09165 
09166          ast_mutex_unlock(&iaxsl[f->callno]);
09167 
09168          if (f->retries < 0) {
09169             /* This is not supposed to be retransmitted */
09170             AST_LIST_REMOVE_CURRENT(&iaxq.queue, list);
09171             iaxq.count--;
09172             /* Free the iax frame */
09173             iax_frame_free(f);
09174          } else {
09175             /* We need reliable delivery.  Schedule a retransmission */
09176             f->retries++;
09177             f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
09178          }
09179       }
09180       AST_LIST_TRAVERSE_SAFE_END
09181       AST_LIST_UNLOCK(&iaxq.queue);
09182 
09183       pthread_testcancel();
09184 
09185       if (option_debug && count >= 20)
09186          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
09187 
09188       /* Now do the IO, and run scheduled tasks */
09189       res = ast_io_wait(io, wakeup);
09190       if (res >= 0) {
09191          if (option_debug && res >= 20)
09192             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
09193       }
09194    }
09195    return NULL;
09196 }

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

Definition at line 1380 of file chan_iax2.c.

References ao2_alloc(), ao2_ref(), ast_string_field_init, ast_string_field_set, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, chan_iax2_pvt::bridgecallno, chan_iax2_pvt::callno, exten, chan_iax2_pvt::initid, chan_iax2_pvt::jb, jb_new(), jb_setconf(), chan_iax2_pvt::jbid, chan_iax2_pvt::lagid, jb_conf::max_contig_interp, jb_conf::max_jitterbuf, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, prefs, chan_iax2_pvt::prefs, pvt_destructor(), jb_conf::resync_threshold, and chan_iax2_pvt::transfercallno.

Referenced by __find_callno().

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

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

03202 {
03203    if (ast_strlen_zero(data))
03204       return;
03205 
03206    pds->peer = strsep(&data, "/");
03207    pds->exten = strsep(&data, "/");
03208    pds->options = data;
03209 
03210    if (pds->exten) {
03211       data = pds->exten;
03212       pds->exten = strsep(&data, "@");
03213       pds->context = data;
03214    }
03215 
03216    if (strchr(pds->peer, '@')) {
03217       data = pds->peer;
03218       pds->username = strsep(&data, "@");
03219       pds->peer = data;
03220    }
03221 
03222    if (pds->username) {
03223       data = pds->username;
03224       pds->username = strsep(&data, ":");
03225       pds->password = data;
03226    }
03227 
03228    data = pds->peer;
03229    pds->peer = strsep(&data, ":");
03230    pds->port = data;
03231 
03232    /* check for a key name wrapped in [] in the secret position, if found,
03233       move it to the key field instead
03234    */
03235    if (pds->password && (pds->password[0] == '[')) {
03236       pds->key = ast_strip_quoted(pds->password, "[", "]");
03237       pds->password = NULL;
03238    }
03239 }

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

Referenced by load_module().

01119 {
01120    struct iax2_peer *peer = obj, *peer2 = arg;
01121 
01122    return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0;
01123 }

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

Definition at line 9829 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09830 {
09831    struct iax2_peer *peer = obj;
09832 
09833    ast_set_flag(peer, IAX_DELME);
09834 
09835    return 0;
09836 }

static void peer_destructor ( void *  obj  )  [static]

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

09355 {
09356    struct iax2_peer *peer = obj;
09357 
09358    ast_free_ha(peer->ha);
09359 
09360    if (peer->callno > 0) {
09361       ast_mutex_lock(&iaxsl[peer->callno]);
09362       iax2_destroy(peer->callno);
09363       ast_mutex_unlock(&iaxsl[peer->callno]);
09364    }
09365 
09366    register_peer_exten(peer, 0);
09367 
09368    if (peer->dnsmgr)
09369       ast_dnsmgr_release(peer->dnsmgr);
09370 
09371    ast_string_field_free_memory(peer);
09372 }

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

References ast_str_hash().

Referenced by load_module().

01109 {
01110    const struct iax2_peer *peer = obj;
01111 
01112    return ast_str_hash(peer->name);
01113 }

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

Definition at line 1165 of file chan_iax2.c.

References ao2_ref().

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

01166 {
01167    ao2_ref(peer, +1);
01168    return peer;
01169 }

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

Definition at line 11129 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

11130 {
11131    struct iax2_peer *peer = obj;
11132 
11133    if (peer->sockfd < 0)
11134       peer->sockfd = defaultsockfd;
11135 
11136    return 0;
11137 }

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

References iax2_registry::addr, ast_get_ip(), ast_log(), ast_netsock_bind(), ast_netsock_find(), ast_netsock_sockfd(), ast_netsock_unref(), ast_strdupa, check_srcaddr(), IAX_DEFAULT_PORTNO, LOG_DEBUG, LOG_WARNING, option_debug, socket_read(), iax2_peer::sockfd, and strsep().

Referenced by build_peer().

09282 {
09283    struct sockaddr_in sin;
09284    int nonlocal = 1;
09285    int port = IAX_DEFAULT_PORTNO;
09286    int sockfd = defaultsockfd;
09287    char *tmp;
09288    char *addr;
09289    char *portstr;
09290 
09291    if (!(tmp = ast_strdupa(srcaddr)))
09292       return -1;
09293 
09294    addr = strsep(&tmp, ":");
09295    portstr = tmp;
09296 
09297    if (portstr) {
09298       port = atoi(portstr);
09299       if (port < 1)
09300          port = IAX_DEFAULT_PORTNO;
09301    }
09302    
09303    if (!ast_get_ip(&sin, addr)) {
09304       struct ast_netsock *sock;
09305       int res;
09306 
09307       sin.sin_port = 0;
09308       sin.sin_family = AF_INET;
09309       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
09310       if (res == 0) {
09311          /* ip address valid. */
09312          sin.sin_port = htons(port);
09313          if (!(sock = ast_netsock_find(netsock, &sin)))
09314             sock = ast_netsock_find(outsock, &sin);
09315          if (sock) {
09316             sockfd = ast_netsock_sockfd(sock);
09317             nonlocal = 0;
09318          } else {
09319             unsigned int orig_saddr = sin.sin_addr.s_addr;
09320             /* INADDR_ANY matches anyway! */
09321             sin.sin_addr.s_addr = INADDR_ANY;
09322             if (ast_netsock_find(netsock, &sin)) {
09323                sin.sin_addr.s_addr = orig_saddr;
09324                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
09325                if (sock) {
09326                   sockfd = ast_netsock_sockfd(sock);
09327                   ast_netsock_unref(sock);
09328                   nonlocal = 0;
09329                } else {
09330                   nonlocal = 2;
09331                }
09332             }
09333          }
09334       }
09335    }
09336       
09337    peer->sockfd = sockfd;
09338 
09339    if (nonlocal == 1) {
09340       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
09341          srcaddr, peer->name);
09342       return -1;
09343         } else if (nonlocal == 2) {
09344       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
09345          srcaddr, peer->name);
09346          return -1;
09347    } else {
09348       if (option_debug)
09349          ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
09350       return 0;
09351    }
09352 }

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

peer_status: Report Peer status in character string

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

02329 {
02330    int res = 0;
02331    if (peer->maxms) {
02332       if (peer->lastms < 0) {
02333          ast_copy_string(status, "UNREACHABLE", statuslen);
02334       } else if (peer->lastms > peer->maxms) {
02335          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02336          res = 1;
02337       } else if (peer->lastms) {
02338          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02339          res = 1;
02340       } else {
02341          ast_copy_string(status, "UNKNOWN", statuslen);
02342       }
02343    } else { 
02344       ast_copy_string(status, "Unmonitored", statuslen);
02345       res = -1;
02346    }
02347    return res;
02348 }

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

static void poke_all_peers ( void   )  [static]

Definition at line 10290 of file chan_iax2.c.

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

Referenced by reload_config().

10291 {
10292    struct ao2_iterator i;
10293    struct iax2_peer *peer;
10294 
10295    i = ao2_iterator_init(peers, 0);
10296    while ((peer = ao2_iterator_next(&i))) {
10297       iax2_poke_peer(peer, 0);
10298       peer_unref(peer);
10299    }
10300 }

static void prune_peers ( void   )  [static]

Definition at line 9887 of file chan_iax2.c.

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

09888 {
09889    struct iax2_peer *peer;
09890    struct ao2_iterator i;
09891 
09892    i = ao2_iterator_init(peers, 0);
09893    while ((peer = ao2_iterator_next(&i))) {
09894       if (ast_test_flag(peer, IAX_DELME))
09895          unlink_peer(peer);
09896       peer_unref(peer);
09897    }
09898 }

static void prune_users ( void   )  [static]

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

09874 {
09875    struct iax2_user *user;
09876    struct ao2_iterator i;
09877 
09878    i = ao2_iterator_init(users, 0);
09879    while ((user = ao2_iterator_next(&i))) {
09880       if (ast_test_flag(user, IAX_DELME))
09881          ao2_unlink(users, user);
09882       user_unref(user);
09883    }
09884 }

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

Definition at line 11146 of file chan_iax2.c.

References chan_iax2_pvt::frames_received, and match().

Referenced by load_module().

11147 {
11148    struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
11149 
11150    /* The frames_received field is used to hold whether we're matching
11151     * against a full frame or not ... */
11152 
11153    return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 
11154       pvt2->frames_received) ? CMP_MATCH : 0;
11155 }

static void pvt_destructor ( void *  obj  )  [static]

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

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

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

Definition at line 11139 of file chan_iax2.c.

References chan_iax2_pvt::peercallno.

Referenced by load_module().

11140 {
11141    const struct chan_iax2_pvt *pvt = obj;
11142 
11143    return pvt->peercallno;
11144 }

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

Definition at line 5341 of file chan_iax2.c.

References AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), compress_subclass(), ast_iax2_full_hdr::csub, ast_iax2_full_hdr::dcallno, IAX_COMMAND_INVAL, IAX_FLAG_FULL, iax_showframe(), ast_iax2_full_hdr::iseqno, LOG_DEBUG, option_debug, ast_iax2_full_hdr::oseqno, ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::ts, and ast_iax2_full_hdr::type.

Referenced by socket_process().

05342 {
05343    struct ast_iax2_full_hdr fh;
05344    fh.scallno = htons(src | IAX_FLAG_FULL);
05345    fh.dcallno = htons(dst);
05346    fh.ts = 0;
05347    fh.oseqno = 0;
05348    fh.iseqno = 0;
05349    fh.type = AST_FRAME_IAX;
05350    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
05351    if (iaxdebug)
05352        iax_showframe(NULL, &fh, 0, sin, 0);
05353    if (option_debug)
05354       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
05355          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
05356    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
05357 }

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

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

References iax2_peer::addr, ast_copy_flags, ast_get_time_t(), ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_log(), ast_sched_del(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_peer(), iax2_peer::expire, expire_registry(), hp, iax2_sched_add(), IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_TEMPONLY, LOG_DEBUG, ast_variable::name, ast_variable::next, option_debug, peer_ref(), peer_unref(), peers, realtime_update_peer(), reg_source_db(), ast_variable::value, and var.

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

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

Definition at line 2996 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

02997 {
02998    char port[10];
02999    char regseconds[20];
03000    
03001    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
03002    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
03003    ast_update_realtime("iaxpeers", "name", peername, 
03004       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
03005       "regseconds", regseconds, NULL);
03006 }

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

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

References ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_user(), hp, IAX_RTCACHEFRIENDS, IAX_TEMPONLY, ast_variable::name, ast_variable::next, users, ast_variable::value, and var.

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

static void reg_source_db ( struct iax2_peer p  )  [static]

Definition at line 6146 of file chan_iax2.c.

References iax2_peer::addr, ast_db_get(), ast_device_state_changed(), ast_inet_ntoa(), ast_sched_del(), ast_test_flag, ast_verbose(), iax2_peer::expire, expire_registry(), iax2_peer::expiry, iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), IAX_TEMPONLY, option_verbose, peer_ref(), peer_unref(), register_peer_exten(), and VERBOSE_PREFIX_3.

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

06147 {
06148    char data[80];
06149    struct in_addr in;
06150    char *c, *d;
06151    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
06152       c = strchr(data, ':');
06153       if (c) {
06154          *c = '\0';
06155          c++;
06156          if (inet_aton(data, &in)) {
06157             d = strchr(c, ':');
06158             if (d) {
06159                *d = '\0';
06160                d++;
06161                if (option_verbose > 2)
06162                   ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 
06163                   ast_inet_ntoa(in), atoi(c), atoi(d));
06164                iax2_poke_peer(p, 0);
06165                p->expiry = atoi(d);
06166                memset(&p->addr, 0, sizeof(p->addr));
06167                p->addr.sin_family = AF_INET;
06168                p->addr.sin_addr = in;
06169                p->addr.sin_port = htons(atoi(c));
06170                if (p->expire > -1) {
06171                   if (!ast_sched_del(sched, p->expire)) {
06172                      p->expire = -1;
06173                      peer_unref(p);
06174                   }
06175                }
06176                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06177                p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
06178                if (p->expire == -1)
06179                   peer_unref(p);
06180                if (iax2_regfunk)
06181                   iax2_regfunk(p->name, 1);
06182                register_peer_exten(p, 1);
06183             }              
06184                
06185          }
06186       }
06187    }
06188 }

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

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

06067 {
06068    char multi[256];
06069    char *stringp, *ext;
06070    if (!ast_strlen_zero(regcontext)) {
06071       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
06072       stringp = multi;
06073       while((ext = strsep(&stringp, "&"))) {
06074          if (onoff) {
06075             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
06076                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
06077                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
06078          } else
06079             ast_context_remove_extension(regcontext, ext, 1, NULL);
06080       }
06081    }
06082 }

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

Verify inbound registration.

Definition at line 5508 of file chan_iax2.c.

References ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_device_state_changed(), ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, iax2_registry::expire, chan_iax2_pvt::expiry, expiry, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, iaxs, iaxsl, LOG_NOTICE, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, peer_unref(), iax_ies::refresh, iax_ies::rsa_result, iax2_registry::secret, strsep(), and iax_ies::username.

Referenced by handle_request_register(), and socket_process().

05509 {
05510    char requeststr[256] = "";
05511    char peer[256] = "";
05512    char md5secret[256] = "";
05513    char rsasecret[256] = "";
05514    char secret[256] = "";
05515    struct iax2_peer *p = NULL;
05516    struct ast_key *key;
05517    char *keyn;
05518    int x;
05519    int expire = 0;
05520    int res = -1;
05521 
05522    ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05523    /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
05524    if (ies->username)
05525       ast_copy_string(peer, ies->username, sizeof(peer));
05526    if (ies->password)
05527       ast_copy_string(secret, ies->password, sizeof(secret));
05528    if (ies->md5_result)
05529       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05530    if (ies->rsa_result)
05531       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05532    if (ies->refresh)
05533       expire = ies->refresh;
05534 
05535    if (ast_strlen_zero(peer)) {
05536       ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr));
05537       return -1;
05538    }
05539 
05540    /* SLD: first call to lookup peer during registration */
05541    ast_mutex_unlock(&iaxsl[callno]);
05542    p = find_peer(peer, 1);
05543    ast_mutex_lock(&iaxsl[callno]);
05544    if (!p || !iaxs[callno]) {
05545       if (iaxs[callno]) {
05546          int plaintext = ((last_authmethod & IAX_AUTH_PLAINTEXT) | (iaxs[callno]->authmethods & IAX_AUTH_PLAINTEXT));
05547 
05548          ast_string_field_set(iaxs[callno], secret, "badsecret");
05549 
05550          /* An AUTHREQ must be sent in response to a REGREQ of an invalid peer unless
05551           * 1. A challenge already exists indicating a AUTHREQ was already sent out.
05552           * 2. A plaintext secret is present in ie as result of a previous AUTHREQ requesting it.
05553           * 3. A plaintext secret is present in the ie and the last_authmethod used by a peer happened
05554           *    to be plaintext, indicating it is an authmethod used by other peers on the system. 
05555           *
05556           * If none of these cases exist, res will be returned as 0 without authentication indicating
05557           * an AUTHREQ needs to be sent out. */
05558 
05559          if (ast_strlen_zero(iaxs[callno]->challenge) &&
05560             !(!ast_strlen_zero(secret) && plaintext)) {
05561             /* by setting res to 0, an REGAUTH will be sent */
05562             res = 0;
05563          }
05564       }
05565       if (authdebug && !p)
05566          ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05567 
05568       goto return_unref;
05569    }
05570 
05571    if (!ast_test_flag(p, IAX_DYNAMIC)) {
05572       if (authdebug)
05573          ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05574       goto return_unref;
05575    }
05576 
05577    if (!ast_apply_ha(p->ha, sin)) {
05578       if (authdebug)
05579          ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05580       goto return_unref;
05581    }
05582    ast_string_field_set(iaxs[callno], secret, p->secret);
05583    ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
05584    /* Check secret against what we have on file */
05585    if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05586       if (!ast_strlen_zero(p->inkeys)) {
05587          char tmpkeys[256];
05588          char *stringp=NULL;
05589          ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys));
05590          stringp=tmpkeys;
05591          keyn = strsep(&stringp, ":");
05592          while(keyn) {
05593             key = ast_key_get(keyn, AST_KEY_PUBLIC);
05594             if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
05595                ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05596                break;
05597             } else if (!key)
05598                ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
05599             keyn = strsep(&stringp, ":");
05600          }
05601          if (!keyn) {
05602             if (authdebug)
05603                ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
05604             goto return_unref;
05605          }
05606       } else {
05607          if (authdebug)
05608             ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
05609          goto return_unref;
05610       }
05611    } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05612       struct MD5Context md5;
05613       unsigned char digest[16];
05614       char *tmppw, *stringp;
05615 
05616       tmppw = ast_strdupa(p->secret);
05617       stringp = tmppw;
05618       while((tmppw = strsep(&stringp, ";"))) {
05619          MD5Init(&md5);
05620          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
05621          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05622          MD5Final(digest, &md5);
05623          for (x=0;x<16;x++)
05624             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05625          if (!strcasecmp(requeststr, md5secret))
05626             break;
05627       }
05628       if (tmppw) {
05629          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05630       } else {
05631          if (authdebug)
05632             ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret);
05633          goto return_unref;
05634       }
05635    } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
05636       /* They've provided a plain text password and we support that */
05637       if (strcmp(secret, p->secret)) {
05638          if (authdebug)
05639             ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05640          goto return_unref;
05641       } else
05642          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05643    } else if (!ast_strlen_zero(iaxs[callno]->challenge) && ast_strlen_zero(md5secret) && ast_strlen_zero(rsasecret)) {
05644       /* if challenge has been sent, but no challenge response if given, reject. */
05645       goto return_unref;
05646    }
05647    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05648 
05649    /* either Authentication has taken place, or a REGAUTH must be sent before verifying registration */
05650    res = 0;
05651 return_unref:
05652    if (iaxs[callno]) {
05653       ast_string_field_set(iaxs[callno], peer, peer);
05654    }
05655    /* Choose lowest expiry number */
05656    if (expire && (expire < iaxs[callno]->expiry)) {
05657       iaxs[callno]->expiry = expire;
05658    }
05659 
05660    if (p)
05661       peer_unref(p);
05662    return res;
05663 }

static int registry_authrequest ( int  callno  )  [static]

Definition at line 6325 of file chan_iax2.c.

References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_strdupa, ast_string_field_set, chan_iax2_pvt::authmethods, iax2_peer::authmethods, iax_ie_data::buf, find_peer(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_COMMAND_REGAUTH, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CHALLENGE, IAX_IE_USERNAME, iaxs, iaxsl, peer_unref(), iax_ie_data::pos, and send_command().

Referenced by socket_process().

06326 {
06327    struct iax_ie_data ied;
06328    struct iax2_peer *p;
06329    char challenge[10];
06330    const char *peer_name;
06331    int sentauthmethod;
06332 
06333    peer_name = ast_strdupa(iaxs[callno]->peer);
06334 
06335    /* SLD: third call to find_peer in registration */
06336    ast_mutex_unlock(&iaxsl[callno]);
06337    if ((p = find_peer(peer_name, 1))) {
06338       last_authmethod = p->authmethods;
06339    }
06340 
06341    ast_mutex_lock(&iaxsl[callno]);
06342    if (!iaxs[callno])
06343       goto return_unref;
06344 
06345    memset(&ied, 0, sizeof(ied));
06346    /* The selection of which delayed reject is sent may leak information,
06347     * if it sets a static response.  For example, if a host is known to only
06348     * use MD5 authentication, then an RSA response would indicate that the
06349     * peer does not exist, and vice-versa.
06350     * Therefore, we use whatever the last peer used (which may vary over the
06351     * course of a server, which should leak minimal information). */
06352    sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
06353    if (!p) {
06354       iaxs[callno]->authmethods = sentauthmethod;
06355    }
06356    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod);
06357    if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06358       /* Build the challenge */
06359       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06360       ast_string_field_set(iaxs[callno], challenge, challenge);
06361       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06362    }
06363    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06364 
06365 return_unref:
06366    if (p) {
06367       peer_unref(p);
06368    }
06369 
06370    return iaxs[callno] ? send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1) : -1;
06371 }

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

Definition at line 6373 of file chan_iax2.c.

References iax2_registry::addr, AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), authenticate(), iax_ies::authmethods, iax_ie_data::buf, iax_ies::challenge, IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax_ie_data::pos, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_AUTHSENT, REG_STATE_NOAUTH, iax2_registry::regstate, iax2_registry::secret, send_command(), iax2_registry::username, and iax_ies::username.

Referenced by socket_process().

06374 {
06375    struct iax2_registry *reg;
06376    /* Start pessimistic */
06377    struct iax_ie_data ied;
06378    char peer[256] = "";
06379    char challenge[256] = "";
06380    int res;
06381    int authmethods = 0;
06382    if (ies->authmethods)
06383       authmethods = ies->authmethods;
06384    if (ies->username)
06385       ast_copy_string(peer, ies->username, sizeof(peer));
06386    if (ies->challenge)
06387       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
06388    memset(&ied, 0, sizeof(ied));
06389    reg = iaxs[callno]->reg;
06390    if (reg) {
06391          if (inaddrcmp(&reg->addr, sin)) {
06392             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
06393             return -1;
06394          }
06395          if (ast_strlen_zero(reg->secret)) {
06396             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
06397             reg->regstate = REG_STATE_NOAUTH;
06398             return -1;
06399          }
06400          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
06401          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
06402          if (reg->secret[0] == '[') {
06403             char tmpkey[256];
06404             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
06405             tmpkey[strlen(tmpkey) - 1] = '\0';
06406             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL);
06407          } else
06408             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL);
06409          if (!res) {
06410             reg->regstate = REG_STATE_AUTHSENT;
06411             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
06412          } else
06413             return -1;
06414          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
06415    } else   
06416       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
06417    return -1;
06418 }

static char* regstate2str ( int  regstate  )  [static]

Definition at line 4782 of file chan_iax2.c.

References REG_STATE_AUTHSENT, REG_STATE_NOAUTH, REG_STATE_REGISTERED, REG_STATE_REGSENT, REG_STATE_REJECTED, REG_STATE_TIMEOUT, and REG_STATE_UNREGISTERED.

Referenced by handle_response_register(), iax2_show_registry(), sip_reg_timeout(), and sip_show_registry().

04783 {
04784    switch(regstate) {
04785    case REG_STATE_UNREGISTERED:
04786       return "Unregistered";
04787    case REG_STATE_REGSENT:
04788       return "Request Sent";
04789    case REG_STATE_AUTHSENT:
04790       return "Auth. Sent";
04791    case REG_STATE_REGISTERED:
04792       return "Registered";
04793    case REG_STATE_REJECTED:
04794       return "Rejected";
04795    case REG_STATE_TIMEOUT:
04796       return "Timeout";
04797    case REG_STATE_NOAUTH:
04798       return "No Authentication";
04799    default:
04800       return "Unknown";
04801    }
04802 }

static int reload ( void   )  [static]

Definition at line 10327 of file chan_iax2.c.

References reload_config().

10328 {
10329    return reload_config();
10330 }

static int reload_config ( void   )  [static]

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

10302 {
10303    char *config = "iax.conf";
10304    struct iax2_registry *reg;
10305 
10306    if (set_config(config, 1) > 0) {
10307       prune_peers();
10308       prune_users();
10309       AST_LIST_LOCK(&registrations);
10310       AST_LIST_TRAVERSE(&registrations, reg, entry)
10311          iax2_do_register(reg);
10312       AST_LIST_UNLOCK(&registrations);
10313       /* Qualify hosts, too */
10314       poke_all_peers();
10315    }
10316    reload_firmware(0);
10317    iax_provision_reload();
10318 
10319    return 0;
10320 }

static void reload_firmware ( int  unload  )  [static]

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

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

static void remove_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

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

01257 {
01258    if (!pvt->peercallno) {
01259       ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
01260       return;
01261    }
01262 
01263    ao2_unlink(iax_peercallno_pvts, pvt);
01264 }

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

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

Definition at line 9103 of file chan_iax2.c.

References ast_cond_timedwait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), LOG_DEBUG, and option_debug.

Referenced by start_network_thread().

09104 {
09105    int count;
09106    int res;
09107    struct timeval tv;
09108    struct timespec ts;
09109 
09110    for (;;) {
09111       res = ast_sched_wait(sched);
09112       if ((res > 1000) || (res < 0))
09113          res = 1000;
09114       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
09115       ts.tv_sec = tv.tv_sec;
09116       ts.tv_nsec = tv.tv_usec * 1000;
09117 
09118       pthread_testcancel();
09119       ast_mutex_lock(&sched_lock);
09120       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
09121       ast_mutex_unlock(&sched_lock);
09122       pthread_testcancel();
09123 
09124       count = ast_sched_runq(sched);
09125       if (option_debug && count >= 20)
09126          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
09127    }
09128    return NULL;
09129 }

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

References __do_deliver(), iax_frame::af, ast_bridged_channel(), AST_CHAN_TP_WANTSJITTER, ast_codec_get_samples(), AST_FRAME_CNG, AST_FRAME_VOICE, ast_log(), AST_SCHED_DEL, ast_test_flag, ast_tvadd(), calc_rxstamp(), iax_frame::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), IAX_FORCEJITTERBUF, IAX_USEJITTERBUF, iaxs, chan_iax2_pvt::jb, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, chan_iax2_pvt::jbid, len, LOG_DEBUG, option_debug, chan_iax2_pvt::owner, ast_channel_tech::properties, chan_iax2_pvt::rxcore, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().

Referenced by socket_process().

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

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

References AST_FRAME_IAX, compress_subclass(), and ast_iax2_full_hdr::scallno.

Referenced by socket_process().

03175 {
03176    struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno),
03177       .ts = htonl(ts), .iseqno = seqno, .oseqno = seqno, .type = AST_FRAME_IAX,
03178       .csub = compress_subclass(command) };
03179 
03180    return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin));
03181 }

static int send_command ( struct chan_iax2_pvt i,
char  type,
int  command,
unsigned int  ts,
const unsigned char *  data,
int  datalen,
int  seqno 
) [static]

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

05086 {
05087    int call_num = i->callno;
05088    /* It is assumed that the callno has already been locked */
05089    iax2_predestroy(i->callno);
05090    if (!iaxs[call_num])
05091       return -1;
05092    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
05093 }

static int send_command_immediate ( struct chan_iax2_pvt i,
char  type,
int  command,
unsigned int  ts,
const unsigned char *  data,
int  datalen,
int  seqno 
) [static]

Definition at line 5095 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

05096 {
05097    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
05098 }

static int send_command_locked ( unsigned short  callno,
char  type,
int  command,
unsigned int  ts,
const unsigned char *  data,
int  datalen,
int  seqno 
) [static]

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

05072 {
05073    int res;
05074    ast_mutex_lock(&iaxsl[callno]);
05075    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
05076    ast_mutex_unlock(&iaxsl[callno]);
05077    return res;
05078 }

static int send_command_transfer ( struct chan_iax2_pvt i,
char  type,
int  command,
unsigned int  ts,
const unsigned char *  data,
int  datalen 
) [static]

Definition at line 5100 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

05101 {
05102    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
05103 }

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

Definition at line 1062 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

01063 {
01064 #ifdef SCHED_MULTITHREADED
01065    if (schedule_action(__send_lagrq, data))
01066 #endif      
01067       __send_lagrq(data);
01068    return 0;
01069 }

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 2086 of file chan_iax2.c.

References chan_iax2_pvt::addr, iax2_registry::addr, ast_inet_ntoa(), ast_log(), iax_frame::callno, iax2_registry::callno, iax_frame::data, iax_frame::datalen, errno, error(), handle_error(), iax_showframe(), iaxs, LOG_DEBUG, option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, transfer, iax_frame::transfer, and iax_frame::ts.

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

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

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

Definition at line 1022 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

01023 {
01024 #ifdef SCHED_MULTITHREADED
01025    if (schedule_action(__send_ping, data))
01026 #endif      
01027       __send_ping(data);
01028    return 0;
01029 }

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

Definition at line 6555 of file chan_iax2.c.

References iax2_trunk_peer::addr, iax_frame::afdata, ast_inet_ntoa(), ast_log(), ast_test_flag, calc_txpeerstamp(), iax2_trunk_peer::calls, ast_iax2_meta_hdr::cmddata, iax_frame::data, ast_iax2_meta_hdr::data, iax_frame::datalen, iax_frame::direction, DIRECTION_OUTGRESS, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_TRUNKTIMESTAMPS, LOG_DEBUG, ast_iax2_meta_hdr::metacmd, option_debug, iax_frame::retrans, iax2_trunk_peer::sockfd, iax_frame::transfer, transmit_trunk(), iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdatalen, ast_iax2_meta_trunk_hdr::ts, and ast_iax2_meta_hdr::zeros.

Referenced by timing_read().

06556 {
06557    int res = 0;
06558    struct iax_frame *fr;
06559    struct ast_iax2_meta_hdr *meta;
06560    struct ast_iax2_meta_trunk_hdr *mth;
06561    int calls = 0;
06562    
06563    /* Point to frame */
06564    fr = (struct iax_frame *)tpeer->trunkdata;
06565    /* Point to meta data */
06566    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
06567    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
06568    if (tpeer->trunkdatalen) {
06569       /* We're actually sending a frame, so fill the meta trunk header and meta header */
06570       meta->zeros = 0;
06571       meta->metacmd = IAX_META_TRUNK;
06572       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
06573          meta->cmddata = IAX_META_TRUNK_MINI;
06574       else
06575          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
06576       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
06577       /* And the rest of the ast_iax2 header */
06578       fr->direction = DIRECTION_OUTGRESS;
06579       fr->retrans = -1;
06580       fr->transfer = 0;
06581       /* Any appropriate call will do */
06582       fr->data = fr->afdata;
06583       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
06584       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
06585       calls = tpeer->calls;
06586 #if 0
06587       if (option_debug)
06588          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));
06589 #endif      
06590       /* Reset transmit trunk side data */
06591       tpeer->trunkdatalen = 0;
06592       tpeer->calls = 0;
06593    }
06594    if (res < 0)
06595       return res;
06596    return calls;
06597 }

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

Load configuration.

Definition at line 9931 of file chan_iax2.c.

References __ao2_link(), ast_category_browse(), ast_cdr_amaflags2int(), ast_clear_flag, ast_config_destroy(), ast_config_load(), ast_context_create(), ast_context_find(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_netsock_bind(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_netsock_sockfd(), ast_netsock_unref(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_str2tos(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), build_peer(), build_user(), capability, DEFAULT_MAXMS, errno, format, gen, get_encrypt_methods(), iax2_register(), IAX_ALLOWFWDOWNLOAD, IAX_CAPABILITY_FULLBANDWIDTH, IAX_CAPABILITY_LOWBANDWIDTH, IAX_CAPABILITY_MEDBANDWIDTH, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_RTUPDATE, IAX_TRANSFERMEDIA, IAX_TRUNKTIMESTAMPS, IAX_USEJITTERBUF, iaxmaxthreadcount, iaxthreadcount, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MAX_PEER_BUCKETS, ast_variable::name, ast_variable::next, option_verbose, peer_unref(), peers, portno, prefs, reg_source_db(), iax2_registry::secret, set_config_destroy(), set_timing(), socket_read(), user_unref(), users, ast_variable::value, and VERBOSE_PREFIX_2.

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

09932 {
09933    struct ast_config *cfg, *ucfg;
09934    int capability=iax2_capability;
09935    struct ast_variable *v;
09936    char *cat;
09937    const char *utype;
09938    const char *tosval;
09939    int format;
09940    int portno = IAX_DEFAULT_PORTNO;
09941    int  x;
09942    struct iax2_user *user;
09943    struct iax2_peer *peer;
09944    struct ast_netsock *ns;
09945 #if 0
09946    static unsigned short int last_port=0;
09947 #endif
09948 
09949    cfg = ast_config_load(config_file);
09950    
09951    if (!cfg) {
09952       ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
09953       return -1;
09954    }
09955 
09956    if (reload) {
09957       set_config_destroy();
09958    }
09959 
09960    /* Reset global codec prefs */   
09961    memset(&prefs, 0 , sizeof(struct ast_codec_pref));
09962    
09963    /* Reset Global Flags */
09964    memset(&globalflags, 0, sizeof(globalflags));
09965    ast_set_flag(&globalflags, IAX_RTUPDATE);
09966 
09967 #ifdef SO_NO_CHECK
09968    nochecksums = 0;
09969 #endif
09970 
09971    min_reg_expire = IAX_DEFAULT_REG_EXPIRE;
09972    max_reg_expire = IAX_DEFAULT_REG_EXPIRE;
09973 
09974    maxauthreq = 3;
09975 
09976    v = ast_variable_browse(cfg, "general");
09977 
09978    /* Seed initial tos value */
09979    tosval = ast_variable_retrieve(cfg, "general", "tos");
09980    if (tosval) {
09981       if (ast_str2tos(tosval, &tos))
09982          ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n");
09983    }
09984    while(v) {
09985       if (!strcasecmp(v->name, "bindport")){ 
09986          if (reload)
09987             ast_log(LOG_NOTICE, "Ignoring bindport on reload\n");
09988          else
09989             portno = atoi(v->value);
09990       } else if (!strcasecmp(v->name, "pingtime")) 
09991          ping_time = atoi(v->value);
09992       else if (!strcasecmp(v->name, "iaxthreadcount")) {
09993          if (reload) {
09994             if (atoi(v->value) != iaxthreadcount)
09995                ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n");
09996          } else {
09997             iaxthreadcount = atoi(v->value);
09998             if (iaxthreadcount < 1) {
09999                ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n");
10000                iaxthreadcount = 1;
10001             } else if (iaxthreadcount > 256) {
10002                ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n");
10003                iaxthreadcount = 256;
10004             }
10005          }
10006       } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) {
10007          if (reload) {
10008             AST_LIST_LOCK(&dynamic_list);
10009             iaxmaxthreadcount = atoi(v->value);
10010             AST_LIST_UNLOCK(&dynamic_list);
10011          } else {
10012             iaxmaxthreadcount = atoi(v->value);
10013             if (iaxmaxthreadcount < 0) {
10014                ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n");
10015                iaxmaxthreadcount = 0;
10016             } else if (iaxmaxthreadcount > 256) {
10017                ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n");
10018                iaxmaxthreadcount = 256;
10019             }
10020          }
10021       } else if (!strcasecmp(v->name, "nochecksums")) {
10022 #ifdef SO_NO_CHECK
10023          if (ast_true(v->value))
10024             nochecksums = 1;
10025          else
10026             nochecksums = 0;
10027 #else
10028          if (ast_true(v->value))
10029             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
10030 #endif
10031       }
10032       else if (!strcasecmp(v->name, "maxjitterbuffer")) 
10033          maxjitterbuffer = atoi(v->value);
10034       else if (!strcasecmp(v->name, "resyncthreshold")) 
10035          resyncthreshold = atoi(v->value);
10036       else if (!strcasecmp(v->name, "maxjitterinterps")) 
10037          maxjitterinterps = atoi(v->value);
10038       else if (!strcasecmp(v->name, "lagrqtime")) 
10039          lagrq_time = atoi(v->value);
10040       else if (!strcasecmp(v->name, "maxregexpire")) 
10041          max_reg_expire = atoi(v->value);
10042       else if (!strcasecmp(v->name, "minregexpire")) 
10043          min_reg_expire = atoi(v->value);
10044       else if (!strcasecmp(v->name, "bindaddr")) {
10045          if (reload) {
10046             ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n");
10047          } else {
10048             if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) {
10049                ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno);
10050             } else {
10051                if (option_verbose > 1) {
10052                   if (strchr(v->value, ':'))
10053                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value);
10054                   else
10055                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno);
10056                }
10057                if (defaultsockfd < 0) 
10058                   defaultsockfd = ast_netsock_sockfd(ns);
10059                ast_netsock_unref(ns);
10060             }
10061          }
10062       } else if (!strcasecmp(v->name, "authdebug"))
10063          authdebug = ast_true(v->value);
10064       else if (!strcasecmp(v->name, "encryption"))
10065          iax2_encryption = get_encrypt_methods(v->value);
10066       else if (!strcasecmp(v->name, "notransfer")) {
10067          ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
10068          ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
10069          ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER);   
10070       } else if (!strcasecmp(v->name, "transfer")) {
10071          if (!strcasecmp(v->value, "mediaonly")) {
10072             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 
10073          } else if (ast_true(v->value)) {
10074             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
10075          } else 
10076             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
10077       } else if (!strcasecmp(v->name, "codecpriority")) {
10078          if(!strcasecmp(v->value, "caller"))
10079             ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST);
10080          else if(!strcasecmp(v->value, "disabled"))
10081             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
10082          else if(!strcasecmp(v->value, "reqonly")) {
10083             ast_set_flag((&globalflags), IAX_CODEC_NOCAP);
10084             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
10085          }
10086       } else if (!strcasecmp(v->name, "jitterbuffer"))
10087          ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 
10088       else if (!strcasecmp(v->name, "forcejitterbuffer"))
10089          ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);  
10090       else if (!strcasecmp(v->name, "delayreject"))
10091          delayreject = ast_true(v->value);
10092       else if (!strcasecmp(v->name, "allowfwdownload"))
10093          ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD);
10094       else if (!strcasecmp(v->name, "rtcachefriends"))
10095          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS);  
10096       else if (!strcasecmp(v->name, "rtignoreregexpire"))
10097          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE);  
10098       else if (!strcasecmp(v->name, "rtupdate"))
10099          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE);
10100       else if (!strcasecmp(v->name, "trunktimestamps"))
10101          ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS);
10102       else if (!strcasecmp(v->name, "rtautoclear")) {
10103          int i = atoi(v->value);
10104          if(i > 0)
10105             global_rtautoclear = i;
10106          else
10107             i = 0;
10108          ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR);   
10109       } else if (!strcasecmp(v->name, "trunkfreq")) {
10110          trunkfreq = atoi(v->value);
10111          if (trunkfreq < 10)
10112             trunkfreq = 10;
10113       } else if (!strcasecmp(v->name, "autokill")) {
10114          if (sscanf(v->value, "%d", &x) == 1) {
10115             if (x >= 0)
10116                autokill = x;
10117             else
10118                ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
10119          } else if (ast_true(v->value)) {
10120             autokill = DEFAULT_MAXMS;
10121          } else {
10122             autokill = 0;
10123          }
10124       } else if (!strcasecmp(v->name, "bandwidth")) {
10125          if (!strcasecmp(v->value, "low")) {
10126             capability = IAX_CAPABILITY_LOWBANDWIDTH;
10127          } else if (!strcasecmp(v->value, "medium")) {
10128             capability = IAX_CAPABILITY_MEDBANDWIDTH;
10129          } else if (!strcasecmp(v->value, "high")) {
10130             capability = IAX_CAPABILITY_FULLBANDWIDTH;
10131          } else
10132             ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n");
10133       } else if (!strcasecmp(v->name, "allow")) {
10134          ast_parse_allow_disallow(&prefs, &capability, v->value, 1);
10135       } else if (!strcasecmp(v->name, "disallow")) {
10136          ast_parse_allow_disallow(&prefs, &capability, v->value, 0);
10137       } else if (!strcasecmp(v->name, "register")) {
10138          iax2_register(v->value, v->lineno);
10139       } else if (!strcasecmp(v->name, "iaxcompat")) {
10140          iaxcompat = ast_true(v->value);
10141       } else if (!strcasecmp(v->name, "regcontext")) {
10142          ast_copy_string(regcontext, v->value, sizeof(regcontext));
10143          /* Create context if it doesn't exist already */
10144          if (!ast_context_find(regcontext))
10145             ast_context_create(NULL, regcontext, "IAX2");
10146       } else if (!strcasecmp(v->name, "tos")) {
10147          if (ast_str2tos(v->value, &tos))
10148             ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno);
10149       } else if (!strcasecmp(v->name, "accountcode")) {
10150          ast_copy_string(accountcode, v->value, sizeof(accountcode));
10151       } else if (!strcasecmp(v->name, "mohinterpret")) {
10152          ast_copy_string(mohinterpret, v->value, sizeof(user->mohinterpret));
10153       } else if (!strcasecmp(v->name, "mohsuggest")) {
10154          ast_copy_string(mohsuggest, v->value, sizeof(user->mohsuggest));
10155       } else if (!strcasecmp(v->name, "amaflags")) {
10156          format = ast_cdr_amaflags2int(v->value);
10157          if (format < 0) {
10158             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
10159          } else {
10160             amaflags = format;
10161          }
10162       } else if (!strcasecmp(v->name, "language")) {
10163          ast_copy_string(language, v->value, sizeof(language));
10164       } else if (!strcasecmp(v->name, "maxauthreq")) {
10165          maxauthreq = atoi(v->value);
10166          if (maxauthreq < 0)
10167             maxauthreq = 0;
10168       } else if (!strcasecmp(v->name, "adsi")) {
10169          adsi = ast_true(v->value);
10170       } /*else if (strcasecmp(v->name,"type")) */
10171       /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
10172       v = v->next;
10173    }
10174    
10175    if (defaultsockfd < 0) {
10176       if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) {
10177          ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
10178       } else {
10179          if (option_verbose > 1)
10180             ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno);
10181          defaultsockfd = ast_netsock_sockfd(ns);
10182          ast_netsock_unref(ns);
10183       }
10184    }
10185    if (reload) {
10186       ast_netsock_release(outsock);
10187       outsock = ast_netsock_list_alloc();
10188       if (!outsock) {
10189          ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
10190          return -1;
10191       }
10192       ast_netsock_init(outsock);
10193    }
10194 
10195    if (min_reg_expire > max_reg_expire) {
10196       ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n",
10197          min_reg_expire, max_reg_expire, max_reg_expire);
10198       min_reg_expire = max_reg_expire;
10199    }
10200    iax2_capability = capability;
10201    
10202    ucfg = ast_config_load("users.conf");
10203    if (ucfg) {
10204       struct ast_variable *gen;
10205       int genhasiax;
10206       int genregisteriax;
10207       const char *hasiax, *registeriax;
10208       
10209       genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax"));
10210       genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax"));
10211       gen = ast_variable_browse(ucfg, "general");
10212       cat = ast_category_browse(ucfg, NULL);
10213       while (cat) {
10214          if (strcasecmp(cat, "general")) {
10215             hasiax = ast_variable_retrieve(ucfg, cat, "hasiax");
10216             registeriax = ast_variable_retrieve(ucfg, cat, "registeriax");
10217             if (ast_true(hasiax) || (!hasiax && genhasiax)) {
10218                /* Start with general parameters, then specific parameters, user and peer */
10219                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
10220                if (user) {
10221                   __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10222                   user = user_unref(user);
10223                }
10224                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
10225                if (peer) {
10226                   if (ast_test_flag(peer, IAX_DYNAMIC))
10227                      reg_source_db(peer);
10228                   __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10229                   peer = peer_unref(peer);
10230                }
10231             }
10232             if (ast_true(registeriax) || (!registeriax && genregisteriax)) {
10233                char tmp[256];
10234                const char *host = ast_variable_retrieve(ucfg, cat, "host");
10235                const char *username = ast_variable_retrieve(ucfg, cat, "username");
10236                const char *secret = ast_variable_retrieve(ucfg, cat, "secret");
10237                if (!host)
10238                   host = ast_variable_retrieve(ucfg, "general", "host");
10239                if (!username)
10240                   username = ast_variable_retrieve(ucfg, "general", "username");
10241                if (!secret)
10242                   secret = ast_variable_retrieve(ucfg, "general", "secret");
10243                if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
10244                   if (!ast_strlen_zero(secret))
10245                      snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host);
10246                   else
10247                      snprintf(tmp, sizeof(tmp), "%s@%s", username, host);
10248                   iax2_register(tmp, 0);
10249                }
10250             }
10251          }
10252          cat = ast_category_browse(ucfg, cat);
10253       }
10254       ast_config_destroy(ucfg);
10255    }
10256    
10257    cat = ast_category_browse(cfg, NULL);
10258    while(cat) {
10259       if (strcasecmp(cat, "general")) {
10260          utype = ast_variable_retrieve(cfg, cat, "type");
10261          if (utype) {
10262             if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
10263                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
10264                if (user) {
10265                   __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10266                   user = user_unref(user);
10267                }
10268             }
10269             if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
10270                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
10271                if (peer) {
10272                   if (ast_test_flag(peer, IAX_DYNAMIC))
10273                      reg_source_db(peer);
10274                   __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10275                   peer = peer_unref(peer);
10276                }
10277             } else if (strcasecmp(utype, "user")) {
10278                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file);
10279             }
10280          } else
10281             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
10282       }
10283       cat = ast_category_browse(cfg, cat);
10284    }
10285    ast_config_destroy(cfg);
10286    set_timing();
10287    return 1;
10288 }

static void set_config_destroy ( void   )  [static]

Definition at line 9915 of file chan_iax2.c.

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

Referenced by set_config().

09916 {
09917    strcpy(accountcode, "");
09918    strcpy(language, "");
09919    strcpy(mohinterpret, "default");
09920    strcpy(mohsuggest, "");
09921    amaflags = 0;
09922    delayreject = 0;
09923    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09924    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09925    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09926    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09927    delete_users();
09928 }

static void set_timing ( void   )  [static]

Definition at line 9900 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09901 {
09902 #ifdef HAVE_ZAPTEL
09903    int bs = trunkfreq * 8;
09904    if (timingfd > -1) {
09905       if (
09906 #ifdef ZT_TIMERACK
09907          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09908 #endif         
09909          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09910          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09911    }
09912 #endif
09913 }

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

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

00761 {
00762    ast_mutex_lock(lock);
00763    ast_cond_signal(cond);
00764    ast_mutex_unlock(lock);
00765 }

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 7029 of file chan_iax2.c.

References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, ast_async_goto(), ast_best_codec(), ast_bridged_channel(), AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_clear_flag, ast_codec_choose(), ast_codec_get_samples(), ast_codec_pref_convert(), ast_codec_pref_index(), ast_codec_pref_string(), AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_device_state_changed(), ast_exists_extension(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_IAX, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_parking_ext(), ast_sched_del(), AST_SCHED_DEL, ast_set_flag, ast_set_read_format(), ast_set_write_format(), AST_STATE_RING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose(), auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), chan_iax2_pvt::authmethods, iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, iax_frame::cacheable, calc_timestamp(), iax_ies::called_number, iax2_peer::callno, chan_iax2_pvt::callno, ast_iax2_meta_trunk_entry::callno, ast_iax2_mini_hdr::callno, iax2_registry::callno, iax_frame::callno, chan_iax2_pvt::capability, iax_ies::cause, iax_ies::causecode, check_access(), check_provisioning(), chan_iax2_pvt::chosenformat, cid_num, ast_iax2_meta_hdr::cmddata, iax_ies::codec_prefs, complete_dpreply(), complete_transfer(), construct_rr(), ast_iax2_full_hdr::csub, ast_frame::data, ast_iax2_meta_trunk_hdr::data, ast_iax2_meta_hdr::data, ast_frame::datalen, ast_iax2_full_hdr::dcallno, DEADLOCK_AVOIDANCE, decrypt_frame(), iax_ies::devicetype, dp_lookup(), chan_iax2_pvt::encmethods, iax_ies::encmethods, chan_iax2_pvt::error, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, iax_frame::final, find_callno(), find_callno_locked(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, iax_ies::format, format, chan_iax2_pvt::frames_received, ast_frame::frametype, iax_ies::fwdesc, ast_channel::hangupcause, iax2_peer::historicms, iax2_ack_registry(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_queue_control_data(), iax2_queue_frame(), iax2_sched_add(), iax2_send(), iax2_vnak(), IAX_ALLOWFWDOWNLOAD, IAX_ALREADYGONE, IAX_AUTH_MD5, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, IAX_COMMAND_DIAL, IAX_COMMAND_DPREP, IAX_COMMAND_DPREQ, IAX_COMMAND_FWDATA, IAX_COMMAND_FWDOWNL, IAX_COMMAND_HANGUP, IAX_COMMAND_INVAL, IAX_COMMAND_LAGRP, IAX_COMMAND_LAGRQ, IAX_COMMAND_NEW, IAX_COMMAND_PING, IAX_COMMAND_POKE, IAX_COMMAND_PONG, IAX_COMMAND_QUELCH, IAX_COMMAND_REGACK, IAX_COMMAND_REGAUTH, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, IAX_COMMAND_TRANSFER, IAX_COMMAND_TXACC, IAX_COMMAND_TXCNT, IAX_COMMAND_TXMEDIA, IAX_COMMAND_TXREADY, IAX_COMMAND_TXREJ, IAX_COMMAND_TXREL, IAX_COMMAND_TXREQ, IAX_COMMAND_UNQUELCH, IAX_COMMAND_UNSUPPORT, IAX_COMMAND_VNAK, IAX_DELAYPBXSTART, IAX_ENCRYPTED, iax_firmware_append(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_wrap(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLNO, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_FORMAT, IAX_IE_IAX_UNKNOWN, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_TRUNK, iax_ies::iax_unknown, iaxfrdup2(), iaxq, iaxs, iaxsl, inaddrcmp(), chan_iax2_pvt::initid, chan_iax2_pvt::iseqno, ast_iax2_full_hdr::iseqno, iax_frame::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_frame::len, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, len, ast_channel::lock, iax2_trunk_peer::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_trunk(), ast_frame::mallocd, manager_event(), iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, iax_ies::musiconhold, ast_channel::nativeformats, NEW_ALLOW, NEW_PREVENT, ast_frame::offset, option_debug, option_verbose, chan_iax2_pvt::oseqno, iax_frame::oseqno, ast_iax2_full_hdr::oseqno, iax_frame::outoforder, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), iax2_dpcache::peer, peer_ref(), peer_unref(), chan_iax2_pvt::peercallno, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, chan_iax2_pvt::prefs, iax_ies::provver, iax_ies::provverpres, raw_hangup(), ast_channel::readformat, iax_ies::refresh, REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), remove_by_peercallno(), iax_frame::retries, chan_iax2_pvt::rprefs, chan_iax2_pvt::rseqno, iax2_trunk_peer::rxtrunktime, S_OR, ast_frame::samples, save_rr(), ast_iax2_full_hdr::scallno, schedule_delivery(), send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax_ies::serviceident, iax2_peer::smoothing, spawn_dp_lookup(), ast_frame::src, chan_iax2_pvt::state, stop_stuff(), store_by_peercallno(), ast_frame::subclass, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MEDIAPASS, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, iax2_trunk_peer::trunkact, try_transfer(), ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_mini_hdr::ts, ast_iax2_meta_trunk_hdr::ts, ast_iax2_full_hdr::type, uncompress_subclass(), update_registry(), iax_ies::username, VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, chan_iax2_pvt::videoformat, vnak_retransmit(), chan_iax2_pvt::voiceformat, and ast_iax2_meta_hdr::zeros.

Referenced by handle_deferred_full_frames(), and iax2_process_thread().

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

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

Definition at line 6951 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), iax2_registry::callno, ast_iax2_full_hdr::csub, defer_full_frame(), errno, iax2_thread::ffinfo, find_idle_thread(), handle_error(), IAX_FLAG_FULL, IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, inaddrcmp(), len, LOG_DEBUG, LOG_WARNING, option_debug, ast_iax2_full_hdr::scallno, signal_condition(), t, thread, and ast_iax2_full_hdr::type.

Referenced by network_thread(), peer_set_srcaddr(), and set_config().

06952 {
06953    struct iax2_thread *thread;
06954    socklen_t len;
06955    time_t t;
06956    static time_t last_errtime = 0;
06957    struct ast_iax2_full_hdr *fh;
06958 
06959    if (!(thread = find_idle_thread())) {
06960       time(&t);
06961       if (t != last_errtime && option_debug)
06962          ast_log(LOG_DEBUG, "Out of idle IAX2 threads for I/O, pausing!\n");
06963       last_errtime = t;
06964       usleep(1);
06965       return 1;
06966    }
06967 
06968    len = sizeof(thread->iosin);
06969    thread->iofd = fd;
06970    thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
06971    thread->buf_size = sizeof(thread->readbuf);
06972    thread->buf = thread->readbuf;
06973    if (thread->buf_len < 0) {
06974       if (errno != ECONNREFUSED && errno != EAGAIN)
06975          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
06976       handle_error();
06977       thread->iostate = IAX_IOSTATE_IDLE;
06978       signal_condition(&thread->lock, &thread->cond);
06979       return 1;
06980    }
06981    if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
06982       thread->iostate = IAX_IOSTATE_IDLE;
06983       signal_condition(&thread->lock, &thread->cond);
06984       return 1;
06985    }
06986    
06987    /* Determine if this frame is a full frame; if so, and any thread is currently
06988       processing a full frame for the same callno from this peer, then drop this
06989       frame (and the peer will retransmit it) */
06990    fh = (struct ast_iax2_full_hdr *) thread->buf;
06991    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
06992       struct iax2_thread *cur = NULL;
06993       uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
06994       
06995       AST_LIST_LOCK(&active_list);
06996       AST_LIST_TRAVERSE(&active_list, cur, list) {
06997          if ((cur->ffinfo.callno == callno) &&
06998              !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
06999             break;
07000       }
07001       if (cur) {
07002          /* we found another thread processing a full frame for this call,
07003             so queue it up for processing later. */
07004          defer_full_frame(thread, cur);
07005          AST_LIST_UNLOCK(&active_list);
07006          thread->iostate = IAX_IOSTATE_IDLE;
07007          signal_condition(&thread->lock, &thread->cond);
07008          return 1;
07009       } else {
07010          /* this thread is going to process this frame, so mark it */
07011          thread->ffinfo.callno = callno;
07012          memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
07013          thread->ffinfo.type = fh->type;
07014          thread->ffinfo.csub = fh->csub;
07015       }
07016       AST_LIST_UNLOCK(&active_list);
07017    }
07018    
07019    /* Mark as ready and send on its way */
07020    thread->iostate = IAX_IOSTATE_READY;
07021 #ifdef DEBUG_SCHED_MULTITHREAD
07022    ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
07023 #endif
07024    signal_condition(&thread->lock, &thread->cond);
07025 
07026    return 1;
07027 }

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

Definition at line 6738 of file chan_iax2.c.

References ast_calloc, ast_log(), ast_pthread_create, ast_strdup, dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, dp_lookup_thread(), and LOG_WARNING.

Referenced by socket_process().

06739 {
06740    pthread_t newthread;
06741    struct dpreq_data *dpr;
06742    pthread_attr_t attr;
06743    
06744    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06745       return;
06746 
06747    pthread_attr_init(&attr);
06748    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06749 
06750    dpr->callno = callno;
06751    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06752    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06753    if (callerid)
06754       dpr->callerid = ast_strdup(callerid);
06755    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06756       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06757    }
06758 
06759    pthread_attr_destroy(&attr);
06760 }

static int start_network_thread ( void   )  [static]

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

09199 {
09200    pthread_attr_t attr;
09201    int threadcount = 0;
09202    int x;
09203    for (x = 0; x < iaxthreadcount; x++) {
09204       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
09205       if (thread) {
09206          thread->type = IAX_TYPE_POOL;
09207          thread->threadnum = ++threadcount;
09208          ast_mutex_init(&thread->lock);
09209          ast_cond_init(&thread->cond, NULL);
09210          pthread_attr_init(&attr);
09211          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
09212          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
09213             ast_log(LOG_WARNING, "Failed to create new thread!\n");
09214             free(thread);
09215             thread = NULL;
09216          }
09217          AST_LIST_LOCK(&idle_list);
09218          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
09219          AST_LIST_UNLOCK(&idle_list);
09220       }
09221    }
09222    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
09223    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
09224    if (option_verbose > 1)
09225       ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount);
09226    return 0;
09227 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 6420 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06421 {
06422    iax2_destroy_helper(iaxs[callno]);
06423 }

static void store_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

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

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_link(iax_peercallno_pvts, pvt);
01254 }

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

Definition at line 6607 of file chan_iax2.c.

References iax2_trunk_peer::addr, ast_inet_ntoa(), AST_IO_PRI, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, iax2_trunk_expired(), iax2_trunk_peer::lock, LOG_DEBUG, LOG_WARNING, MAX_TRUNKDATA, iax2_trunk_peer::next, option_debug, send_trunk(), tpeers, iax2_trunk_peer::trunkdataalloc, and iax2_trunk_peer::trunkdatalen.

Referenced by network_thread().

06608 {
06609    char buf[1024];
06610    int res;
06611    struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL;
06612    int processed = 0;
06613    int totalcalls = 0;
06614 #ifdef ZT_TIMERACK
06615    int x = 1;
06616 #endif
06617    struct timeval now;
06618    if (iaxtrunkdebug)
06619       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA);
06620    gettimeofday(&now, NULL);
06621    if (events & AST_IO_PRI) {
06622 #ifdef ZT_TIMERACK
06623       /* Great, this is a timing interface, just call the ioctl */
06624       if (ioctl(fd, ZT_TIMERACK, &x)) {
06625          ast_log(LOG_WARNING, "Unable to acknowledge zap timer. IAX trunking will fail!\n");
06626          usleep(1);
06627          return -1;
06628       }
06629 #endif      
06630    } else {
06631       /* Read and ignore from the pseudo channel for timing */
06632       res = read(fd, buf, sizeof(buf));
06633       if (res < 1) {
06634          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
06635          return 1;
06636       }
06637    }
06638    /* For each peer that supports trunking... */
06639    ast_mutex_lock(&tpeerlock);
06640    tpeer = tpeers;
06641    while(tpeer) {
06642       processed++;
06643       res = 0;
06644       ast_mutex_lock(&tpeer->lock);
06645       /* We can drop a single tpeer per pass.  That makes all this logic
06646          substantially easier */
06647       if (!drop && iax2_trunk_expired(tpeer, &now)) {
06648          /* Take it out of the list, but don't free it yet, because it
06649             could be in use */
06650          if (prev)
06651             prev->next = tpeer->next;
06652          else
06653             tpeers = tpeer->next;
06654          drop = tpeer;
06655       } else {
06656          res = send_trunk(tpeer, &now);
06657          if (iaxtrunkdebug)
06658             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);
06659       }     
06660       totalcalls += res;   
06661       res = 0;
06662       ast_mutex_unlock(&tpeer->lock);
06663       prev = tpeer;
06664       tpeer = tpeer->next;
06665    }
06666    ast_mutex_unlock(&tpeerlock);
06667    if (drop) {
06668       ast_mutex_lock(&drop->lock);
06669       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
06670          because by the time they could get tpeerlock, we've already grabbed it */
06671       if (option_debug)
06672          ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
06673       if (drop->trunkdata) {
06674          free(drop->trunkdata);
06675          drop->trunkdata = NULL;
06676       }
06677       ast_mutex_unlock(&drop->lock);
06678       ast_mutex_destroy(&drop->lock);
06679       free(drop);
06680       
06681    }
06682    if (iaxtrunkdebug)
06683       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
06684    iaxtrunkdebug =0;
06685    return 1;
06686 }

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

Definition at line 2072 of file chan_iax2.c.

References ast_log(), iax_frame::data, iax_frame::datalen, errno, handle_error(), LOG_DEBUG, and option_debug.

Referenced by send_trunk().

02073 {
02074    int res;
02075    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
02076                sizeof(*sin));
02077    if (res < 0) {
02078       if (option_debug)
02079          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
02080       handle_error();
02081    } else
02082       res = 0;
02083    return res;
02084 }

static int try_firmware ( char *  s  )  [static]

Definition at line 1760 of file chan_iax2.c.

References ast_calloc, ast_log(), ast_random(), ast_strlen_zero(), MD5Context::buf, ast_iax2_firmware_header::chksum, ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, iax_firmware::dead, ast_iax2_firmware_header::devname, errno, iax_firmware::fd, iax_firmware::fwh, IAX_FIRMWARE_MAGIC, last, len, LOG_WARNING, ast_iax2_firmware_header::magic, MD5Final(), MD5Init(), MD5Update(), iax_firmware::mmaplen, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.

Referenced by reload_firmware().

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

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

Definition at line 5813 of file chan_iax2.c.

References iax_ies::apparent_addr, AST_FRAME_IAX, ast_log(), iax_ie_data::buf, iax_ies::callno, IAX_COMMAND_TXCNT, iax_ie_append_int(), IAX_IE_TRANSFERID, LOG_WARNING, iax_ie_data::pos, send_command_transfer(), chan_iax2_pvt::transfer, TRANSFER_BEGIN, chan_iax2_pvt::transfercallno, iax_ies::transferid, chan_iax2_pvt::transferid, and chan_iax2_pvt::transferring.

Referenced by socket_process().

05814 {
05815    int newcall = 0;
05816    char newip[256];
05817    struct iax_ie_data ied;
05818    struct sockaddr_in new;
05819    
05820    
05821    memset(&ied, 0, sizeof(ied));
05822    if (ies->apparent_addr)
05823       bcopy(ies->apparent_addr, &new, sizeof(new));
05824    if (ies->callno)
05825       newcall = ies->callno;
05826    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05827       ast_log(LOG_WARNING, "Invalid transfer request\n");
05828       return -1;
05829    }
05830    pvt->transfercallno = newcall;
05831    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05832    inet_aton(newip, &pvt->transfer.sin_addr);
05833    pvt->transfer.sin_family = AF_INET;
05834    pvt->transferring = TRANSFER_BEGIN;
05835    pvt->transferid = ies->transferid;
05836    if (ies->transferid)
05837       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05838    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05839    return 0; 
05840 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1091 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

01092 {
01093    /* If the SC_LOG flag is set, return 2^csub otherwise csub */
01094    if (csub & IAX_FLAG_SC_LOG) {
01095       /* special case for 'compressed' -1 */
01096       if (csub == 0xff)
01097          return -1;
01098       else
01099          return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT);
01100    }
01101    else
01102       return csub;
01103 }

static void unlink_peer ( struct iax2_peer peer  )  [static]

Definition at line 6085 of file chan_iax2.c.

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

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

06086 {
06087    if (peer->expire > -1) {
06088       if (!ast_sched_del(sched, peer->expire)) {
06089          peer->expire = -1;
06090          peer_unref(peer);
06091       }
06092    }
06093 
06094    if (peer->pokeexpire > -1) {
06095       if (!ast_sched_del(sched, peer->pokeexpire)) {
06096          peer->pokeexpire = -1;
06097          peer_unref(peer);
06098       }
06099    }
06100 
06101    ao2_unlink(peers, peer);
06102 }

static int unload_module ( void   )  [static]

Definition at line 11123 of file chan_iax2.c.

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

11124 {
11125    ast_custom_function_unregister(&iaxpeer_function);
11126    return __unload_module();
11127 }

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

Definition at line 3491 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03492 {
03493    ast_mutex_unlock(&iaxsl[callno1]);
03494    ast_mutex_unlock(&iaxsl[callno0]);
03495 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

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

02518 {
02519    int x;
02520 
02521    if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) {
02522       x = fr->ts - iaxs[fr->callno]->last;
02523       if (x < -50000) {
02524          /* Sudden big jump backwards in timestamp:
02525             What likely happened here is that miniframe timestamp has circled but we haven't
02526             gotten the update from the main packet.  We'll just pretend that we did, and
02527             update the timestamp appropriately. */
02528          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
02529          if (option_debug && iaxdebug)
02530             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02531       }
02532       if (x > 50000) {
02533          /* Sudden apparent big jump forwards in timestamp:
02534             What's likely happened is this is an old miniframe belonging to the previous
02535             top-16-bit timestamp that has turned up out of order.
02536             Adjust the timestamp appropriately. */
02537          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
02538          if (option_debug && iaxdebug)
02539             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02540       }
02541    }
02542 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 2546 of file chan_iax2.c.

References AST_SCHED_DEL, chan_iax2_pvt::callno, CALLNO_TO_PTR, get_from_jb(), iax2_sched_add(), chan_iax2_pvt::jb, jb_next(), chan_iax2_pvt::jbid, and chan_iax2_pvt::rxcore.

Referenced by __get_from_jb(), and schedule_delivery().

02547 {
02548    int when;
02549    
02550    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02551    
02552    when = jb_next(pvt->jb) - when;
02553 
02554    AST_SCHED_DEL(sched, pvt->jbid);
02555 
02556    if(when <= 0) {
02557       /* XXX should really just empty until when > 0.. */
02558       when = 1;
02559    }
02560    
02561    pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02562 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1459 of file chan_iax2.c.

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

Referenced by __find_callno(), and make_trunk().

01460 {
01461    int max = 1;
01462    int x;
01463    /* XXX Prolly don't need locks here XXX */
01464    for (x=1;x<TRUNK_CALL_START - 1; x++) {
01465       if (iaxs[x])
01466          max = x + 1;
01467    }
01468    maxnontrunkcall = max;
01469    if (option_debug && iaxdebug)
01470       ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max);
01471 }

static void update_max_trunk ( void   )  [static]

Definition at line 1266 of file chan_iax2.c.

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

Referenced by iax2_destroy(), and make_trunk().

01267 {
01268    int max = TRUNK_CALL_START;
01269    int x;
01270 
01271    /* XXX Prolly don't need locks here XXX */
01272    for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) {
01273       if (iaxs[x]) {
01274          max = x + 1;
01275       }
01276    }
01277 
01278    maxtrunkcall = max;
01279    if (option_debug && iaxdebug)
01280       ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max);
01281 }

static int update_packet ( struct iax_frame f  )  [static]

Definition at line 2143 of file chan_iax2.c.

References iax_frame::callno, iax_frame::data, iax_frame::datalen, iax_frame::dcallno, ast_iax2_full_hdr::dcallno, decode_frame(), iax_frame::ecx, iax_frame::encmethods, encrypt_frame(), IAX_FLAG_RETRANS, iaxs, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, iax_frame::mydcx, and iax_frame::semirand.

Referenced by __attempt_transmit().

02144 {
02145    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02146    struct ast_iax2_full_hdr *fh = f->data;
02147    struct ast_frame af;
02148 
02149    /* if frame is encrypted. decrypt before updating it. */
02150    if (f->encmethods) {
02151       decode_frame(&f->mydcx, fh, &af, &f->datalen);
02152    }
02153    /* Mark this as a retransmission */
02154    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02155    /* Update iseqno */
02156    f->iseqno = iaxs[f->callno]->iseqno;
02157    fh->iseqno = f->iseqno;
02158 
02159    /* Now re-encrypt the frame */
02160    if (f->encmethods) {
02161       encrypt_frame(&f->ecx, fh, f->semirand, &f->datalen);
02162    }
02163    return 0;
02164 }

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

References iax2_peer::addr, ast_app_inboxcount(), ast_db_del(), ast_db_put(), ast_device_state_changed(), AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verbose(), iax_ie_data::buf, EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), iax2_datetime(), iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), iax_check_version(), IAX_COMMAND_REGACK, IAX_HASCALLERID, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_DATETIME, IAX_IE_FIRMWAREVER, IAX_IE_MSGCOUNT, IAX_IE_REFRESH, IAX_IE_USERNAME, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_STATE_AUTHENTICATED, IAX_TEMPONLY, iaxs, iaxsl, inaddrcmp(), LOG_NOTICE, LOG_WARNING, manager_event(), option_verbose, peer_ref(), peer_unref(), iax_ie_data::pos, realtime_update_peer(), register_peer_exten(), send_command_final(), iax2_peer::sockfd, and VERBOSE_PREFIX_3.

Referenced by socket_process().

06197 {
06198    /* Called from IAX thread only, with proper iaxsl lock */
06199    struct iax_ie_data ied;
06200    struct iax2_peer *p;
06201    int msgcount;
06202    char data[80];
06203    int version;
06204    const char *peer_name;
06205    int res = -1;
06206 
06207    memset(&ied, 0, sizeof(ied));
06208 
06209    peer_name = ast_strdupa(iaxs[callno]->peer);
06210 
06211    /* SLD: Another find_peer call during registration - this time when we are really updating our registration */
06212    ast_mutex_unlock(&iaxsl[callno]);
06213    if (!(p = find_peer(peer_name, 1))) {
06214       ast_mutex_lock(&iaxsl[callno]);
06215       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
06216       return -1;
06217    }
06218    ast_mutex_lock(&iaxsl[callno]);
06219    if (!iaxs[callno])
06220       goto return_unref;
06221 
06222    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) {
06223       if (sin->sin_addr.s_addr) {
06224          time_t nowtime;
06225          time(&nowtime);
06226          realtime_update_peer(peer_name, sin, nowtime);
06227       } else {
06228          realtime_update_peer(peer_name, sin, 0);
06229       }
06230    }
06231    if (inaddrcmp(&p->addr, sin)) {
06232       if (iax2_regfunk)
06233          iax2_regfunk(p->name, 1);
06234       /* Stash the IP address from which they registered */
06235       memcpy(&p->addr, sin, sizeof(p->addr));
06236       snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry);
06237       if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) {
06238          ast_db_put("IAX/Registry", p->name, data);
06239          if  (option_verbose > 2)
06240             ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 
06241                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
06242          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name);
06243          register_peer_exten(p, 1);
06244          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06245       } else if (!ast_test_flag(p, IAX_TEMPONLY)) {
06246          if  (option_verbose > 2)
06247             ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 
06248                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED");
06249          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name);
06250          register_peer_exten(p, 0);
06251          ast_db_del("IAX/Registry", p->name);
06252          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06253       }
06254       /* Update the host */
06255       /* Verify that the host is really there */
06256       iax2_poke_peer(p, callno);
06257    }     
06258 
06259    /* Make sure our call still exists, an INVAL at the right point may make it go away */
06260    if (!iaxs[callno]) {
06261       res = 0;
06262       goto return_unref;
06263    }
06264 
06265    /* Store socket fd */
06266    p->sockfd = fd;
06267    /* Setup the expiry */
06268    if (p->expire > -1) {
06269       if (!ast_sched_del(sched, p->expire)) {
06270          p->expire = -1;
06271          peer_unref(p);
06272       }
06273    }
06274    /* treat an unspecified refresh interval as the minimum */
06275    if (!refresh)
06276       refresh = min_reg_expire;
06277    if (refresh > max_reg_expire) {
06278       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
06279          p->name, max_reg_expire, refresh);
06280       p->expiry = max_reg_expire;
06281    } else if (refresh < min_reg_expire) {
06282       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
06283          p->name, min_reg_expire, refresh);
06284       p->expiry = min_reg_expire;
06285    } else {
06286       p->expiry = refresh;
06287    }
06288    if (p->expiry && sin->sin_addr.s_addr) {
06289       p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
06290       if (p->expire == -1)
06291          peer_unref(p);
06292    }
06293    iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
06294    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag));
06295    if (sin->sin_addr.s_addr) {
06296       iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry);
06297       iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
06298       if (!ast_strlen_zero(p->mailbox)) {
06299          int new, old;
06300          ast_app_inboxcount(p->mailbox, &new, &old);
06301          if (new > 255)
06302             new = 255;
06303          if (old > 255)
06304             old = 255;
06305          msgcount = (old << 8) | new;
06306          iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
06307       }
06308       if (ast_test_flag(p, IAX_HASCALLERID)) {
06309          iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num);
06310          iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name);
06311       }
06312    }
06313    version = iax_check_version(devtype);
06314    if (version) 
06315       iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version);
06316 
06317    res = 0;
06318 
06319 return_unref:
06320    peer_unref(p);
06321 
06322    return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
06323 }

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

Referenced by load_module().

01139 {
01140    struct iax2_user *user = obj, *user2 = arg;
01141 
01142    return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0;
01143 }

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

Definition at line 9838 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09839 {
09840    struct iax2_user *user = obj;
09841 
09842    ast_set_flag(user, IAX_DELME);
09843 
09844    return 0;
09845 }

static void user_destructor ( void *  obj  )  [static]

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

09603 {
09604    struct iax2_user *user = obj;
09605 
09606    ast_free_ha(user->ha);
09607    free_context(user->contexts);
09608    if(user->vars) {
09609       ast_variables_destroy(user->vars);
09610       user->vars = NULL;
09611    }
09612    ast_string_field_free_memory(user);
09613 }

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

References ast_str_hash().

Referenced by load_module().

01129 {
01130    const struct iax2_user *user = obj;
01131 
01132    return ast_str_hash(user->name);
01133 }

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

Definition at line 1177 of file chan_iax2.c.

References ao2_ref().

01178 {
01179    ao2_ref(user, +1);
01180    return user;
01181 }

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

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

01184 {
01185    ao2_ref(user, -1);
01186    return NULL;
01187 }

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

Definition at line 6521 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax_frame::callno, f, iaxq, iaxs, iax_frame::oseqno, iax_frame::retries, and send_packet().

Referenced by socket_process().

06522 {
06523    struct iax_frame *f;
06524 
06525    AST_LIST_LOCK(&iaxq.queue);
06526    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06527       /* Send a copy immediately */
06528       if ((f->callno == callno) && iaxs[f->callno] &&
06529          ((unsigned char ) (f->oseqno - last) < 128) &&
06530          (f->retries >= 0)) {
06531          send_packet(f);
06532       }
06533    }
06534    AST_LIST_UNLOCK(&iaxq.queue);
06535 }


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

int adsi = 0 [static]

Definition at line 223 of file chan_iax2.c.

int amaflags = 0 [static]

Definition at line 222 of file chan_iax2.c.

int authdebug = 1 [static]

Definition at line 158 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 159 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 10939 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

Initial value:

 {
   { "iax2", "jb", "debug", NULL },
   iax2_do_jb_debug, NULL,
   NULL }

Definition at line 10919 of file chan_iax2.c.

Initial value:

 {
   { "iax2", "no", "debug", NULL },
   iax2_no_debug, NULL,
   NULL }

Definition at line 10924 of file chan_iax2.c.

Initial value:

 {
   { "iax2", "no", "jb", "debug", NULL },
   iax2_no_jb_debug, NULL,
   NULL }

Definition at line 10934 of file chan_iax2.c.

Initial value:

 {
   { "iax2", "no", "trunk", "debug", NULL },
   iax2_no_trunk_debug, NULL,
   NULL }

Definition at line 10929 of file chan_iax2.c.

Initial value:

 {
   { "iax2", "trunk", "debug", NULL },
   iax2_do_trunk_debug, NULL,
   NULL }

Definition at line 10914 of file chan_iax2.c.

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

Definition at line 145 of file chan_iax2.c.

char debug_jb_usage[] [static]

Initial value:

"Usage: iax2 set debug jb\n"
"       Enables jitterbuffer debugging information\n"

Definition at line 10888 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 10880 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 10872 of file chan_iax2.c.

int defaultsockfd = -1 [static]

Definition at line 176 of file chan_iax2.c.

int delayreject = 0 [static]

Definition at line 224 of file chan_iax2.c.

struct iax2_dpcache * dpcache [static]

Referenced by find_cache(), and iax2_show_cache().

int global_rtautoclear = 120 [static]

Definition at line 277 of file chan_iax2.c.

struct ast_flags globalflags = { 0 } [static]

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 205 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 225 of file chan_iax2.c.

enum { ... } iax2_flags

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

char iax2_reload_usage[] [static]

Initial value:

"Usage: iax2 reload\n"
"       Reloads IAX configuration from iax.conf\n"

Definition at line 10830 of file chan_iax2.c.

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10804 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

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

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

Referenced by __find_callno(), __unload_module(), load_module(), remove_by_peercallno(), and store_by_peercallno().

int iaxactivethreadcount = 0 [static]

Definition at line 453 of file chan_iax2.c.

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

int iaxcompat = 0 [static]

Definition at line 160 of file chan_iax2.c.

int iaxdebug = 0 [static]

Definition at line 207 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 163 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 165 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 452 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 451 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

Definition at line 10740 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

struct ast_iax2_queue iaxq [static]

struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static]

ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static]

int iaxthreadcount = DEFAULT_THREAD_COUNT [static]

Definition at line 450 of file chan_iax2.c.

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

int iaxtrunkdebug = 0 [static]

Definition at line 209 of file chan_iax2.c.

struct io_context* io [static]

Definition at line 202 of file chan_iax2.c.

int lagrq_time = 10 [static]

Definition at line 153 of file chan_iax2.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 147 of file chan_iax2.c.

int last_authmethod = 0 [static]

Definition at line 161 of file chan_iax2.c.

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

Definition at line 817 of file chan_iax2.c.

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

int max_reg_expire [static]

Definition at line 170 of file chan_iax2.c.

int max_retries = 4 [static]

Definition at line 151 of file chan_iax2.c.

int maxauthreq = 3 [static]

Definition at line 150 of file chan_iax2.c.

int maxjitterbuffer = 1000 [static]

Definition at line 154 of file chan_iax2.c.

int maxjitterinterps = 10 [static]

Definition at line 156 of file chan_iax2.c.

int maxnontrunkcall = 1 [static]

Definition at line 835 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_nontrunk().

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 834 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_trunk().

int min_reg_expire [static]

Definition at line 169 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 220 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

Definition at line 221 of file chan_iax2.c.

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

struct ast_netsock_list* netsock [static]

Definition at line 174 of file chan_iax2.c.

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 229 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 10892 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 10884 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 10876 of file chan_iax2.c.

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 175 of file chan_iax2.c.

char* papp = "IAX2Provision" [static]

Definition at line 8845 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

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

Referenced by load_module().

struct ao2_container* peers [static]

int ping_time = 21 [static]

Definition at line 152 of file chan_iax2.c.

struct ast_codec_pref prefs [static]

char prune_realtime_usage[] [static]

Initial value:

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

Definition at line 10826 of file chan_iax2.c.

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

Definition at line 8846 of file chan_iax2.c.

Referenced by load_module().

char regcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 148 of file chan_iax2.c.

int resyncthreshold = 1000 [static]

Definition at line 155 of file chan_iax2.c.

struct sched_context* sched [static]

Definition at line 203 of file chan_iax2.c.

Definition at line 232 of file chan_iax2.c.

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 230 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 10818 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 10846 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 10864 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 10850 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 10822 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 10858 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10834 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 10868 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 10814 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 10854 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 10841 of file chan_iax2.c.

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

Definition at line 143 of file chan_iax2.c.

int test_losspct = 0 [static]

Definition at line 211 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 172 of file chan_iax2.c.

unsigned int tos = 0 [static]

Definition at line 167 of file chan_iax2.c.

struct iax2_trunk_peer * tpeers [static]

Referenced by find_tpeer(), and timing_read().

int trunkfreq = 20 [static]

Definition at line 157 of file chan_iax2.c.

struct ao2_container* users [static]

struct ast_firmware_list waresl [static]


Generated on Thu Oct 8 21:57:39 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.8