Fri Aug 24 02:23:54 2007

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"

Include dependency graph for chan_iax2.c:

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   0x4000
#define TS_GAP_FOR_JB_RESYNC   5000

Enumerations

enum  { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2), IAX_STATE_UNCHANGED = (1 << 3) }
enum  {
  IAX_HASCALLERID = (1 << 0), IAX_DELME = (1 << 1), IAX_TEMPONLY = (1 << 2), IAX_TRUNK = (1 << 3),
  IAX_NOTRANSFER = (1 << 4), IAX_USEJITTERBUF = (1 << 5), IAX_DYNAMIC = (1 << 6), IAX_SENDANI = (1 << 7),
  IAX_ALREADYGONE = (1 << 9), IAX_PROVISION = (1 << 10), IAX_QUELCH = (1 << 11), IAX_ENCRYPTED = (1 << 12),
  IAX_KEYPOPULATED = (1 << 13), IAX_CODEC_USER_FIRST = (1 << 14), IAX_CODEC_NOPREFS = (1 << 15), IAX_CODEC_NOCAP = (1 << 16),
  IAX_RTCACHEFRIENDS = (1 << 17), IAX_RTUPDATE = (1 << 18), IAX_RTAUTOCLEAR = (1 << 19), IAX_FORCEJITTERBUF = (1 << 20),
  IAX_RTIGNOREREGEXPIRE = (1 << 21), IAX_TRUNKTIMESTAMPS = (1 << 22), IAX_TRANSFERMEDIA = (1 << 23), IAX_MAXAUTHREQ = (1 << 24),
  IAX_DELAYPBXSTART = (1 << 25)
}
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 (void *data)
static void __auth_reject (void *nothing)
static void __auto_congest (void *nothing)
static void __auto_hangup (void *nothing)
static int __do_deliver (void *data)
static void __expire_registry (void *data)
static void __get_from_jb (void *p)
static void __iax2_do_register_s (void *data)
static void __iax2_poke_noanswer (void *data)
static void __iax2_poke_peer_s (void *data)
static int __iax2_show_peers (int manager, int fd, struct mansession *s, int argc, char *argv[])
static int __schedule_action (void(*func)(void *data), 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 (void *data)
static void __send_ping (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 (void *data)
static int auth_fail (int callno, int failcode)
static int auth_reject (void *data)
static int authenticate (const char *challenge, const char *secret, const char *keyn, int authmethods, struct iax_ie_data *ied, struct sockaddr_in *sin, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx)
static int authenticate_reply (struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, const char *override, const char *okey)
static int authenticate_request (int call_num)
static int authenticate_verify (struct chan_iax2_pvt *p, struct iax_ies *ies)
static int auto_congest (void *data)
static int auto_hangup (void *data)
static struct iax2_contextbuild_context (char *context)
static void build_enc_keys (const unsigned char *digest, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx)
static struct iax2_peerbuild_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly)
 Create peer structure based on configuration.
static struct iax2_userbuild_user (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly)
 Create in-memory user structure from configuration.
static int cache_get_callno_locked (const char *data)
static unsigned int calc_rxstamp (struct chan_iax2_pvt *p, unsigned int offset)
static unsigned int calc_timestamp (struct chan_iax2_pvt *p, unsigned int ts, struct ast_frame *f)
static unsigned int calc_txpeerstamp (struct iax2_trunk_peer *tpeer, int sampms, struct timeval *tv)
static int check_access (int callno, struct sockaddr_in *sin, struct iax_ies *ies)
static int check_provisioning (struct sockaddr_in *sin, int sockfd, char *si, unsigned int ver)
static int check_srcaddr (struct sockaddr *sa, socklen_t salen)
 Check if address can be used as packet source.
static int complete_dpreply (struct chan_iax2_pvt *pvt, struct iax_ies *ies)
static char * complete_iax2_show_peer (const char *line, const char *word, int pos, int state)
static int complete_transfer (int callno, struct iax_ies *ies)
static unsigned char compress_subclass (int subclass)
static void construct_rr (struct chan_iax2_pvt *pvt, struct iax_ie_data *iep)
static int create_addr (const char *peername, struct 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 (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)
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 (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 (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 (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 (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_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)
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 prune_peers (void)
static void prune_users (void)
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)
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 (void)
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_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 (void *data)
static int send_packet (struct iax_frame *f)
static int send_ping (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_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 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 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 int iaxactivethreadcount = 0
static int iaxcompat = 0
static int iaxdebug = 0
static int iaxdefaultdpcache = 10 * 60
static int iaxdefaulttimeout = 5
static int iaxdynamicthreadcount = 0
static int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT
ast_custom_function iaxpeer_function
static struct ast_iax2_queue iaxq
static struct chan_iax2_pvtiaxs [IAX_MAX_CALLS]
static ast_mutex_t iaxsl [IAX_MAX_CALLS]
static int iaxthreadcount = DEFAULT_THREAD_COUNT
static int iaxtrunkdebug = 0
static struct io_contextio
static int lagrq_time = 10
static char language [MAX_LANGUAGE] = ""
static struct timeval lastused [IAX_MAX_CALLS]
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 ao2_container * peers
static int ping_time = 21
static struct ast_codec_pref prefs
static char prune_realtime_usage []
static char * psyn = "Provision a calling IAXy with a given template"
static char regcontext [AST_MAX_CONTEXT] = ""
static int resyncthreshold = 1000
static struct sched_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 ao2_container * users
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 663 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 659 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 673 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 661 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 665 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 667 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

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

Referenced by complete_dpreply(), and iax2_show_cache().

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

Definition at line 122 of file chan_iax2.c.

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

#define DEBUG_SCHED_MULTITHREAD

Definition at line 110 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 133 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 128 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 125 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 126 of file chan_iax2.c.

Referenced by complete_transfer(), and find_callno().

#define DEFAULT_THREAD_COUNT   10

Definition at line 124 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 138 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 694 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 696 of file chan_iax2.c.

#define IAX_IOSTATE_READY   1

Definition at line 695 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 697 of file chan_iax2.c.

Referenced by __schedule_action().

#define IAX_TYPE_DYNAMIC   2

Definition at line 700 of file chan_iax2.c.

Referenced by find_idle_thread(), iax2_process_thread(), iax2_show_threads(), and insert_idle_thread().

#define IAX_TYPE_POOL   1

Definition at line 699 of file chan_iax2.c.

Referenced by start_network_thread().

#define IPTOS_MINCOST   0x02

Definition at line 113 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 645 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 650 of file chan_iax2.c.

Referenced by load_module().

#define MEMORY_SIZE   100

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

Referenced by find_callno(), and make_trunk().

#define NEW_ALLOW   1

Definition at line 1226 of file chan_iax2.c.

Referenced by find_callno(), and socket_process().

#define NEW_FORCE   2

Definition at line 1227 of file chan_iax2.c.

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

#define NEW_PREVENT   0

Definition at line 1225 of file chan_iax2.c.

Referenced by socket_process().

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

Definition at line 121 of file chan_iax2.c.

Referenced by __auto_congest(), __get_from_jb(), function_iaxpeer(), iax2_answer(), iax2_bridge(), iax2_call(), iax2_digit_begin(), iax2_digit_end(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_prov_app(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), iax2_transfer(), and iax2_write().

#define SCHED_MULTITHREADED

Definition at line 106 of file chan_iax2.c.

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

Definition at line 963 of file chan_iax2.c.

Referenced by attempt_transmit(), auth_reject(), auto_congest(), auto_hangup(), expire_registry(), get_from_jb(), iax2_do_register_s(), iax2_poke_noanswer(), iax2_poke_peer_s(), send_lagrq(), and send_ping().

#define TRUNK_CALL_START   0x4000

Definition at line 131 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 
IAX_STATE_UNCHANGED 

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    IAX_STATE_UNCHANGED =      (1 << 3),
00239 } 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

Definition at line 246 of file chan_iax2.c.

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

enum iax_reg_state

Enumerator:
REG_STATE_UNREGISTERED 
REG_STATE_REGSENT 
REG_STATE_AUTHSENT 
REG_STATE_REGISTERED 
REG_STATE_REJECTED 
REG_STATE_TIMEOUT 
REG_STATE_NOAUTH 

Definition at line 394 of file chan_iax2.c.

enum iax_transfer_state

Enumerator:
TRANSFER_NONE 
TRANSFER_BEGIN 
TRANSFER_READY 
TRANSFER_RELEASED 
TRANSFER_PASSTHROUGH 
TRANSFER_MBEGIN 
TRANSFER_MREADY 
TRANSFER_MRELEASED 
TRANSFER_MPASSTHROUGH 
TRANSFER_MEDIA 
TRANSFER_MEDIAPASS 

Definition at line 404 of file chan_iax2.c.


Function Documentation

static void __attempt_transmit ( void *  data  )  [static]

Definition at line 2032 of file chan_iax2.c.

References chan_iax2_pvt::addr, 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(), ast_sched_add(), attempt_transmit(), iax_frame::callno, chan_iax2_pvt::error, f, ast_frame::frametype, ast_channel::hangupcause, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iaxq, iaxs, iaxsl, LOG_WARNING, MAX_RETRY_TIME, chan_iax2_pvt::owner, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), send_packet(), ast_frame::subclass, update_packet(), and iax2_registry::us.

Referenced by attempt_transmit().

02033 {
02034    /* Attempt to transmit the frame to the remote peer...
02035       Called without iaxsl held. */
02036    struct iax_frame *f = data;
02037    int freeme=0;
02038    int callno = f->callno;
02039    /* Make sure this call is still active */
02040    if (callno) 
02041       ast_mutex_lock(&iaxsl[callno]);
02042    if (callno && iaxs[callno]) {
02043       if ((f->retries < 0) /* Already ACK'd */ ||
02044           (f->retries >= max_retries) /* Too many attempts */) {
02045             /* Record an error if we've transmitted too many times */
02046             if (f->retries >= max_retries) {
02047                if (f->transfer) {
02048                   /* Transfer timeout */
02049                   send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
02050                } else if (f->final) {
02051                   if (f->final) 
02052                      iax2_destroy(callno);
02053                } else {
02054                   if (iaxs[callno]->owner)
02055                      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);
02056                   iaxs[callno]->error = ETIMEDOUT;
02057                   if (iaxs[callno]->owner) {
02058                      struct ast_frame fr = { 0, };
02059                      /* Hangup the fd */
02060                      fr.frametype = AST_FRAME_CONTROL;
02061                      fr.subclass = AST_CONTROL_HANGUP;
02062                      iax2_queue_frame(callno, &fr); // XXX
02063                      /* Remember, owner could disappear */
02064                      if (iaxs[callno] && iaxs[callno]->owner)
02065                         iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
02066                   } else {
02067                      if (iaxs[callno]->reg) {
02068                         memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us));
02069                         iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT;
02070                         iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE;
02071                      }
02072                      iax2_destroy(callno);
02073                   }
02074                }
02075 
02076             }
02077             freeme++;
02078       } else {
02079          /* Update it if it needs it */
02080          update_packet(f);
02081          /* Attempt transmission */
02082          send_packet(f);
02083          f->retries++;
02084          /* Try again later after 10 times as long */
02085          f->retrytime *= 10;
02086          if (f->retrytime > MAX_RETRY_TIME)
02087             f->retrytime = MAX_RETRY_TIME;
02088          /* Transfer messages max out at one second */
02089          if (f->transfer && (f->retrytime > 1000))
02090             f->retrytime = 1000;
02091          f->retrans = ast_sched_add(sched, f->retrytime, attempt_transmit, f);
02092       }
02093    } else {
02094       /* Make sure it gets freed */
02095       f->retries = -1;
02096       freeme++;
02097    }
02098    if (callno)
02099       ast_mutex_unlock(&iaxsl[callno]);
02100    /* Do not try again */
02101    if (freeme) {
02102       /* Don't attempt delivery, just remove it from the queue */
02103       AST_LIST_LOCK(&iaxq.queue);
02104       AST_LIST_REMOVE(&iaxq.queue, f, list);
02105       iaxq.count--;
02106       AST_LIST_UNLOCK(&iaxq.queue);
02107       f->retrans = -1;
02108       /* Free the IAX frame */
02109       iax2_frame_free(f);
02110    }
02111 }

static void __auth_reject ( void *  nothing  )  [static]

Definition at line 6072 of file chan_iax2.c.

References AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_FACILITY_REJECTED, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), IAX_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, and send_command_final().

Referenced by auth_reject().

06073 {
06074    /* Called from IAX thread only, without iaxs lock */
06075    int callno = (int)(long)(nothing);
06076    struct iax_ie_data ied;
06077    ast_mutex_lock(&iaxsl[callno]);
06078    if (iaxs[callno]) {
06079       memset(&ied, 0, sizeof(ied));
06080       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
06081          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
06082          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
06083       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
06084          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
06085          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
06086       }
06087       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
06088    }
06089    ast_mutex_unlock(&iaxsl[callno]);
06090 }

static void __auto_congest ( void *  nothing  )  [static]

Definition at line 2921 of file chan_iax2.c.

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

Referenced by auto_congest().

02922 {
02923    int callno = PTR_TO_CALLNO(nothing);
02924    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
02925    ast_mutex_lock(&iaxsl[callno]);
02926    if (iaxs[callno]) {
02927       iaxs[callno]->initid = -1;
02928       iax2_queue_frame(callno, &f);
02929       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
02930    }
02931    ast_mutex_unlock(&iaxsl[callno]);
02932 }

static void __auto_hangup ( void *  nothing  )  [static]

Definition at line 6122 of file chan_iax2.c.

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

Referenced by auto_hangup().

06123 {
06124    /* Called from IAX thread only, without iaxs lock */
06125    int callno = (int)(long)(nothing);
06126    struct iax_ie_data ied;
06127    ast_mutex_lock(&iaxsl[callno]);
06128    if (iaxs[callno]) {
06129       memset(&ied, 0, sizeof(ied));
06130       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
06131       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
06132       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
06133    }
06134    ast_mutex_unlock(&iaxsl[callno]);
06135 }

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

References iax_frame::af, ast_test_flag, iax_frame::callno, ast_frame::has_timing_info, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, iaxs, and iax_frame::retrans.

Referenced by __get_from_jb(), and schedule_delivery().

01784 {
01785    /* Just deliver the packet by using queueing.  This is called by
01786      the IAX thread with the iaxsl lock held. */
01787    struct iax_frame *fr = data;
01788    fr->retrans = -1;
01789    fr->af.has_timing_info = 0;
01790    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
01791       iax2_queue_frame(fr->callno, &fr->af);
01792    /* Free our iax frame */
01793    iax2_frame_free(fr);
01794    /* And don't run again */
01795    return 0;
01796 }

static void __expire_registry ( void *  data  )  [static]

Definition at line 5769 of file chan_iax2.c.

References iax2_peer::addr, ao2_find(), ao2_unlink(), ast_db_del(), ast_device_state_changed(), ast_log(), ast_test_flag, EVENT_FLAG_SYSTEM, iax2_peer::expire, iax2_peer::expiry, globalflags, iax2_regfunk, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, manager_event(), name, peer_unref(), peers, realtime_update_peer(), and register_peer_exten().

Referenced by expire_registry().

05770 {
05771    char *name = data;
05772    struct iax2_peer *peer = NULL;
05773    struct iax2_peer tmp_peer = {
05774       .name = name,
05775    };
05776 
05777    peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
05778    if (!peer)
05779       return;
05780 
05781    peer->expire = -1;
05782 
05783    ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name);
05784    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
05785       realtime_update_peer(peer->name, &peer->addr, 0);
05786    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
05787    /* Reset the address */
05788    memset(&peer->addr, 0, sizeof(peer->addr));
05789    /* Reset expiry value */
05790    peer->expiry = min_reg_expire;
05791    if (!ast_test_flag(peer, IAX_TEMPONLY))
05792       ast_db_del("IAX/Registry", peer->name);
05793    register_peer_exten(peer, 0);
05794    ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
05795    if (iax2_regfunk)
05796       iax2_regfunk(peer->name, 0);
05797 
05798    if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
05799       ao2_unlink(peers, peer);
05800 
05801    peer_unref(peer);
05802 }

static void __get_from_jb ( void *  p  )  [static]

Definition at line 2432 of file chan_iax2.c.

References __do_deliver(), ast_backtrace(), ast_codec_interp_len(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_tvadd(), jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, iaxs, iaxsl, chan_iax2_pvt::jb, JB_DROP, JB_EMPTY, jb_get(), JB_INTERP, jb_next(), JB_NOFRAME, JB_OK, chan_iax2_pvt::jbid, LOG_ERROR, 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().

02433 {
02434    int callno = PTR_TO_CALLNO(p);
02435    struct chan_iax2_pvt *pvt = NULL;
02436    struct iax_frame *fr;
02437    jb_frame frame;
02438    int ret;
02439    long now;
02440    long next;
02441    struct timeval tv;
02442    
02443    /* Make sure we have a valid private structure before going on */
02444    ast_mutex_lock(&iaxsl[callno]);
02445    pvt = iaxs[callno];
02446    if (!pvt) {
02447       /* No go! */
02448       ast_mutex_unlock(&iaxsl[callno]);
02449       return;
02450    }
02451     
02452     if( pvt->jb == NULL ) {
02453    ast_log( LOG_ERROR, "__get_from_jb(): why p->jb is null?\n" );
02454    ast_backtrace();
02455    return;
02456     }
02457 
02458    pvt->jbid = -1;
02459    
02460    gettimeofday(&tv,NULL);
02461    /* round up a millisecond since ast_sched_runq does; */
02462    /* prevents us from spinning while waiting for our now */
02463    /* to catch up with runq's now */
02464    tv.tv_usec += 1000;
02465    
02466    now = ast_tvdiff_ms(tv, pvt->rxcore);
02467    
02468    if(now >= (next = jb_next(pvt->jb))) {
02469       ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
02470       switch(ret) {
02471       case JB_OK:
02472          fr = frame.data;
02473          __do_deliver(fr);
02474          /* __do_deliver() can cause the call to disappear */
02475          pvt = iaxs[callno];
02476          break;
02477       case JB_INTERP:
02478       {
02479          struct ast_frame af = { 0, };
02480          
02481          /* create an interpolation frame */
02482          af.frametype = AST_FRAME_VOICE;
02483          af.subclass = pvt->voiceformat;
02484          af.samples  = frame.ms * 8;
02485          af.src  = "IAX2 JB interpolation";
02486          af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
02487          af.offset = AST_FRIENDLY_OFFSET;
02488          
02489          /* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
02490           * which we'd need to malloc, and then it would free it.  That seems like a drag */
02491          if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
02492             iax2_queue_frame(callno, &af);
02493             /* iax2_queue_frame() could cause the call to disappear */
02494             pvt = iaxs[callno];
02495          }
02496       }
02497          break;
02498       case JB_DROP:
02499          iax2_frame_free(frame.data);
02500          break;
02501       case JB_NOFRAME:
02502       case JB_EMPTY:
02503          /* do nothing */
02504          break;
02505       default:
02506          /* shouldn't happen */
02507          break;
02508       }
02509    }
02510    if (pvt)
02511       update_jbsched(pvt);
02512    ast_mutex_unlock(&iaxsl[callno]);
02513 }

static void __iax2_do_register_s ( void *  data  )  [static]

Definition at line 5486 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05487 {
05488    struct iax2_registry *reg = data;
05489    reg->expire = -1;
05490    iax2_do_register(reg);
05491 }

static void __iax2_poke_noanswer ( void *  data  )  [static]

Definition at line 8477 of file chan_iax2.c.

References ast_device_state_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), iax2_peer::callno, EVENT_FLAG_SYSTEM, iax2_destroy(), iax2_poke_peer_s(), iaxsl, iax2_peer::lastms, LOG_NOTICE, manager_event(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, and sched.

Referenced by iax2_poke_noanswer().

08478 {
08479    struct iax2_peer *peer = data;
08480    if (peer->lastms > -1) {
08481       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08482       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08483       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08484    }
08485    if (peer->callno > 0) {
08486       ast_mutex_lock(&iaxsl[peer->callno]);
08487       iax2_destroy(peer->callno);
08488       ast_mutex_unlock(&iaxsl[peer->callno]);
08489    }
08490    peer->callno = 0;
08491    peer->lastms = -1;
08492    /* Try again quickly */
08493    peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer);
08494 }

static void __iax2_poke_peer_s ( void *  data  )  [static]

Definition at line 6186 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by iax2_poke_peer_s().

06187 {
06188    struct iax2_peer *peer = data;
06189    iax2_poke_peer(peer, 0);
06190 }

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

Definition at line 4275 of file chan_iax2.c.

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

Referenced by iax2_show_peers(), and manager_iax2_show_peers().

04276 {
04277    regex_t regexbuf;
04278    int havepattern = 0;
04279    int total_peers = 0;
04280    int online_peers = 0;
04281    int offline_peers = 0;
04282    int unmonitored_peers = 0;
04283    ao2_iterator i;
04284 
04285 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
04286 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
04287 
04288    struct iax2_peer *peer = NULL;
04289    char name[256];
04290    int registeredonly=0;
04291    char *term = manager ? "\r\n" : "\n";
04292 
04293    switch (argc) {
04294    case 6:
04295       if (!strcasecmp(argv[3], "registered"))
04296          registeredonly = 1;
04297       else
04298          return RESULT_SHOWUSAGE;
04299       if (!strcasecmp(argv[4], "like")) {
04300          if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
04301             return RESULT_SHOWUSAGE;
04302          havepattern = 1;
04303       } else
04304          return RESULT_SHOWUSAGE;
04305       break;
04306    case 5:
04307       if (!strcasecmp(argv[3], "like")) {
04308          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04309             return RESULT_SHOWUSAGE;
04310          havepattern = 1;
04311       } else
04312          return RESULT_SHOWUSAGE;
04313       break;
04314    case 4:
04315       if (!strcasecmp(argv[3], "registered"))
04316          registeredonly = 1;
04317       else
04318          return RESULT_SHOWUSAGE;
04319       break;
04320    case 3:
04321       break;
04322    default:
04323       return RESULT_SHOWUSAGE;
04324    }
04325 
04326 
04327    if (s)
04328       astman_append(s, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04329    else
04330       ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04331 
04332    i = ao2_iterator_init(peers, 0);
04333    for (peer = ao2_iterator_next(&i); peer; 
04334       peer_unref(peer), peer = ao2_iterator_next(&i)) {
04335       char nm[20];
04336       char status[20];
04337       char srch[2000];
04338       int retstatus;
04339 
04340       if (registeredonly && !peer->addr.sin_addr.s_addr)
04341          continue;
04342       if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0))
04343          continue;
04344 
04345       if (!ast_strlen_zero(peer->username))
04346          snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
04347       else
04348          ast_copy_string(name, peer->name, sizeof(name));
04349       
04350       retstatus = peer_status(peer, status, sizeof(status));
04351       if (retstatus > 0)
04352          online_peers++;
04353       else if (!retstatus)
04354          offline_peers++;
04355       else
04356          unmonitored_peers++;
04357       
04358       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
04359       
04360       snprintf(srch, sizeof(srch), FORMAT, name, 
04361           peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04362           ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04363           nm,
04364           ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04365           peer->encmethods ? "(E)" : "   ", status, term);
04366       
04367       if (s)
04368          astman_append(s, FORMAT, name, 
04369                   peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)",
04370                   ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04371                   nm,
04372                   ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04373                   peer->encmethods ? "(E)" : "   ", status, term);
04374       else
04375          ast_cli(fd, FORMAT, name, 
04376             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04377             ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04378             nm,
04379             ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04380             peer->encmethods ? "(E)" : "   ", status, term);
04381       total_peers++;
04382    }
04383 
04384    if (s)
04385       astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04386    else
04387       ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04388 
04389    if (havepattern)
04390       regfree(&regexbuf);
04391 
04392    return RESULT_SUCCESS;
04393 #undef FORMAT
04394 #undef FORMAT2
04395 }

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

Definition at line 938 of file chan_iax2.c.

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

00939 {
00940    struct iax2_thread *thread = NULL;
00941    static time_t lasterror;
00942    static time_t t;
00943 
00944    thread = find_idle_thread();
00945 
00946    if (thread != NULL) {
00947       thread->schedfunc = func;
00948       thread->scheddata = data;
00949       thread->iostate = IAX_IOSTATE_SCHEDREADY;
00950 #ifdef DEBUG_SCHED_MULTITHREAD
00951       ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc));
00952 #endif
00953       signal_condition(&thread->lock, &thread->cond);
00954       return 0;
00955    }
00956    time(&t);
00957    if (t != lasterror) 
00958       ast_log(LOG_NOTICE, "Out of idle IAX2 threads for scheduling!\n");
00959    lasterror = t;
00960 
00961    return -1;
00962 }

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

References f, and iax2_send().

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

04777 {
04778    struct ast_frame f = { 0, };
04779 
04780    f.frametype = type;
04781    f.subclass = command;
04782    f.datalen = datalen;
04783    f.src = __FUNCTION__;
04784    f.data = (void *) data;
04785 
04786    return iax2_send(i, &f, ts, seqno, now, transfer, final);
04787 }

static void __send_lagrq ( void *  data  )  [static]

Definition at line 1002 of file chan_iax2.c.

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

Referenced by send_lagrq().

01003 {
01004    int callno = (long)data;
01005    /* Ping only if it's real not if it's bridged */
01006    ast_mutex_lock(&iaxsl[callno]);
01007    if (iaxs[callno] && iaxs[callno]->lagid != -1) {
01008       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
01009       iaxs[callno]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
01010    }
01011    ast_mutex_unlock(&iaxsl[callno]);
01012 }

static void __send_ping ( void *  data  )  [static]

Definition at line 968 of file chan_iax2.c.

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

Referenced by send_ping().

00969 {
00970    int callno = (long)data;
00971    ast_mutex_lock(&iaxsl[callno]);
00972    if (iaxs[callno] && iaxs[callno]->pingid != -1) {
00973       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
00974       iaxs[callno]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, data);
00975    }
00976    ast_mutex_unlock(&iaxsl[callno]);
00977 }

static int __unload_module ( void   )  [static]

Definition at line 10570 of file chan_iax2.c.

References ao2_ref(), 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_MAX_CALLS, iax_provision_unload(), iaxactivethreadcount, iaxq, iaxs, iaxsl, ast_firmware_list::lock, netsock, outsock, peers, sched, sched_context_destroy(), thread, users, and waresl.

Referenced by load_module(), and unload_module().

10571 {
10572    struct iax2_thread *thread = NULL;
10573    int x;
10574 
10575    /* Make sure threads do not hold shared resources when they are canceled */
10576    
10577    /* Grab the sched lock resource to keep it away from threads about to die */
10578    /* Cancel the network thread, close the net socket */
10579    if (netthreadid != AST_PTHREADT_NULL) {
10580       AST_LIST_LOCK(&iaxq.queue);
10581       ast_mutex_lock(&sched_lock);
10582       pthread_cancel(netthreadid);
10583       ast_cond_signal(&sched_cond);
10584       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
10585       AST_LIST_UNLOCK(&iaxq.queue);
10586       pthread_join(netthreadid, NULL);
10587    }
10588    if (schedthreadid != AST_PTHREADT_NULL) {
10589       ast_mutex_lock(&sched_lock);  
10590       pthread_cancel(schedthreadid);
10591       ast_cond_signal(&sched_cond);
10592       ast_mutex_unlock(&sched_lock);   
10593       pthread_join(schedthreadid, NULL);
10594    }
10595    
10596    /* Call for all threads to halt */
10597    AST_LIST_LOCK(&idle_list);
10598    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
10599       AST_LIST_REMOVE_CURRENT(&idle_list, list);
10600       pthread_cancel(thread->threadid);
10601    }
10602    AST_LIST_TRAVERSE_SAFE_END
10603    AST_LIST_UNLOCK(&idle_list);
10604 
10605    AST_LIST_LOCK(&active_list);
10606    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
10607       AST_LIST_REMOVE_CURRENT(&active_list, list);
10608       pthread_cancel(thread->threadid);
10609    }
10610    AST_LIST_TRAVERSE_SAFE_END
10611    AST_LIST_UNLOCK(&active_list);
10612 
10613    AST_LIST_LOCK(&dynamic_list);
10614         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
10615       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
10616       pthread_cancel(thread->threadid);
10617         }
10618    AST_LIST_TRAVERSE_SAFE_END
10619         AST_LIST_UNLOCK(&dynamic_list);
10620 
10621    AST_LIST_HEAD_DESTROY(&iaxq.queue);
10622 
10623    /* Wait for threads to exit */
10624    while(0 < iaxactivethreadcount)
10625       usleep(10000);
10626    
10627    ast_netsock_release(netsock);
10628    ast_netsock_release(outsock);
10629    for (x=0;x<IAX_MAX_CALLS;x++)
10630       if (iaxs[x])
10631          iax2_destroy(x);
10632    ast_manager_unregister( "IAXpeers" );
10633    ast_manager_unregister( "IAXnetstats" );
10634    ast_unregister_application(papp);
10635    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10636    ast_unregister_switch(&iax2_switch);
10637    ast_channel_unregister(&iax2_tech);
10638    delete_users();
10639    iax_provision_unload();
10640    sched_context_destroy(sched);
10641 
10642    ast_mutex_destroy(&waresl.lock);
10643 
10644    for (x = 0; x < IAX_MAX_CALLS; x++)
10645       ast_mutex_destroy(&iaxsl[x]);
10646 
10647    ao2_ref(peers, -1);
10648    ao2_ref(users, -1);
10649 
10650    return 0;
10651 }

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

Definition at line 4828 of file chan_iax2.c.

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

Referenced by check_access().

04829 {
04830    while(con) {
04831       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
04832          return -1;
04833       con = con->next;
04834    }
04835    return 0;
04836 }

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

Definition at line 4603 of file chan_iax2.c.

References 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_MAX_CALLS, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), iax_rr::jitter, jb_info::jitter, iax_rr::losscnt, iax_rr::losspct, jb_info::losspct, jb_info::min, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::pingtime, chan_iax2_pvt::remote_rr, and s.

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

04604 {
04605    int x;
04606    int numchans = 0;
04607    for (x=0;x<IAX_MAX_CALLS;x++) {
04608       ast_mutex_lock(&iaxsl[x]);
04609       if (iaxs[x]) {
04610          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04611          char *fmt;
04612          jb_info jbinfo;
04613          
04614          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04615             jb_getinfo(iaxs[x]->jb, &jbinfo);
04616             localjitter = jbinfo.jitter;
04617             localdelay = jbinfo.current - jbinfo.min;
04618             locallost = jbinfo.frames_lost;
04619             locallosspct = jbinfo.losspct/1000;
04620             localdropped = jbinfo.frames_dropped;
04621             localooo = jbinfo.frames_ooo;
04622          } else {
04623             localjitter = -1;
04624             localdelay = 0;
04625             locallost = -1;
04626             locallosspct = -1;
04627             localdropped = 0;
04628             localooo = -1;
04629          }
04630          if (limit_fmt)
04631             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04632          else
04633             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04634          if (s)
04635             
04636             astman_append(s, fmt,
04637                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04638                      iaxs[x]->pingtime,
04639                      localjitter, 
04640                      localdelay,
04641                      locallost,
04642                      locallosspct,
04643                      localdropped,
04644                      localooo,
04645                      iaxs[x]->frames_received/1000,
04646                      iaxs[x]->remote_rr.jitter,
04647                      iaxs[x]->remote_rr.delay,
04648                      iaxs[x]->remote_rr.losscnt,
04649                      iaxs[x]->remote_rr.losspct,
04650                      iaxs[x]->remote_rr.dropped,
04651                      iaxs[x]->remote_rr.ooo,
04652                      iaxs[x]->remote_rr.packets/1000);
04653          else
04654             ast_cli(fd, fmt,
04655                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04656                iaxs[x]->pingtime,
04657                localjitter, 
04658                localdelay,
04659                locallost,
04660                locallosspct,
04661                localdropped,
04662                localooo,
04663                iaxs[x]->frames_received/1000,
04664                iaxs[x]->remote_rr.jitter,
04665                iaxs[x]->remote_rr.delay,
04666                iaxs[x]->remote_rr.losscnt,
04667                iaxs[x]->remote_rr.losspct,
04668                iaxs[x]->remote_rr.dropped,
04669                iaxs[x]->remote_rr.ooo,
04670                iaxs[x]->remote_rr.packets/1000
04671                );
04672          numchans++;
04673       }
04674       ast_mutex_unlock(&iaxsl[x]);
04675    }
04676    return numchans;
04677 }

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

Create new call, interface with the PBX core.

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

03514 {
03515    struct ast_channel *tmp;
03516    struct chan_iax2_pvt *i;
03517    struct ast_variable *v = NULL;
03518 
03519    if (!(i = iaxs[callno])) {
03520       ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
03521       return NULL;
03522    }
03523 
03524    /* Don't hold call lock */
03525    ast_mutex_unlock(&iaxsl[callno]);
03526    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);
03527    ast_mutex_lock(&iaxsl[callno]);
03528    if (!tmp)
03529       return NULL;
03530    tmp->tech = &iax2_tech;
03531    /* We can support any format by default, until we get restricted */
03532    tmp->nativeformats = capability;
03533    tmp->readformat = ast_best_codec(capability);
03534    tmp->writeformat = ast_best_codec(capability);
03535    tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
03536 
03537    /* Don't use ast_set_callerid() here because it will
03538     * generate a NewCallerID event before the NewChannel event */
03539    if (!ast_strlen_zero(i->ani))
03540       tmp->cid.cid_ani = ast_strdup(i->ani);
03541    else
03542       tmp->cid.cid_ani = ast_strdup(i->cid_num);
03543    tmp->cid.cid_dnid = ast_strdup(i->dnid);
03544    tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
03545    tmp->cid.cid_pres = i->calling_pres;
03546    tmp->cid.cid_ton = i->calling_ton;
03547    tmp->cid.cid_tns = i->calling_tns;
03548    if (!ast_strlen_zero(i->language))
03549       ast_string_field_set(tmp, language, i->language);
03550    if (!ast_strlen_zero(i->accountcode))
03551       ast_string_field_set(tmp, accountcode, i->accountcode);
03552    if (i->amaflags)
03553       tmp->amaflags = i->amaflags;
03554    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
03555    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
03556    if (i->adsi)
03557       tmp->adsicpe = i->peeradsicpe;
03558    else
03559       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
03560    i->owner = tmp;
03561    i->capability = capability;
03562 
03563    for (v = i->vars ; v ; v = v->next)
03564       pbx_builtin_setvar_helper(tmp, v->name, v->value);
03565 
03566    if (state != AST_STATE_DOWN) {
03567       if (ast_pbx_start(tmp)) {
03568          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
03569          ast_hangup(tmp);
03570          i->owner = NULL;
03571          return NULL;
03572       }
03573    }
03574 
03575    ast_module_ref(ast_module_info->self);
03576    
03577    return tmp;
03578 }

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 ( void *  data  )  [static]

Definition at line 2113 of file chan_iax2.c.

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02114 {
02115 #ifdef SCHED_MULTITHREADED
02116    if (schedule_action(__attempt_transmit, data))
02117 #endif      
02118       __attempt_transmit(data);
02119    return 0;
02120 }

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

Definition at line 6106 of file chan_iax2.c.

References ast_sched_add(), ast_sched_del(), auth_reject(), chan_iax2_pvt::authfail, chan_iax2_pvt::authid, iaxs, and sched.

Referenced by socket_process().

06107 {
06108    /* Schedule sending the authentication failure in one second, to prevent
06109       guessing */
06110    if (iaxs[callno]) {
06111       iaxs[callno]->authfail = failcode;
06112       if (delayreject) {
06113          if (iaxs[callno]->authid > -1)
06114             ast_sched_del(sched, iaxs[callno]->authid);
06115          iaxs[callno]->authid = ast_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06116       } else
06117          auth_reject((void *)(long)callno);
06118    }
06119    return 0;
06120 }

static int auth_reject ( void *  data  )  [static]

Definition at line 6092 of file chan_iax2.c.

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

Referenced by auth_fail().

06093 {
06094    int callno = (int)(long)(data);
06095    ast_mutex_lock(&iaxsl[callno]);
06096    if (iaxs[callno])
06097       iaxs[callno]->authid = -1;
06098    ast_mutex_unlock(&iaxsl[callno]);
06099 #ifdef SCHED_MULTITHREADED
06100    if (schedule_action(__auth_reject, data))
06101 #endif      
06102       __auth_reject(data);
06103    return 0;
06104 }

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

Definition at line 5355 of file chan_iax2.c.

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

05356 {
05357    int res = -1;
05358    int x;
05359    if (!ast_strlen_zero(keyn)) {
05360       if (!(authmethods & IAX_AUTH_RSA)) {
05361          if (ast_strlen_zero(secret)) 
05362             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));
05363       } else if (ast_strlen_zero(challenge)) {
05364          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
05365       } else {
05366          char sig[256];
05367          struct ast_key *key;
05368          key = ast_key_get(keyn, AST_KEY_PRIVATE);
05369          if (!key) {
05370             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
05371          } else {
05372             if (ast_sign(key, (char*)challenge, sig)) {
05373                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
05374                res = -1;
05375             } else {
05376                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
05377                res = 0;
05378             }
05379          }
05380       }
05381    } 
05382    /* Fall back */
05383    if (res && !ast_strlen_zero(secret)) {
05384       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
05385          struct MD5Context md5;
05386          unsigned char digest[16];
05387          char digres[128];
05388          MD5Init(&md5);
05389          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
05390          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
05391          MD5Final(digest, &md5);
05392          /* If they support md5, authenticate with it.  */
05393          for (x=0;x<16;x++)
05394             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
05395          if (ecx && dcx)
05396             build_enc_keys(digest, ecx, dcx);
05397          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
05398          res = 0;
05399       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
05400          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
05401          res = 0;
05402       } else
05403          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
05404    }
05405    return res;
05406 }

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

References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), authenticate(), iax2_peer::authmethods, chan_iax2_pvt::callno, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, iaxs, iaxsl, ies, iax2_peer::mask, merge_encryption(), peer_unref(), peers, realtime_peer(), and send_command().

Referenced by socket_process().

05413 {
05414    struct iax2_peer *peer = NULL;
05415    /* Start pessimistic */
05416    int res = -1;
05417    int authmethods = 0;
05418    struct iax_ie_data ied;
05419    uint16_t callno = p->callno;
05420 
05421    memset(&ied, 0, sizeof(ied));
05422    
05423    if (ies->username)
05424       ast_string_field_set(p, username, ies->username);
05425    if (ies->challenge)
05426       ast_string_field_set(p, challenge, ies->challenge);
05427    if (ies->authmethods)
05428       authmethods = ies->authmethods;
05429    if (authmethods & IAX_AUTH_MD5)
05430       merge_encryption(p, ies->encmethods);
05431    else
05432       p->encmethods = 0;
05433 
05434    /* Check for override RSA authentication first */
05435    if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) {
05436       /* Normal password authentication */
05437       res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05438    } else {
05439       ao2_iterator i = ao2_iterator_init(peers, 0);
05440       while ((peer = ao2_iterator_next(&i))) {
05441          if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
05442              /* No peer specified at our end, or this is the peer */
05443              && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
05444              /* No username specified in peer rule, or this is the right username */
05445              && (!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)))
05446              /* No specified host, or this is our host */
05447             ) {
05448             res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05449             if (!res) {
05450                peer_unref(peer);
05451                break;
05452             }
05453          }
05454          peer_unref(peer);
05455       }
05456       if (!peer) {
05457          /* We checked our list and didn't find one.  It's unlikely, but possible, 
05458             that we're trying to authenticate *to* a realtime peer */
05459          const char *peer_name = ast_strdupa(p->peer);
05460          ast_mutex_unlock(&iaxsl[callno]);
05461          if ((peer = realtime_peer(peer_name, NULL))) {
05462             ast_mutex_lock(&iaxsl[callno]);
05463             if (!(p = iaxs[callno])) {
05464                peer_unref(peer);
05465                return -1;
05466             }
05467             res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05468             peer_unref(peer);
05469          }
05470          if (!peer) {
05471             ast_mutex_lock(&iaxsl[callno]);
05472             if (!(p = iaxs[callno]))
05473                return -1;
05474          }
05475       }
05476    }
05477    if (ies->encmethods)
05478       ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
05479    if (!res)
05480       res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);
05481    return res;
05482 }

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

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

Referenced by socket_process().

05091 {
05092    struct iax_ie_data ied;
05093    int res = -1, authreq_restrict = 0;
05094    char challenge[10];
05095    struct chan_iax2_pvt *p = iaxs[call_num];
05096 
05097    memset(&ied, 0, sizeof(ied));
05098 
05099    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
05100    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05101       struct iax2_user *user, tmp_user = {
05102          .name = p->username, 
05103       };
05104 
05105       user = ao2_find(users, &tmp_user, OBJ_POINTER);
05106       if (user) {
05107          if (user->curauthreq == user->maxauthreq)
05108             authreq_restrict = 1;
05109          else
05110             user->curauthreq++;
05111          user = user_unref(user);
05112       }
05113    }
05114 
05115    /* If the AUTHREQ limit test failed, send back an error */
05116    if (authreq_restrict) {
05117       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
05118       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
05119       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
05120       return 0;
05121    }
05122 
05123    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
05124    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
05125       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
05126       ast_string_field_set(p, challenge, challenge);
05127       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
05128       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
05129    }
05130    if (p->encmethods)
05131       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
05132 
05133    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
05134 
05135    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
05136 
05137    if (p->encmethods)
05138       ast_set_flag(p, IAX_ENCRYPTED);
05139 
05140    return res;
05141 }

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

Definition at line 5143 of file chan_iax2.c.

References ao2_find(), ast_check_signature, ast_clear_flag, ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, chan_iax2_pvt::authmethods, iax2_user::curauthreq, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_MAXAUTHREQ, IAX_STATE_AUTHENTICATED, ies, key(), LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), secret, chan_iax2_pvt::state, strsep(), user_unref(), and users.

Referenced by socket_process().

05144 {
05145    char requeststr[256];
05146    char md5secret[256] = "";
05147    char secret[256] = "";
05148    char rsasecret[256] = "";
05149    int res = -1; 
05150    int x;
05151    struct iax2_user *user, tmp_user = {
05152       .name = p->username, 
05153    };
05154 
05155    user = ao2_find(users, &tmp_user, OBJ_POINTER);
05156    if (user) {
05157       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05158          ast_atomic_fetchadd_int(&user->curauthreq, -1);
05159          ast_clear_flag(p, IAX_MAXAUTHREQ);
05160       }
05161       ast_string_field_set(p, host, user->name);
05162       user = user_unref(user);
05163    }
05164 
05165    if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
05166       return res;
05167    if (ies->password)
05168       ast_copy_string(secret, ies->password, sizeof(secret));
05169    if (ies->md5_result)
05170       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05171    if (ies->rsa_result)
05172       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05173    if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) {
05174       struct ast_key *key;
05175       char *keyn;
05176       char tmpkey[256];
05177       char *stringp=NULL;
05178       ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey));
05179       stringp=tmpkey;
05180       keyn = strsep(&stringp, ":");
05181       while(keyn) {
05182          key = ast_key_get(keyn, AST_KEY_PUBLIC);
05183          if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
05184             res = 0;
05185             break;
05186          } else if (!key)
05187             ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
05188          keyn = strsep(&stringp, ":");
05189       }
05190    } else if (p->authmethods & IAX_AUTH_MD5) {
05191       struct MD5Context md5;
05192       unsigned char digest[16];
05193       char *tmppw, *stringp;
05194       
05195       tmppw = ast_strdupa(p->secret);
05196       stringp = tmppw;
05197       while((tmppw = strsep(&stringp, ";"))) {
05198          MD5Init(&md5);
05199          MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge));
05200          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05201          MD5Final(digest, &md5);
05202          /* If they support md5, authenticate with it.  */
05203          for (x=0;x<16;x++)
05204             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05205          if (!strcasecmp(requeststr, md5secret)) {
05206             res = 0;
05207             break;
05208          }
05209       }
05210    } else if (p->authmethods & IAX_AUTH_PLAINTEXT) {
05211       if (!strcmp(secret, p->secret))
05212          res = 0;
05213    }
05214    return res;
05215 }

static int auto_congest ( void *  data  )  [static]

Definition at line 2934 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

02935 {
02936 #ifdef SCHED_MULTITHREADED
02937    if (schedule_action(__auto_congest, data))
02938 #endif      
02939       __auto_congest(data);
02940    return 0;
02941 }

static int auto_hangup ( void *  data  )  [static]

Definition at line 6137 of file chan_iax2.c.

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

Referenced by iax2_dprequest(), and iax2_provision().

06138 {
06139    int callno = (int)(long)(data);
06140    ast_mutex_lock(&iaxsl[callno]);
06141    if (iaxs[callno]) {
06142       iaxs[callno]->autoid = -1;
06143    }
06144    ast_mutex_unlock(&iaxsl[callno]);
06145 #ifdef SCHED_MULTITHREADED
06146    if (schedule_action(__auto_hangup, data))
06147 #endif      
06148       __auto_hangup(data);
06149    return 0;
06150 }

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

Definition at line 8783 of file chan_iax2.c.

References ast_calloc.

Referenced by build_user().

08784 {
08785    struct iax2_context *con;
08786 
08787    if ((con = ast_calloc(1, sizeof(*con))))
08788       ast_copy_string(con->context, context, sizeof(con->context));
08789    
08790    return con;
08791 }

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

Definition at line 3872 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

03873 {
03874    aes_encrypt_key128(digest, ecx);
03875    aes_decrypt_key128(digest, dcx);
03876 }

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

Create peer structure based on configuration.

Definition at line 8932 of file chan_iax2.c.

References ao2_alloc(), ao2_find(), ao2_unlink(), 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_free_pools, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), cid_name, cid_num, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, get_auth_methods(), get_encrypt_methods(), globalflags, iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, ast_variable::name, ast_variable::next, peer_destructor(), peer_set_srcaddr(), peer_unref(), peers, prefs, sched, secret, and ast_variable::value.

08933 {
08934    struct iax2_peer *peer = NULL;
08935    struct ast_ha *oldha = NULL;
08936    int maskfound=0;
08937    int found=0;
08938    int firstpass=1;
08939    struct iax2_peer tmp_peer = {
08940       .name = name,
08941    };
08942 
08943    if (!temponly) {
08944       peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
08945       if (peer && !ast_test_flag(peer, IAX_DELME))
08946          firstpass = 0;
08947    }
08948 
08949    if (peer) {
08950       found++;
08951       if (firstpass) {
08952          oldha = peer->ha;
08953          peer->ha = NULL;
08954       }
08955       ao2_unlink(peers, peer);
08956    } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) {
08957       peer->expire = -1;
08958       peer->pokeexpire = -1;
08959       peer->sockfd = defaultsockfd;
08960       if (ast_string_field_init(peer, 32))
08961          peer = peer_unref(peer);
08962    }
08963 
08964    if (peer) {
08965       if (firstpass) {
08966          ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08967          peer->encmethods = iax2_encryption;
08968          peer->adsi = adsi;
08969          ast_string_field_set(peer,secret,"");
08970          if (!found) {
08971             ast_string_field_set(peer, name, name);
08972             peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
08973             peer->expiry = min_reg_expire;
08974          }
08975          peer->prefs = prefs;
08976          peer->capability = iax2_capability;
08977          peer->smoothing = 0;
08978          peer->pokefreqok = DEFAULT_FREQ_OK;
08979          peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
08980          ast_string_field_set(peer,context,"");
08981          ast_string_field_set(peer,peercontext,"");
08982          ast_clear_flag(peer, IAX_HASCALLERID);
08983          ast_string_field_set(peer, cid_name, "");
08984          ast_string_field_set(peer, cid_num, "");
08985       }
08986 
08987       if (!v) {
08988          v = alt;
08989          alt = NULL;
08990       }
08991       while(v) {
08992          if (!strcasecmp(v->name, "secret")) {
08993             ast_string_field_set(peer, secret, v->value);
08994          } else if (!strcasecmp(v->name, "mailbox")) {
08995             ast_string_field_set(peer, mailbox, v->value);
08996          } else if (!strcasecmp(v->name, "mohinterpret")) {
08997             ast_string_field_set(peer, mohinterpret, v->value);
08998          } else if (!strcasecmp(v->name, "mohsuggest")) {
08999             ast_string_field_set(peer, mohsuggest, v->value);
09000          } else if (!strcasecmp(v->name, "dbsecret")) {
09001             ast_string_field_set(peer, dbsecret, v->value);
09002          } else if (!strcasecmp(v->name, "trunk")) {
09003             ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK);   
09004             if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) {
09005                ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without zaptel timing\n", peer->name);
09006                ast_clear_flag(peer, IAX_TRUNK);
09007             }
09008          } else if (!strcasecmp(v->name, "auth")) {
09009             peer->authmethods = get_auth_methods(v->value);
09010          } else if (!strcasecmp(v->name, "encryption")) {
09011             peer->encmethods = get_encrypt_methods(v->value);
09012          } else if (!strcasecmp(v->name, "notransfer")) {
09013             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09014             ast_clear_flag(peer, IAX_TRANSFERMEDIA);  
09015             ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 
09016          } else if (!strcasecmp(v->name, "transfer")) {
09017             if (!strcasecmp(v->value, "mediaonly")) {
09018                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
09019             } else if (ast_true(v->value)) {
09020                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09021             } else 
09022                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09023          } else if (!strcasecmp(v->name, "jitterbuffer")) {
09024             ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF);  
09025          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
09026             ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF);   
09027          } else if (!strcasecmp(v->name, "host")) {
09028             if (!strcasecmp(v->value, "dynamic")) {
09029                /* They'll register with us */
09030                ast_set_flag(peer, IAX_DYNAMIC); 
09031                if (!found) {
09032                   /* Initialize stuff iff we're not found, otherwise
09033                      we keep going with what we had */
09034                   memset(&peer->addr.sin_addr, 0, 4);
09035                   if (peer->addr.sin_port) {
09036                      /* If we've already got a port, make it the default rather than absolute */
09037                      peer->defaddr.sin_port = peer->addr.sin_port;
09038                      peer->addr.sin_port = 0;
09039                   }
09040                }
09041             } else {
09042                /* Non-dynamic.  Make sure we become that way if we're not */
09043                if (peer->expire > -1)
09044                   ast_sched_del(sched, peer->expire);
09045                peer->expire = -1;
09046                ast_clear_flag(peer, IAX_DYNAMIC);
09047                if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr)) {
09048                   ast_string_field_free_pools(peer);
09049                   return peer_unref(peer);
09050                }
09051                if (!peer->addr.sin_port)
09052                   peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
09053             }
09054             if (!maskfound)
09055                inet_aton("255.255.255.255", &peer->mask);
09056          } else if (!strcasecmp(v->name, "defaultip")) {
09057             if (ast_get_ip(&peer->defaddr, v->value)) {
09058                ast_string_field_free_pools(peer);
09059                return peer_unref(peer);
09060             }
09061          } else if (!strcasecmp(v->name, "sourceaddress")) {
09062             peer_set_srcaddr(peer, v->value);
09063          } else if (!strcasecmp(v->name, "permit") ||
09064                   !strcasecmp(v->name, "deny")) {
09065             peer->ha = ast_append_ha(v->name, v->value, peer->ha);
09066          } else if (!strcasecmp(v->name, "mask")) {
09067             maskfound++;
09068             inet_aton(v->value, &peer->mask);
09069          } else if (!strcasecmp(v->name, "context")) {
09070             ast_string_field_set(peer, context, v->value);
09071          } else if (!strcasecmp(v->name, "regexten")) {
09072             ast_string_field_set(peer, regexten, v->value);
09073          } else if (!strcasecmp(v->name, "peercontext")) {
09074             ast_string_field_set(peer, peercontext, v->value);
09075          } else if (!strcasecmp(v->name, "port")) {
09076             if (ast_test_flag(peer, IAX_DYNAMIC))
09077                peer->defaddr.sin_port = htons(atoi(v->value));
09078             else
09079                peer->addr.sin_port = htons(atoi(v->value));
09080          } else if (!strcasecmp(v->name, "username")) {
09081             ast_string_field_set(peer, username, v->value);
09082          } else if (!strcasecmp(v->name, "allow")) {
09083             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1);
09084          } else if (!strcasecmp(v->name, "disallow")) {
09085             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0);
09086          } else if (!strcasecmp(v->name, "callerid")) {
09087             if (!ast_strlen_zero(v->value)) {
09088                char name2[80];
09089                char num2[80];
09090                ast_callerid_split(v->value, name2, 80, num2, 80);
09091                ast_string_field_set(peer, cid_name, name2);
09092                ast_string_field_set(peer, cid_num, num2);
09093                ast_set_flag(peer, IAX_HASCALLERID);
09094             } else {
09095                ast_clear_flag(peer, IAX_HASCALLERID);
09096                ast_string_field_set(peer, cid_name, "");
09097                ast_string_field_set(peer, cid_num, "");
09098             }
09099          } else if (!strcasecmp(v->name, "fullname")) {
09100             if (!ast_strlen_zero(v->value)) {
09101                ast_string_field_set(peer, cid_name, v->value);
09102                ast_set_flag(peer, IAX_HASCALLERID);
09103             } else {
09104                ast_string_field_set(peer, cid_name, "");
09105                if (ast_strlen_zero(peer->cid_num))
09106                   ast_clear_flag(peer, IAX_HASCALLERID);
09107             }
09108          } else if (!strcasecmp(v->name, "cid_number")) {
09109             if (!ast_strlen_zero(v->value)) {
09110                ast_string_field_set(peer, cid_num, v->value);
09111                ast_set_flag(peer, IAX_HASCALLERID);
09112             } else {
09113                ast_string_field_set(peer, cid_num, "");
09114                if (ast_strlen_zero(peer->cid_name))
09115                   ast_clear_flag(peer, IAX_HASCALLERID);
09116             }
09117          } else if (!strcasecmp(v->name, "sendani")) {
09118             ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 
09119          } else if (!strcasecmp(v->name, "inkeys")) {
09120             ast_string_field_set(peer, inkeys, v->value);
09121          } else if (!strcasecmp(v->name, "outkey")) {
09122             ast_string_field_set(peer, outkey, v->value);
09123          } else if (!strcasecmp(v->name, "qualify")) {
09124             if (!strcasecmp(v->value, "no")) {
09125                peer->maxms = 0;
09126             } else if (!strcasecmp(v->value, "yes")) {
09127                peer->maxms = DEFAULT_MAXMS;
09128             } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
09129                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);
09130                peer->maxms = 0;
09131             }
09132          } else if (!strcasecmp(v->name, "qualifysmoothing")) {
09133             peer->smoothing = ast_true(v->value);
09134          } else if (!strcasecmp(v->name, "qualifyfreqok")) {
09135             if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) {
09136                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);
09137             }
09138          } else if (!strcasecmp(v->name, "qualifyfreqnotok")) {
09139             if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) {
09140                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);
09141             } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok);
09142          } else if (!strcasecmp(v->name, "timezone")) {
09143             ast_string_field_set(peer, zonetag, v->value);
09144          } else if (!strcasecmp(v->name, "adsi")) {
09145             peer->adsi = ast_true(v->value);
09146          }/* else if (strcasecmp(v->name,"type")) */
09147          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09148          v = v->next;
09149          if (!v) {
09150             v = alt;
09151             alt = NULL;
09152          }
09153       }
09154       if (!peer->authmethods)
09155          peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09156       ast_clear_flag(peer, IAX_DELME); 
09157       /* Make sure these are IPv4 addresses */
09158       peer->addr.sin_family = AF_INET;
09159    }
09160    if (oldha)
09161       ast_free_ha(oldha);
09162    return peer;
09163 }

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

Create in-memory user structure from configuration.

Definition at line 9179 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_pools, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_new(), iax2_user::authmethods, build_context(), iax2_user::capability, cid_name, cid_num, cleanup(), iax2_user::contexts, iax2_user::curauthreq, iax2_user::encmethods, format, free_context(), get_auth_methods(), get_encrypt_methods(), globalflags, iax2_user::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, iax2_user::prefs, prefs, secret, user_destructor(), user_unref(), users, ast_variable::value, and iax2_user::vars.

09180 {
09181    struct iax2_user *user = NULL;
09182    struct iax2_context *con, *conl = NULL;
09183    struct ast_ha *oldha = NULL;
09184    struct iax2_context *oldcon = NULL;
09185    int format;
09186    int firstpass=1;
09187    int oldcurauthreq = 0;
09188    char *varname = NULL, *varval = NULL;
09189    struct ast_variable *tmpvar = NULL;
09190    struct iax2_user tmp_user = {
09191       .name = name,
09192    };
09193 
09194    if (!temponly) {
09195       user = ao2_find(users, &tmp_user, OBJ_POINTER);
09196       if (user && !ast_test_flag(user, IAX_DELME))
09197          firstpass = 0;
09198    }
09199 
09200    if (user) {
09201       if (firstpass) {
09202          oldcurauthreq = user->curauthreq;
09203          oldha = user->ha;
09204          oldcon = user->contexts;
09205          user->ha = NULL;
09206          user->contexts = NULL;
09207       }
09208       /* Already in the list, remove it and it will be added back (or FREE'd) */
09209       ao2_unlink(users, user);
09210    } else {
09211       user = ao2_alloc(sizeof(*user), user_destructor);
09212    }
09213    
09214    if (user) {
09215       if (firstpass) {
09216          ast_string_field_free_pools(user);
09217          memset(user, 0, sizeof(struct iax2_user));
09218          if (ast_string_field_init(user, 32)) {
09219             user = user_unref(user);
09220             goto cleanup;
09221          }
09222          user->maxauthreq = maxauthreq;
09223          user->curauthreq = oldcurauthreq;
09224          user->prefs = prefs;
09225          user->capability = iax2_capability;
09226          user->encmethods = iax2_encryption;
09227          user->adsi = adsi;
09228          ast_string_field_set(user, name, name);
09229          ast_string_field_set(user, language, language);
09230          ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP);   
09231          ast_clear_flag(user, IAX_HASCALLERID);
09232          ast_string_field_set(user, cid_name, "");
09233          ast_string_field_set(user, cid_num, "");
09234       }
09235       if (!v) {
09236          v = alt;
09237          alt = NULL;
09238       }
09239       while(v) {
09240          if (!strcasecmp(v->name, "context")) {
09241             con = build_context(v->value);
09242             if (con) {
09243                if (conl)
09244                   conl->next = con;
09245                else
09246                   user->contexts = con;
09247                conl = con;
09248             }
09249          } else if (!strcasecmp(v->name, "permit") ||
09250                   !strcasecmp(v->name, "deny")) {
09251             user->ha = ast_append_ha(v->name, v->value, user->ha);
09252          } else if (!strcasecmp(v->name, "setvar")) {
09253             varname = ast_strdupa(v->value);
09254             if (varname && (varval = strchr(varname,'='))) {
09255                *varval = '\0';
09256                varval++;
09257                if((tmpvar = ast_variable_new(varname, varval))) {
09258                   tmpvar->next = user->vars; 
09259                   user->vars = tmpvar;
09260                }
09261             }
09262          } else if (!strcasecmp(v->name, "allow")) {
09263             ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
09264          } else if (!strcasecmp(v->name, "disallow")) {
09265             ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0);
09266          } else if (!strcasecmp(v->name, "trunk")) {
09267             ast_set2_flag(user, ast_true(v->value), IAX_TRUNK);   
09268             if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) {
09269                ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without zaptel timing\n", user->name);
09270                ast_clear_flag(user, IAX_TRUNK);
09271             }
09272          } else if (!strcasecmp(v->name, "auth")) {
09273             user->authmethods = get_auth_methods(v->value);
09274          } else if (!strcasecmp(v->name, "encryption")) {
09275             user->encmethods = get_encrypt_methods(v->value);
09276          } else if (!strcasecmp(v->name, "notransfer")) {
09277             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09278             ast_clear_flag(user, IAX_TRANSFERMEDIA);  
09279             ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 
09280          } else if (!strcasecmp(v->name, "transfer")) {
09281             if (!strcasecmp(v->value, "mediaonly")) {
09282                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
09283             } else if (ast_true(v->value)) {
09284                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09285             } else 
09286                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09287          } else if (!strcasecmp(v->name, "codecpriority")) {
09288             if(!strcasecmp(v->value, "caller"))
09289                ast_set_flag(user, IAX_CODEC_USER_FIRST);
09290             else if(!strcasecmp(v->value, "disabled"))
09291                ast_set_flag(user, IAX_CODEC_NOPREFS);
09292             else if(!strcasecmp(v->value, "reqonly")) {
09293                ast_set_flag(user, IAX_CODEC_NOCAP);
09294                ast_set_flag(user, IAX_CODEC_NOPREFS);
09295             }
09296          } else if (!strcasecmp(v->name, "jitterbuffer")) {
09297             ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF);
09298          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
09299             ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF);
09300          } else if (!strcasecmp(v->name, "dbsecret")) {
09301             ast_string_field_set(user, dbsecret, v->value);
09302          } else if (!strcasecmp(v->name, "secret")) {
09303             if (!ast_strlen_zero(user->secret)) {
09304                char *old = ast_strdupa(user->secret);
09305 
09306                ast_string_field_build(user, secret, "%s;%s", old, v->value);
09307             } else
09308                ast_string_field_set(user, secret, v->value);
09309          } else if (!strcasecmp(v->name, "callerid")) {
09310             if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) {
09311                char name2[80];
09312                char num2[80];
09313                ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
09314                ast_string_field_set(user, cid_name, name2);
09315                ast_string_field_set(user, cid_num, num2);
09316                ast_set_flag(user, IAX_HASCALLERID);
09317             } else {
09318                ast_clear_flag(user, IAX_HASCALLERID);
09319                ast_string_field_set(user, cid_name, "");
09320                ast_string_field_set(user, cid_num, "");
09321             }
09322          } else if (!strcasecmp(v->name, "fullname")) {
09323             if (!ast_strlen_zero(v->value)) {
09324                ast_string_field_set(user, cid_name, v->value);
09325                ast_set_flag(user, IAX_HASCALLERID);
09326             } else {
09327                ast_string_field_set(user, cid_name, "");
09328                if (ast_strlen_zero(user->cid_num))
09329                   ast_clear_flag(user, IAX_HASCALLERID);
09330             }
09331          } else if (!strcasecmp(v->name, "cid_number")) {
09332             if (!ast_strlen_zero(v->value)) {
09333                ast_string_field_set(user, cid_num, v->value);
09334                ast_set_flag(user, IAX_HASCALLERID);
09335             } else {
09336                ast_string_field_set(user, cid_num, "");
09337                if (ast_strlen_zero(user->cid_name))
09338                   ast_clear_flag(user, IAX_HASCALLERID);
09339             }
09340          } else if (!strcasecmp(v->name, "accountcode")) {
09341             ast_string_field_set(user, accountcode, v->value);
09342          } else if (!strcasecmp(v->name, "mohinterpret")) {
09343             ast_string_field_set(user, mohinterpret, v->value);
09344          } else if (!strcasecmp(v->name, "mohsuggest")) {
09345             ast_string_field_set(user, mohsuggest, v->value);
09346          } else if (!strcasecmp(v->name, "language")) {
09347             ast_string_field_set(user, language, v->value);
09348          } else if (!strcasecmp(v->name, "amaflags")) {
09349             format = ast_cdr_amaflags2int(v->value);
09350             if (format < 0) {
09351                ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
09352             } else {
09353                user->amaflags = format;
09354             }
09355          } else if (!strcasecmp(v->name, "inkeys")) {
09356             ast_string_field_set(user, inkeys, v->value);
09357          } else if (!strcasecmp(v->name, "maxauthreq")) {
09358             user->maxauthreq = atoi(v->value);
09359             if (user->maxauthreq < 0)
09360                user->maxauthreq = 0;
09361          } else if (!strcasecmp(v->name, "adsi")) {
09362             user->adsi = ast_true(v->value);
09363          }/* else if (strcasecmp(v->name,"type")) */
09364          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09365          v = v->next;
09366          if (!v) {
09367             v = alt;
09368             alt = NULL;
09369          }
09370       }
09371       if (!user->authmethods) {
09372          if (!ast_strlen_zero(user->secret)) {
09373             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09374             if (!ast_strlen_zero(user->inkeys))
09375                user->authmethods |= IAX_AUTH_RSA;
09376          } else if (!ast_strlen_zero(user->inkeys)) {
09377             user->authmethods = IAX_AUTH_RSA;
09378          } else {
09379             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09380          }
09381       }
09382       ast_clear_flag(user, IAX_DELME);
09383    }
09384 cleanup:
09385    if (oldha)
09386       ast_free_ha(oldha);
09387    if (oldcon)
09388       free_context(oldcon);
09389    return user;
09390 }

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

Definition at line 9875 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, chan_iax2_pvt::capability, create_addr(), find_callno(), 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_MAX_CALLS, IAX_PROTO_VERSION, iaxs, iaxsl, LOG_WARNING, NEW_FORCE, parse_dial_string(), secret, and send_command().

Referenced by find_cache().

09876 {
09877    struct sockaddr_in sin;
09878    int x;
09879    int callno;
09880    struct iax_ie_data ied;
09881    struct create_addr_info cai;
09882    struct parsed_dial_string pds;
09883    char *tmpstr;
09884 
09885    for (x=0; x<IAX_MAX_CALLS; x++) {
09886       /* Look for an *exact match* call.  Once a call is negotiated, it can only
09887          look up entries for a single context */
09888       if (!ast_mutex_trylock(&iaxsl[x])) {
09889          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
09890             return x;
09891          ast_mutex_unlock(&iaxsl[x]);
09892       }
09893    }
09894 
09895    /* No match found, we need to create a new one */
09896 
09897    memset(&cai, 0, sizeof(cai));
09898    memset(&ied, 0, sizeof(ied));
09899    memset(&pds, 0, sizeof(pds));
09900 
09901    tmpstr = ast_strdupa(data);
09902    parse_dial_string(tmpstr, &pds);
09903 
09904    /* Populate our address from the given */
09905    if (create_addr(pds.peer, &sin, &cai))
09906       return -1;
09907 
09908    ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
09909       pds.peer, pds.username, pds.password, pds.context);
09910 
09911    callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
09912    if (callno < 1) {
09913       ast_log(LOG_WARNING, "Unable to create call\n");
09914       return -1;
09915    }
09916 
09917    ast_mutex_lock(&iaxsl[callno]);
09918    ast_string_field_set(iaxs[callno], dproot, data);
09919    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
09920 
09921    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
09922    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
09923    /* the string format is slightly different from a standard dial string,
09924       because the context appears in the 'exten' position
09925    */
09926    if (pds.exten)
09927       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
09928    if (pds.username)
09929       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
09930    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
09931    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
09932    /* Keep password handy */
09933    if (pds.password)
09934       ast_string_field_set(iaxs[callno], secret, pds.password);
09935    if (pds.key)
09936       ast_string_field_set(iaxs[callno], outkey, pds.key);
09937    /* Start the call going */
09938    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
09939 
09940    return callno;
09941 }

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

Definition at line 3742 of file chan_iax2.c.

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

03743 {
03744    /* Returns where in "receive time" we are.  That is, how many ms
03745       since we received (or would have received) the frame with timestamp 0 */
03746    int ms;
03747 #ifdef IAXTESTS
03748    int jit;
03749 #endif /* IAXTESTS */
03750    /* Setup rxcore if necessary */
03751    if (ast_tvzero(p->rxcore)) {
03752       p->rxcore = ast_tvnow();
03753       if (option_debug && iaxdebug)
03754          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
03755                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
03756       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
03757 #if 1
03758       if (option_debug && iaxdebug)
03759          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
03760                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
03761 #endif
03762    }
03763 
03764    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
03765 #ifdef IAXTESTS
03766    if (test_jit) {
03767       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
03768          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
03769          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
03770             jit = -jit;
03771          ms += jit;
03772       }
03773    }
03774    if (test_late) {
03775       ms += test_late;
03776       test_late = 0;
03777    }
03778 #endif /* IAXTESTS */
03779    return ms;
03780 }

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

Definition at line 3624 of file chan_iax2.c.

References AST_FRAME_CNG, AST_FRAME_IAX, AST_FRAME_VOICE, ast_log(), ast_tvadd(), ast_tvsub(), chan_iax2_pvt::callno, f, iaxs, chan_iax2_pvt::lastsent, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, chan_iax2_pvt::offset, option_debug, and chan_iax2_pvt::peercallno.

Referenced by iax2_send(), and socket_process().

03625 {
03626    int ms;
03627    int voice = 0;
03628    int genuine = 0;
03629    int adjust;
03630    struct timeval *delivery = NULL;
03631 
03632 
03633    /* What sort of frame do we have?: voice is self-explanatory
03634       "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK
03635       non-genuine frames are CONTROL frames [ringing etc], DTMF
03636       The "genuine" distinction is needed because genuine frames must get a clock-based timestamp,
03637       the others need a timestamp slaved to the voice frames so that they go in sequence
03638    */
03639    if (f) {
03640       if (f->frametype == AST_FRAME_VOICE) {
03641          voice = 1;
03642          delivery = &f->delivery;
03643       } else if (f->frametype == AST_FRAME_IAX) {
03644          genuine = 1;
03645       } else if (f->frametype == AST_FRAME_CNG) {
03646          p->notsilenttx = 0;  
03647       }
03648    }
03649    if (ast_tvzero(p->offset)) {
03650       gettimeofday(&p->offset, NULL);
03651       /* Round to nearest 20ms for nice looking traces */
03652       p->offset.tv_usec -= p->offset.tv_usec % 20000;
03653    }
03654    /* If the timestamp is specified, just send it as is */
03655    if (ts)
03656       return ts;
03657    /* If we have a time that the frame arrived, always use it to make our timestamp */
03658    if (delivery && !ast_tvzero(*delivery)) {
03659       ms = ast_tvdiff_ms(*delivery, p->offset);
03660       if (option_debug > 2 && iaxdebug)
03661          ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno);
03662    } else {
03663       ms = ast_tvdiff_ms(ast_tvnow(), p->offset);
03664       if (ms < 0)
03665          ms = 0;
03666       if (voice) {
03667          /* On a voice frame, use predicted values if appropriate */
03668          if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
03669             /* Adjust our txcore, keeping voice and non-voice synchronized */
03670             /* AN EXPLANATION:
03671                When we send voice, we usually send "calculated" timestamps worked out
03672                on the basis of the number of samples sent. When we send other frames,
03673                we usually send timestamps worked out from the real clock.
03674                The problem is that they can tend to drift out of step because the 
03675                   source channel's clock and our clock may not be exactly at the same rate.
03676                We fix this by continuously "tweaking" p->offset.  p->offset is "time zero"
03677                for this call.  Moving it adjusts timestamps for non-voice frames.
03678                We make the adjustment in the style of a moving average.  Each time we
03679                adjust p->offset by 10% of the difference between our clock-derived
03680                timestamp and the predicted timestamp.  That's why you see "10000"
03681                below even though IAX2 timestamps are in milliseconds.
03682                The use of a moving average avoids offset moving too radically.
03683                Generally, "adjust" roams back and forth around 0, with offset hardly
03684                changing at all.  But if a consistent different starts to develop it
03685                will be eliminated over the course of 10 frames (200-300msecs) 
03686             */
03687             adjust = (ms - p->nextpred);
03688             if (adjust < 0)
03689                p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000));
03690             else if (adjust > 0)
03691                p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000));
03692 
03693             if (!p->nextpred) {
03694                p->nextpred = ms; /*f->samples / 8;*/
03695                if (p->nextpred <= p->lastsent)
03696                   p->nextpred = p->lastsent + 3;
03697             }
03698             ms = p->nextpred;
03699          } else {
03700                 /* in this case, just use the actual
03701             * time, since we're either way off
03702             * (shouldn't happen), or we're  ending a
03703             * silent period -- and seed the next
03704             * predicted time.  Also, round ms to the
03705             * next multiple of frame size (so our
03706             * silent periods are multiples of
03707             * frame size too) */
03708 
03709             if (iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW )
03710                ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n",
03711                   abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW);
03712 
03713             if (f->samples >= 8) /* check to make sure we dont core dump */
03714             {
03715                int diff = ms % (f->samples / 8);
03716                if (diff)
03717                    ms += f->samples/8 - diff;
03718             }
03719 
03720             p->nextpred = ms;
03721             p->notsilenttx = 1;
03722          }
03723       } else {
03724          /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless
03725             it's a genuine frame */
03726          if (genuine) {
03727             /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */
03728             if (ms <= p->lastsent)
03729                ms = p->lastsent + 3;
03730          } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) {
03731             /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */
03732             ms = p->lastsent + 3;
03733          }
03734       }
03735    }
03736    p->lastsent = ms;
03737    if (voice)
03738       p->nextpred = p->nextpred + f->samples / 8;
03739    return ms;
03740 }

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

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

03581 {
03582    unsigned long int mssincetx; /* unsigned to handle overflows */
03583    long int ms, pred;
03584 
03585    tpeer->trunkact = *tv;
03586    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03587    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03588       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03589       tpeer->txtrunktime = *tv;
03590       tpeer->lastsent = 999999;
03591    }
03592    /* Update last transmit time now */
03593    tpeer->lasttxtime = *tv;
03594    
03595    /* Calculate ms offset */
03596    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03597    /* Predict from last value */
03598    pred = tpeer->lastsent + sampms;
03599    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03600       ms = pred;
03601    
03602    /* We never send the same timestamp twice, so fudge a little if we must */
03603    if (ms == tpeer->lastsent)
03604       ms = tpeer->lastsent + 1;
03605    tpeer->lastsent = ms;
03606    return ms;
03607 }

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

Definition at line 4839 of file chan_iax2.c.

References iax2_user::adsi, chan_iax2_pvt::adsi, chan_iax2_pvt::amaflags, iax2_user::amaflags, ao2_iterator_init(), ao2_iterator_next(), apply_context(), ast_apply_ha(), ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_inet_ntoa(), ast_log(), AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, ast_set2_flag, ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_variable_new(), iax2_user::authmethods, chan_iax2_pvt::authmethods, chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, iax2_user::capability, chan_iax2_pvt::capability, cid_name, cid_num, iax2_context::context, iax2_user::contexts, iax2_user::encmethods, chan_iax2_pvt::encmethods, exten, iax2_user::ha, iax2_getpeertrunk(), IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_MAXAUTHREQ, IAX_NOTRANSFER, IAX_PROTO_VERSION, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, ies, key(), LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, chan_iax2_pvt::peeradsicpe, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_user::prefs, chan_iax2_pvt::prefs, prefs, realtime_user(), secret, user_unref(), users, ast_variable::value, chan_iax2_pvt::vars, and iax2_user::vars.

Referenced by socket_process().

04840 {
04841    /* Start pessimistic */
04842    int res = -1;
04843    int version = 2;
04844    struct iax2_user *user = NULL, *best = NULL;
04845    int bestscore = 0;
04846    int gotcapability = 0;
04847    struct ast_variable *v = NULL, *tmpvar = NULL;
04848    ao2_iterator i;
04849 
04850    if (!iaxs[callno])
04851       return res;
04852    if (ies->called_number)
04853       ast_string_field_set(iaxs[callno], exten, ies->called_number);
04854    if (ies->calling_number) {
04855       ast_shrink_phone_number(ies->calling_number);
04856       ast_string_field_set(iaxs[callno], cid_num, ies->calling_number);
04857    }
04858    if (ies->calling_name)
04859       ast_string_field_set(iaxs[callno], cid_name, ies->calling_name);
04860    if (ies->calling_ani)
04861       ast_string_field_set(iaxs[callno], ani, ies->calling_ani);
04862    if (ies->dnid)
04863       ast_string_field_set(iaxs[callno], dnid, ies->dnid);
04864    if (ies->rdnis)
04865       ast_string_field_set(iaxs[callno], rdnis, ies->rdnis);
04866    if (ies->called_context)
04867       ast_string_field_set(iaxs[callno], context, ies->called_context);
04868    if (ies->language)
04869       ast_string_field_set(iaxs[callno], language, ies->language);
04870    if (ies->username)
04871       ast_string_field_set(iaxs[callno], username, ies->username);
04872    if (ies->calling_ton > -1)
04873       iaxs[callno]->calling_ton = ies->calling_ton;
04874    if (ies->calling_tns > -1)
04875       iaxs[callno]->calling_tns = ies->calling_tns;
04876    if (ies->calling_pres > -1)
04877       iaxs[callno]->calling_pres = ies->calling_pres;
04878    if (ies->format)
04879       iaxs[callno]->peerformat = ies->format;
04880    if (ies->adsicpe)
04881       iaxs[callno]->peeradsicpe = ies->adsicpe;
04882    if (ies->capability) {
04883       gotcapability = 1;
04884       iaxs[callno]->peercapability = ies->capability;
04885    } 
04886    if (ies->version)
04887       version = ies->version;
04888 
04889    /* Use provided preferences until told otherwise for actual preferences */
04890    if(ies->codec_prefs) {
04891       ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
04892       ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
04893    }
04894 
04895    if (!gotcapability) 
04896       iaxs[callno]->peercapability = iaxs[callno]->peerformat;
04897    if (version > IAX_PROTO_VERSION) {
04898       ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 
04899          ast_inet_ntoa(sin->sin_addr), version);
04900       return res;
04901    }
04902    /* Search the userlist for a compatible entry, and fill in the rest */
04903    i = ao2_iterator_init(users, 0);
04904    while ((user = ao2_iterator_next(&i))) {
04905       if ((ast_strlen_zero(iaxs[callno]->username) ||          /* No username specified */
04906          !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */
04907          && ast_apply_ha(user->ha, sin)   /* Access is permitted from this IP */
04908          && (ast_strlen_zero(iaxs[callno]->context) ||         /* No context specified */
04909               apply_context(user->contexts, iaxs[callno]->context))) {        /* Context is permitted */
04910          if (!ast_strlen_zero(iaxs[callno]->username)) {
04911             /* Exact match, stop right now. */
04912             if (best)
04913                user_unref(best);
04914             best = user;
04915             break;
04916          } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->inkeys)) {
04917             /* No required authentication */
04918             if (user->ha) {
04919                /* There was host authentication and we passed, bonus! */
04920                if (bestscore < 4) {
04921                   bestscore = 4;
04922                   if (best)
04923                      user_unref(best);
04924                   best = user;
04925                   continue;
04926                }
04927             } else {
04928                /* No host access, but no secret, either, not bad */
04929                if (bestscore < 3) {
04930                   bestscore = 3;
04931                   if (best)
04932                      user_unref(best);
04933                   best = user;
04934                   continue;
04935                }
04936             }
04937          } else {
04938             if (user->ha) {
04939                /* Authentication, but host access too, eh, it's something.. */
04940                if (bestscore < 2) {
04941                   bestscore = 2;
04942                   if (best)
04943                      user_unref(best);
04944                   best = user;
04945                   continue;
04946                }
04947             } else {
04948                /* Authentication and no host access...  This is our baseline */
04949                if (bestscore < 1) {
04950                   bestscore = 1;
04951                   if (best)
04952                      user_unref(best);
04953                   best = user;
04954                   continue;
04955                }
04956             }
04957          }
04958       }
04959       user_unref(user);
04960    }
04961    user = best;
04962    if (!user && !ast_strlen_zero(iaxs[callno]->username)) {
04963       user = realtime_user(iaxs[callno]->username);
04964       if (user && !ast_strlen_zero(iaxs[callno]->context) &&         /* No context specified */
04965           !apply_context(user->contexts, iaxs[callno]->context)) {      /* Context is permitted */
04966          user = user_unref(user);
04967       }
04968    }
04969    if (user) {
04970       /* We found our match (use the first) */
04971       /* copy vars */
04972       for (v = user->vars ; v ; v = v->next) {
04973          if((tmpvar = ast_variable_new(v->name, v->value))) {
04974             tmpvar->next = iaxs[callno]->vars; 
04975             iaxs[callno]->vars = tmpvar;
04976          }
04977       }
04978       /* If a max AUTHREQ restriction is in place, activate it */
04979       if (user->maxauthreq > 0)
04980          ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ);
04981       iaxs[callno]->prefs = user->prefs;
04982       ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST);
04983       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS);
04984       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP);
04985       iaxs[callno]->encmethods = user->encmethods;
04986       /* Store the requested username if not specified */
04987       if (ast_strlen_zero(iaxs[callno]->username))
04988          ast_string_field_set(iaxs[callno], username, user->name);
04989       /* Store whether this is a trunked call, too, of course, and move if appropriate */
04990       ast_copy_flags(iaxs[callno], user, IAX_TRUNK);
04991       iaxs[callno]->capability = user->capability;
04992       /* And use the default context */
04993       if (ast_strlen_zero(iaxs[callno]->context)) {
04994          if (user->contexts)
04995             ast_string_field_set(iaxs[callno], context, user->contexts->context);
04996          else
04997             ast_string_field_set(iaxs[callno], context, context);
04998       }
04999       /* And any input keys */
05000       ast_string_field_set(iaxs[callno], inkeys, user->inkeys);
05001       /* And the permitted authentication methods */
05002       iaxs[callno]->authmethods = user->authmethods;
05003       iaxs[callno]->adsi = user->adsi;
05004       /* If they have callerid, override the given caller id.  Always store the ANI */
05005       if (!ast_strlen_zero(iaxs[callno]->cid_num) || !ast_strlen_zero(iaxs[callno]->cid_name)) {
05006          if (ast_test_flag(user, IAX_HASCALLERID)) {
05007             iaxs[callno]->calling_tns = 0;
05008             iaxs[callno]->calling_ton = 0;
05009             ast_string_field_set(iaxs[callno], cid_num, user->cid_num);
05010             ast_string_field_set(iaxs[callno], cid_name, user->cid_name);
05011             iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
05012          }
05013          if (ast_strlen_zero(iaxs[callno]->ani))
05014             ast_string_field_set(iaxs[callno], ani, user->cid_num);
05015       } else {
05016          iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE;
05017       }
05018       if (!ast_strlen_zero(user->accountcode))
05019          ast_string_field_set(iaxs[callno], accountcode, user->accountcode);
05020       if (!ast_strlen_zero(user->mohinterpret))
05021          ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret);
05022       if (!ast_strlen_zero(user->mohsuggest))
05023          ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest);
05024       if (user->amaflags)
05025          iaxs[callno]->amaflags = user->amaflags;
05026       if (!ast_strlen_zero(user->language))
05027          ast_string_field_set(iaxs[callno], language, user->language);
05028       ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);   
05029       /* Keep this check last */
05030       if (!ast_strlen_zero(user->dbsecret)) {
05031          char *family, *key=NULL;
05032          char buf[80];
05033          family = ast_strdupa(user->dbsecret);
05034          key = strchr(family, '/');
05035          if (key) {
05036             *key = '\0';
05037             key++;
05038          }
05039          if (!key || ast_db_get(family, key, buf, sizeof(buf)))
05040             ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret);
05041          else
05042             ast_string_field_set(iaxs[callno], secret, buf);
05043       } else
05044          ast_string_field_set(iaxs[callno], secret, user->secret);
05045       res = 0;
05046       user = user_unref(user);
05047    }
05048    ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);  
05049    return res;
05050 }

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

Definition at line 6488 of file chan_iax2.c.

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

Referenced by socket_process().

06489 {
06490    unsigned int ourver;
06491    char rsi[80];
06492    snprintf(rsi, sizeof(rsi), "si-%s", si);
06493    if (iax_provision_version(&ourver, rsi, 1))
06494       return 0;
06495    if (option_debug)
06496       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06497    if (ourver != ver) 
06498       iax2_provision(sin, sockfd, NULL, rsi, 1);
06499    return 0;
06500 }

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

References ast_log(), and LOG_ERROR.

Referenced by peer_set_srcaddr().

08810 {
08811    int sd;
08812    int res;
08813    
08814    sd = socket(AF_INET, SOCK_DGRAM, 0);
08815    if (sd < 0) {
08816       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
08817       return -1;
08818    }
08819 
08820    res = bind(sd, sa, salen);
08821    if (res < 0) {
08822       ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
08823       close(sd);
08824       return 1;
08825    }
08826 
08827    close(sd);
08828    return 0;
08829 }

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

Definition at line 5531 of file chan_iax2.c.

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

Referenced by socket_process().

05532 {
05533    char exten[256] = "";
05534    int status = CACHE_FLAG_UNKNOWN;
05535    int expiry = iaxdefaultdpcache;
05536    int x;
05537    int matchmore = 0;
05538    struct iax2_dpcache *dp, *prev;
05539    
05540    if (ies->called_number)
05541       ast_copy_string(exten, ies->called_number, sizeof(exten));
05542 
05543    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
05544       status = CACHE_FLAG_EXISTS;
05545    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
05546       status = CACHE_FLAG_CANEXIST;
05547    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
05548       status = CACHE_FLAG_NONEXISTENT;
05549 
05550    if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
05551       /* Don't really do anything with this */
05552    }
05553    if (ies->refresh)
05554       expiry = ies->refresh;
05555    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
05556       matchmore = CACHE_FLAG_MATCHMORE;
05557    ast_mutex_lock(&dpcache_lock);
05558    prev = NULL;
05559    dp = pvt->dpentries;
05560    while(dp) {
05561       if (!strcmp(dp->exten, exten)) {
05562          /* Let them go */
05563          if (prev)
05564             prev->peer = dp->peer;
05565          else
05566             pvt->dpentries = dp->peer;
05567          dp->peer = NULL;
05568          dp->callno = 0;
05569          dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
05570          if (dp->flags & CACHE_FLAG_PENDING) {
05571             dp->flags &= ~CACHE_FLAG_PENDING;
05572             dp->flags |= status;
05573             dp->flags |= matchmore;
05574          }
05575          /* Wake up waiters */
05576          for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
05577             if (dp->waiters[x] > -1)
05578                write(dp->waiters[x], "asdf", 4);
05579       }
05580       prev = dp;
05581       dp = dp->peer;
05582    }
05583    ast_mutex_unlock(&dpcache_lock);
05584    return 0;
05585 }

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

Definition at line 2275 of file chan_iax2.c.

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

02276 {
02277    int which = 0;
02278    struct iax2_peer *peer;
02279    char *res = NULL;
02280    int wordlen = strlen(word);
02281    ao2_iterator i;
02282 
02283    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02284    if (pos != 3)
02285       return NULL;
02286 
02287    i = ao2_iterator_init(peers, 0);
02288    while ((peer = ao2_iterator_next(&i))) {
02289       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02290          res = ast_strdup(peer->name);
02291          peer_unref(peer);
02292          break;
02293       }
02294       peer_unref(peer);
02295    }
02296 
02297    return res;
02298 }

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

Definition at line 5587 of file chan_iax2.c.

References chan_iax2_pvt::addr, chan_iax2_pvt::aseqno, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), iax_frame::callno, jb_frame::data, DEFAULT_RETRY_TIME, iax2_frame_free(), iaxq, iaxs, ies, chan_iax2_pvt::iseqno, chan_iax2_pvt::jb, jb_getall(), JB_OK, jb_reset(), chan_iax2_pvt::lag, chan_iax2_pvt::last, chan_iax2_pvt::lastsent, LOG_WARNING, chan_iax2_pvt::nextpred, chan_iax2_pvt::offset, chan_iax2_pvt::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, iax_frame::retries, chan_iax2_pvt::rseqno, chan_iax2_pvt::rxcore, 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().

05588 {
05589    int peercallno = 0;
05590    struct chan_iax2_pvt *pvt = iaxs[callno];
05591    struct iax_frame *cur;
05592    jb_frame frame;
05593 
05594    if (ies->callno)
05595       peercallno = ies->callno;
05596 
05597    if (peercallno < 1) {
05598       ast_log(LOG_WARNING, "Invalid transfer request\n");
05599       return -1;
05600    }
05601    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
05602    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
05603    /* Reset sequence numbers */
05604    pvt->oseqno = 0;
05605    pvt->rseqno = 0;
05606    pvt->iseqno = 0;
05607    pvt->aseqno = 0;
05608    pvt->peercallno = peercallno;
05609    pvt->transferring = TRANSFER_NONE;
05610    pvt->svoiceformat = -1;
05611    pvt->voiceformat = 0;
05612    pvt->svideoformat = -1;
05613    pvt->videoformat = 0;
05614    pvt->transfercallno = -1;
05615    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
05616    memset(&pvt->offset, 0, sizeof(pvt->offset));
05617    /* reset jitterbuffer */
05618    while(jb_getall(pvt->jb,&frame) == JB_OK)
05619       iax2_frame_free(frame.data);
05620    jb_reset(pvt->jb);
05621    pvt->lag = 0;
05622    pvt->last = 0;
05623    pvt->lastsent = 0;
05624    pvt->nextpred = 0;
05625    pvt->pingtime = DEFAULT_RETRY_TIME;
05626    AST_LIST_LOCK(&iaxq.queue);
05627    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
05628       /* We must cancel any packets that would have been transmitted
05629          because now we're talking to someone new.  It's okay, they
05630          were transmitted to someone that didn't care anyway. */
05631       if (callno == cur->callno) 
05632          cur->retries = -1;
05633    }
05634    AST_LIST_UNLOCK(&iaxq.queue);
05635    return 0; 
05636 }

static unsigned char compress_subclass ( int  subclass  )  [static]

Definition at line 1023 of file chan_iax2.c.

References ast_log(), IAX_FLAG_SC_LOG, IAX_MAX_SHIFT, and LOG_WARNING.

Referenced by iax2_send(), and raw_hangup().

01024 {
01025    int x;
01026    int power=-1;
01027    /* If it's 128 or smaller, just return it */
01028    if (subclass < IAX_FLAG_SC_LOG)
01029       return subclass;
01030    /* Otherwise find its power */
01031    for (x = 0; x < IAX_MAX_SHIFT; x++) {
01032       if (subclass & (1 << x)) {
01033          if (power > -1) {
01034             ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass);
01035             return 0;
01036          } else
01037             power = x;
01038       }
01039    }
01040    return power | IAX_FLAG_SC_LOG;
01041 }

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

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

06503 {
06504    jb_info stats;
06505    jb_getinfo(pvt->jb, &stats);
06506    
06507    memset(iep, 0, sizeof(*iep));
06508 
06509    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06510    if(stats.frames_in == 0) stats.frames_in = 1;
06511    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06512    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06513    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06514    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06515    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06516 }

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

Definition at line 2837 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ahp, ast_clear_flag, ast_codec_pref_convert(), ast_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, key(), iax2_peer::lastms, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, 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.

02838 {
02839    struct ast_hostent ahp;
02840    struct hostent *hp;
02841    struct iax2_peer *peer;
02842    int res = -1;
02843 
02844    ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
02845    cai->sockfd = defaultsockfd;
02846    cai->maxtime = 0;
02847    sin->sin_family = AF_INET;
02848 
02849    if (!(peer = find_peer(peername, 1))) {
02850       cai->found = 0;
02851 
02852       hp = ast_gethostbyname(peername, &ahp);
02853       if (hp) {
02854          memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
02855          sin->sin_port = htons(IAX_DEFAULT_PORTNO);
02856          /* use global iax prefs for unknown peer/user */
02857          ast_codec_pref_convert(&prefs, cai->prefs, sizeof(cai->prefs), 1);
02858          return 0;
02859       } else {
02860          ast_log(LOG_WARNING, "No such host: %s\n", peername);
02861          return -1;
02862       }
02863    }
02864 
02865    cai->found = 1;
02866    
02867    /* if the peer has no address (current or default), return failure */
02868    if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr))
02869       goto return_unref;
02870 
02871    /* if the peer is being monitored and is currently unreachable, return failure */
02872    if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
02873       goto return_unref;
02874 
02875    ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
02876    cai->maxtime = peer->maxms;
02877    cai->capability = peer->capability;
02878    cai->encmethods = peer->encmethods;
02879    cai->sockfd = peer->sockfd;
02880    cai->adsi = peer->adsi;
02881    ast_codec_pref_convert(&peer->prefs, cai->prefs, sizeof(cai->prefs), 1);
02882    ast_copy_string(cai->context, peer->context, sizeof(cai->context));
02883    ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
02884    ast_copy_string(cai->username, peer->username, sizeof(cai->username));
02885    ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
02886    ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
02887    ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
02888    ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
02889    if (ast_strlen_zero(peer->dbsecret)) {
02890       ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret));
02891    } else {
02892       char *family;
02893       char *key = NULL;
02894 
02895       family = ast_strdupa(peer->dbsecret);
02896       key = strchr(family, '/');
02897       if (key)
02898          *key++ = '\0';
02899       if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) {
02900          ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret);
02901          goto return_unref;
02902       }
02903    }
02904 
02905    if (peer->addr.sin_addr.s_addr) {
02906       sin->sin_addr = peer->addr.sin_addr;
02907       sin->sin_port = peer->addr.sin_port;
02908    } else {
02909       sin->sin_addr = peer->defaddr.sin_addr;
02910       sin->sin_port = peer->defaddr.sin_port;
02911    }
02912 
02913    res = 0;
02914 
02915 return_unref:
02916    peer_unref(peer);
02917 
02918    return res;
02919 }

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

Definition at line 3926 of file chan_iax2.c.

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

Referenced by decrypt_frame().

03927 {
03928    int padding;
03929    unsigned char *workspace;
03930 
03931    workspace = alloca(*datalen);
03932    memset(f, 0, sizeof(*f));
03933    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
03934       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
03935       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
03936          return -1;
03937       /* Decrypt */
03938       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
03939 
03940       padding = 16 + (workspace[15] & 0xf);
03941       if (option_debug && iaxdebug)
03942          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
03943       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
03944          return -1;
03945 
03946       *datalen -= padding;
03947       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
03948       f->frametype = fh->type;
03949       if (f->frametype == AST_FRAME_VIDEO) {
03950          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
03951       } else {
03952          f->subclass = uncompress_subclass(fh->csub);
03953       }
03954    } else {
03955       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
03956       if (option_debug && iaxdebug)
03957          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
03958       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
03959          return -1;
03960       /* Decrypt */
03961       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
03962       padding = 16 + (workspace[15] & 0x0f);
03963       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
03964          return -1;
03965       *datalen -= padding;
03966       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
03967    }
03968    return 0;
03969 }

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

Definition at line 4012 of file chan_iax2.c.

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

Referenced by socket_process().

04013 {
04014    int res=-1;
04015    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04016       /* Search for possible keys, given secrets */
04017       struct MD5Context md5;
04018       unsigned char digest[16];
04019       char *tmppw, *stringp;
04020       
04021       tmppw = ast_strdupa(iaxs[callno]->secret);
04022       stringp = tmppw;
04023       while ((tmppw = strsep(&stringp, ";"))) {
04024          MD5Init(&md5);
04025          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04026          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04027          MD5Final(digest, &md5);
04028          build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx);
04029          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04030          if (!res) {
04031             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04032             break;
04033          }
04034       }
04035    } else 
04036       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04037    return res;
04038 }

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

06565 {
06566    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06567    struct ast_iax2_full_hdr *fh, *cur_fh;
06568 
06569    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06570       return;
06571 
06572    pkt_buf->len = from_here->buf_len;
06573    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06574 
06575    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06576    ast_mutex_lock(&to_here->lock);
06577    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06578       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06579       if (fh->oseqno < cur_fh->oseqno) {
06580          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06581          break;
06582       }
06583    }
06584    AST_LIST_TRAVERSE_SAFE_END
06585 
06586    if (!cur_pkt_buf)
06587       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06588    
06589    ast_mutex_unlock(&to_here->lock);
06590 }

static void delete_users ( void   )  [static]

Definition at line 9410 of file chan_iax2.c.

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

09411 {
09412    struct iax2_registry *reg;
09413 
09414    ao2_callback(users, 0, user_delme_cb, NULL);
09415 
09416    AST_LIST_LOCK(&registrations);
09417    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09418       if (reg->expire > -1)
09419          ast_sched_del(sched, reg->expire);
09420       if (reg->callno) {
09421          ast_mutex_lock(&iaxsl[reg->callno]);
09422          if (iaxs[reg->callno]) {
09423             iaxs[reg->callno]->reg = NULL;
09424             iax2_destroy(reg->callno);
09425          }
09426          ast_mutex_unlock(&iaxsl[reg->callno]);
09427       }
09428       if (reg->dnsmgr)
09429          ast_dnsmgr_release(reg->dnsmgr);
09430       free(reg);
09431    }
09432    AST_LIST_UNLOCK(&registrations);
09433 
09434    ao2_callback(peers, 0, peer_delme_cb, NULL);
09435 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1513 of file chan_iax2.c.

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

Referenced by reload_firmware().

01514 {
01515    /* Close firmware */
01516    if (cur->fwh) {
01517       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01518    }
01519    close(cur->fd);
01520    free(cur);
01521 }

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

Definition at line 6336 of file chan_iax2.c.

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

Referenced by dp_lookup_thread(), and socket_process().

06337 {
06338    unsigned short dpstatus = 0;
06339    struct iax_ie_data ied1;
06340    int mm;
06341 
06342    memset(&ied1, 0, sizeof(ied1));
06343    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06344    /* Must be started */
06345    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06346       dpstatus = IAX_DPSTATUS_EXISTS;
06347    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06348       dpstatus = IAX_DPSTATUS_CANEXIST;
06349    } else {
06350       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06351    }
06352    if (ast_ignore_pattern(context, callednum))
06353       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06354    if (mm)
06355       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06356    if (!skiplock)
06357       ast_mutex_lock(&iaxsl[callno]);
06358    if (iaxs[callno]) {
06359       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06360       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06361       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06362       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06363    }
06364    if (!skiplock)
06365       ast_mutex_unlock(&iaxsl[callno]);
06366 }

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

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

06369 {
06370    /* Look up for dpreq */
06371    struct dpreq_data *dpr = data;
06372    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06373    if (dpr->callerid)
06374       free(dpr->callerid);
06375    free(dpr);
06376    return NULL;
06377 }

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

Definition at line 3971 of file chan_iax2.c.

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

Referenced by iax2_send().

03972 {
03973    int padding;
03974    unsigned char *workspace;
03975    workspace = alloca(*datalen + 32);
03976    if (!workspace)
03977       return -1;
03978    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
03979       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
03980       if (option_debug && iaxdebug)
03981          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
03982       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
03983       padding = 16 + (padding & 0xf);
03984       memcpy(workspace, poo, padding);
03985       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
03986       workspace[15] &= 0xf0;
03987       workspace[15] |= (padding & 0xf);
03988       if (option_debug && iaxdebug)
03989          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]);
03990       *datalen += padding;
03991       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
03992       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
03993          memcpy(poo, workspace + *datalen - 32, 32);
03994    } else {
03995       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
03996       if (option_debug && iaxdebug)
03997          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
03998       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
03999       padding = 16 + (padding & 0xf);
04000       memcpy(workspace, poo, padding);
04001       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04002       workspace[15] &= 0xf0;
04003       workspace[15] |= (padding & 0x0f);
04004       *datalen += padding;
04005       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
04006       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
04007          memcpy(poo, workspace + *datalen - 32, 32);
04008    }
04009    return 0;
04010 }

static int expire_registry ( void *  data  )  [static]

Definition at line 5804 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

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

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

Definition at line 9943 of file chan_iax2.c.

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

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

09944 {
09945    struct iax2_dpcache *dp, *prev = NULL, *next;
09946    struct timeval tv;
09947    int x;
09948    int com[2];
09949    int timeout;
09950    int old=0;
09951    int outfd;
09952    int abort;
09953    int callno;
09954    struct ast_channel *c;
09955    struct ast_frame *f;
09956    gettimeofday(&tv, NULL);
09957    dp = dpcache;
09958    while(dp) {
09959       next = dp->next;
09960       /* Expire old caches */
09961       if (ast_tvcmp(tv, dp->expiry) > 0) {
09962             /* It's expired, let it disappear */
09963             if (prev)
09964                prev->next = dp->next;
09965             else
09966                dpcache = dp->next;
09967             if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) {
09968                /* Free memory and go again */
09969                free(dp);
09970             } else {
09971                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);
09972             }
09973             dp = next;
09974             continue;
09975       }
09976       /* We found an entry that matches us! */
09977       if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 
09978          break;
09979       prev = dp;
09980       dp = next;
09981    }
09982    if (!dp) {
09983       /* No matching entry.  Create a new one. */
09984       /* First, can we make a callno? */
09985       callno = cache_get_callno_locked(data);
09986       if (callno < 0) {
09987          ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data);
09988          return NULL;
09989       }
09990       if (!(dp = ast_calloc(1, sizeof(*dp)))) {
09991          ast_mutex_unlock(&iaxsl[callno]);
09992          return NULL;
09993       }
09994       ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext));
09995       ast_copy_string(dp->exten, exten, sizeof(dp->exten));
09996       gettimeofday(&dp->expiry, NULL);
09997       dp->orig = dp->expiry;
09998       /* Expires in 30 mins by default */
09999       dp->expiry.tv_sec += iaxdefaultdpcache;
10000       dp->next = dpcache;
10001       dp->flags = CACHE_FLAG_PENDING;
10002       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10003          dp->waiters[x] = -1;
10004       dpcache = dp;
10005       dp->peer = iaxs[callno]->dpentries;
10006       iaxs[callno]->dpentries = dp;
10007       /* Send the request if we're already up */
10008       if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
10009          iax2_dprequest(dp, callno);
10010       ast_mutex_unlock(&iaxsl[callno]);
10011    }
10012    /* By here we must have a dp */
10013    if (dp->flags & CACHE_FLAG_PENDING) {
10014       /* Okay, here it starts to get nasty.  We need a pipe now to wait
10015          for a reply to come back so long as it's pending */
10016       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) {
10017          /* Find an empty slot */
10018          if (dp->waiters[x] < 0)
10019             break;
10020       }
10021       if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) {
10022          ast_log(LOG_WARNING, "No more waiter positions available\n");
10023          return NULL;
10024       }
10025       if (pipe(com)) {
10026          ast_log(LOG_WARNING, "Unable to create pipe for comm\n");
10027          return NULL;
10028       }
10029       dp->waiters[x] = com[1];
10030       /* Okay, now we wait */
10031       timeout = iaxdefaulttimeout * 1000;
10032       /* Temporarily unlock */
10033       ast_mutex_unlock(&dpcache_lock);
10034       /* Defer any dtmf */
10035       if (chan)
10036          old = ast_channel_defer_dtmf(chan);
10037       abort = 0;
10038       while(timeout) {
10039          c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
10040          if (outfd > -1) {
10041             break;
10042          }
10043          if (c) {
10044             f = ast_read(c);
10045             if (f)
10046                ast_frfree(f);
10047             else {
10048                /* Got hung up on, abort! */
10049                break;
10050                abort = 1;
10051             }
10052          }
10053       }
10054       if (!timeout) {
10055          ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
10056       }
10057       ast_mutex_lock(&dpcache_lock);
10058       dp->waiters[x] = -1;
10059       close(com[1]);
10060       close(com[0]);
10061       if (abort) {
10062          /* Don't interpret anything, just abort.  Not sure what th epoint
10063            of undeferring dtmf on a hung up channel is but hey whatever */
10064          if (!old && chan)
10065             ast_channel_undefer_dtmf(chan);
10066          return NULL;
10067       }
10068       if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
10069          /* Now to do non-independent analysis the results of our wait */
10070          if (dp->flags & CACHE_FLAG_PENDING) {
10071             /* Still pending... It's a timeout.  Wake everybody up.  Consider it no longer
10072                pending.  Don't let it take as long to timeout. */
10073             dp->flags &= ~CACHE_FLAG_PENDING;
10074             dp->flags |= CACHE_FLAG_TIMEOUT;
10075             /* Expire after only 60 seconds now.  This is designed to help reduce backlog in heavily loaded
10076                systems without leaving it unavailable once the server comes back online */
10077             dp->expiry.tv_sec = dp->orig.tv_sec + 60;
10078             for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10079                if (dp->waiters[x] > -1)
10080                   write(dp->waiters[x], "asdf", 4);
10081          }
10082       }
10083       /* Our caller will obtain the rest */
10084       if (!old && chan)
10085          ast_channel_undefer_dtmf(chan);
10086    }
10087    return dp;  
10088 }

static int find_callno ( unsigned short  callno,
unsigned short  dcallno,
struct sockaddr_in *  sin,
int  new,
int  sockfd 
) [static]

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

Definition at line 1327 of file chan_iax2.c.

References chan_iax2_pvt::addr, chan_iax2_pvt::amaflags, ast_copy_flags, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_string_field_set, chan_iax2_pvt::callno, DEFAULT_RETRY_TIME, chan_iax2_pvt::expiry, globalflags, iax2_getpeername(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, iaxs, iaxsl, chan_iax2_pvt::lagid, LOG_DEBUG, LOG_WARNING, match(), MIN_REUSE_TIME, NEW_ALLOW, new_iax(), option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, chan_iax2_pvt::pingtime, sched, send_lagrq(), send_ping(), chan_iax2_pvt::sockfd, TRUNK_CALL_START, and update_max_nontrunk().

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

01328 {
01329    int res = 0;
01330    int x;
01331    struct timeval now;
01332    char host[80];
01333 
01334    if (new <= NEW_ALLOW) {
01335       /* Look for an existing connection first */
01336       for (x=1;(res < 1) && (x<maxnontrunkcall);x++) {
01337          ast_mutex_lock(&iaxsl[x]);
01338          if (iaxs[x]) {
01339             /* Look for an exact match */
01340             if (match(sin, callno, dcallno, iaxs[x])) {
01341                res = x;
01342             }
01343          }
01344          ast_mutex_unlock(&iaxsl[x]);
01345       }
01346       for (x=TRUNK_CALL_START;(res < 1) && (x<maxtrunkcall);x++) {
01347          ast_mutex_lock(&iaxsl[x]);
01348          if (iaxs[x]) {
01349             /* Look for an exact match */
01350             if (match(sin, callno, dcallno, iaxs[x])) {
01351                res = x;
01352             }
01353          }
01354          ast_mutex_unlock(&iaxsl[x]);
01355       }
01356    }
01357    if ((res < 1) && (new >= NEW_ALLOW)) {
01358       /* It may seem odd that we look through the peer list for a name for
01359        * this *incoming* call.  Well, it is weird.  However, users don't
01360        * have an IP address/port number that we can match against.  So,
01361        * this is just checking for a peer that has that IP/port and
01362        * assuming that we have a user of the same name.  This isn't always
01363        * correct, but it will be changed if needed after authentication. */
01364       if (!iax2_getpeername(*sin, host, sizeof(host)))
01365          snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
01366       gettimeofday(&now, NULL);
01367       for (x=1;x<TRUNK_CALL_START;x++) {
01368          /* Find first unused call number that hasn't been used in a while */
01369          ast_mutex_lock(&iaxsl[x]);
01370          if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) break;
01371          ast_mutex_unlock(&iaxsl[x]);
01372       }
01373       /* We've still got lock held if we found a spot */
01374       if (x >= TRUNK_CALL_START) {
01375          ast_log(LOG_WARNING, "No more space\n");
01376          return 0;
01377       }
01378       iaxs[x] = new_iax(sin, host);
01379       update_max_nontrunk();
01380       if (iaxs[x]) {
01381          if (option_debug && iaxdebug)
01382             ast_log(LOG_DEBUG, "Creating new call structure %d\n", x);
01383          iaxs[x]->sockfd = sockfd;
01384          iaxs[x]->addr.sin_port = sin->sin_port;
01385          iaxs[x]->addr.sin_family = sin->sin_family;
01386          iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr;
01387          iaxs[x]->peercallno = callno;
01388          iaxs[x]->callno = x;
01389          iaxs[x]->pingtime = DEFAULT_RETRY_TIME;
01390          iaxs[x]->expiry = min_reg_expire;
01391          iaxs[x]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01392          iaxs[x]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01393          iaxs[x]->amaflags = amaflags;
01394          ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
01395          
01396          ast_string_field_set(iaxs[x], accountcode, accountcode);
01397          ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
01398          ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
01399       } else {
01400          ast_log(LOG_WARNING, "Out of resources\n");
01401          ast_mutex_unlock(&iaxsl[x]);
01402          return 0;
01403       }
01404       ast_mutex_unlock(&iaxsl[x]);
01405       res = x;
01406    }
01407    return res;
01408 }

static struct iax2_thread* find_idle_thread ( void   )  [static]

Definition at line 889 of file chan_iax2.c.

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

Referenced by __schedule_action(), and socket_read().

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

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

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

Definition at line 1101 of file chan_iax2.c.

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

01102 {
01103    struct iax2_peer *peer = NULL;
01104    struct iax2_peer tmp_peer = {
01105       .name = name,
01106    };
01107 
01108    peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
01109 
01110    /* Now go for realtime if applicable */
01111    if(!peer && realtime)
01112       peer = realtime_peer(name, NULL);
01113 
01114    return peer;
01115 }

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

Definition at line 3782 of file chan_iax2.c.

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

Referenced by iax2_trunk_queue(), and socket_process().

03783 {
03784    struct iax2_trunk_peer *tpeer;
03785    
03786    /* Finds and locks trunk peer */
03787    ast_mutex_lock(&tpeerlock);
03788    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
03789       /* We don't lock here because tpeer->addr *never* changes */
03790       if (!inaddrcmp(&tpeer->addr, sin)) {
03791          ast_mutex_lock(&tpeer->lock);
03792          break;
03793       }
03794    }
03795    if (!tpeer) {
03796       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
03797          ast_mutex_init(&tpeer->lock);
03798          tpeer->lastsent = 9999;
03799          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
03800          tpeer->trunkact = ast_tvnow();
03801          ast_mutex_lock(&tpeer->lock);
03802          tpeer->next = tpeers;
03803          tpeer->sockfd = fd;
03804          tpeers = tpeer;
03805 #ifdef SO_NO_CHECK
03806          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
03807 #endif
03808          ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
03809       }
03810    }
03811    ast_mutex_unlock(&tpeerlock);
03812    return tpeer;
03813 }

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

Definition at line 3609 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03610 {
03611    long ms; /* NOT unsigned */
03612    if (ast_tvzero(iaxs[callno]->rxcore)) {
03613       /* Initialize rxcore time if appropriate */
03614       gettimeofday(&iaxs[callno]->rxcore, NULL);
03615       /* Round to nearest 20ms so traces look pretty */
03616       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03617    }
03618    /* Calculate difference between trunk and channel */
03619    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03620    /* Return as the sum of trunk time and the difference between trunk and real time */
03621    return ms + ts;
03622 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8564 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

08565 {
08566    struct iax2_context *conl;
08567    while(con) {
08568       conl = con;
08569       con = con->next;
08570       free(conl);
08571    }
08572 }

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

Definition at line 10212 of file chan_iax2.c.

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

10213 {
10214    struct iax2_peer *peer;
10215    char *peername, *colname;
10216 
10217    peername = ast_strdupa(data);
10218 
10219    /* if our channel, return the IP address of the endpoint of current channel */
10220    if (!strcmp(peername,"CURRENTCHANNEL")) {
10221            unsigned short callno;
10222       if (chan->tech != &iax2_tech)
10223          return -1;
10224       callno = PTR_TO_CALLNO(chan->tech_pvt);   
10225       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
10226       return 0;
10227    }
10228 
10229    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
10230       *colname++ = '\0';
10231    else if ((colname = strchr(peername, '|')))
10232       *colname++ = '\0';
10233    else
10234       colname = "ip";
10235 
10236    if (!(peer = find_peer(peername, 1)))
10237       return -1;
10238 
10239    if (!strcasecmp(colname, "ip")) {
10240       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
10241    } else  if (!strcasecmp(colname, "status")) {
10242       peer_status(peer, buf, len); 
10243    } else  if (!strcasecmp(colname, "mailbox")) {
10244       ast_copy_string(buf, peer->mailbox, len);
10245    } else  if (!strcasecmp(colname, "context")) {
10246       ast_copy_string(buf, peer->context, len);
10247    } else  if (!strcasecmp(colname, "expire")) {
10248       snprintf(buf, len, "%d", peer->expire);
10249    } else  if (!strcasecmp(colname, "dynamic")) {
10250       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
10251    } else  if (!strcasecmp(colname, "callerid_name")) {
10252       ast_copy_string(buf, peer->cid_name, len);
10253    } else  if (!strcasecmp(colname, "callerid_num")) {
10254       ast_copy_string(buf, peer->cid_num, len);
10255    } else  if (!strcasecmp(colname, "codecs")) {
10256       ast_getformatname_multiple(buf, len -1, peer->capability);
10257    } else  if (!strncasecmp(colname, "codec[", 6)) {
10258       char *codecnum, *ptr;
10259       int index = 0, codec = 0;
10260       
10261       codecnum = strchr(colname, '[');
10262       *codecnum = '\0';
10263       codecnum++;
10264       if ((ptr = strchr(codecnum, ']'))) {
10265          *ptr = '\0';
10266       }
10267       index = atoi(codecnum);
10268       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
10269          ast_copy_string(buf, ast_getformatname(codec), len);
10270       }
10271    }
10272 
10273    peer_unref(peer);
10274 
10275    return 0;
10276 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 8793 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

08794 {
08795    int methods = 0;
08796    if (strstr(value, "rsa"))
08797       methods |= IAX_AUTH_RSA;
08798    if (strstr(value, "md5"))
08799       methods |= IAX_AUTH_MD5;
08800    if (strstr(value, "plaintext"))
08801       methods |= IAX_AUTH_PLAINTEXT;
08802    return methods;
08803 }

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

Definition at line 988 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

00989 {
00990    int e;
00991    if (!strcasecmp(s, "aes128"))
00992       e = IAX_ENCRYPT_AES128;
00993    else if (ast_true(s))
00994       e = IAX_ENCRYPT_AES128;
00995    else
00996       e = 0;
00997    return e;
00998 }

static int get_from_jb ( void *  p  )  [static]

Definition at line 2515 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02516 {
02517 #ifdef SCHED_MULTITHREADED
02518    if (schedule_action(__get_from_jb, data))
02519 #endif      
02520       __get_from_jb(data);
02521    return 0;
02522 }

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

Definition at line 6534 of file chan_iax2.c.

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

06535 {
06536    struct iax2_pkt_buf *pkt_buf;
06537 
06538    ast_mutex_lock(&thread->lock);
06539 
06540    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06541       ast_mutex_unlock(&thread->lock);
06542 
06543       thread->buf = pkt_buf->buf;
06544       thread->buf_len = pkt_buf->len;
06545       thread->buf_size = pkt_buf->len + 1;
06546       
06547       socket_process(thread);
06548 
06549       thread->buf = NULL;
06550       ast_free(pkt_buf);
06551 
06552       ast_mutex_lock(&thread->lock);
06553    }
06554 
06555    ast_mutex_unlock(&thread->lock);
06556 }

static int handle_error ( void   )  [static]

Definition at line 1798 of file chan_iax2.c.

References ast_inet_ntoa(), ast_log(), LOG_WARNING, and netsocket.

Referenced by send_packet(), socket_read(), and transmit_trunk().

01799 {
01800    /* XXX Ideally we should figure out why an error occured and then abort those
01801       rather than continuing to try.  Unfortunately, the published interface does
01802       not seem to work XXX */
01803 #if 0
01804    struct sockaddr_in *sin;
01805    int res;
01806    struct msghdr m;
01807    struct sock_extended_err e;
01808    m.msg_name = NULL;
01809    m.msg_namelen = 0;
01810    m.msg_iov = NULL;
01811    m.msg_control = &e;
01812    m.msg_controllen = sizeof(e);
01813    m.msg_flags = 0;
01814    res = recvmsg(netsocket, &m, MSG_ERRQUEUE);
01815    if (res < 0)
01816       ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno));
01817    else {
01818       if (m.msg_controllen) {
01819          sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e);
01820          if (sin) 
01821             ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr));
01822          else
01823             ast_log(LOG_WARNING, "No address detected??\n");
01824       } else {
01825          ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno));
01826       }
01827    }
01828 #endif
01829    return 0;
01830 }

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

Acknowledgment received for OUR registration.

Definition at line 5639 of file chan_iax2.c.

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

Referenced by socket_process().

05640 {
05641    struct iax2_registry *reg;
05642    /* Start pessimistic */
05643    char peer[256] = "";
05644    char msgstatus[60];
05645    int refresh = 60;
05646    char ourip[256] = "<Unspecified>";
05647    struct sockaddr_in oldus;
05648    struct sockaddr_in us;
05649    int oldmsgs;
05650 
05651    memset(&us, 0, sizeof(us));
05652    if (ies->apparent_addr)
05653       bcopy(ies->apparent_addr, &us, sizeof(us));
05654    if (ies->username)
05655       ast_copy_string(peer, ies->username, sizeof(peer));
05656    if (ies->refresh)
05657       refresh = ies->refresh;
05658    if (ies->calling_number) {
05659       /* We don't do anything with it really, but maybe we should */
05660    }
05661    reg = iaxs[callno]->reg;
05662    if (!reg) {
05663       ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer);
05664       return -1;
05665    }
05666    memcpy(&oldus, &reg->us, sizeof(oldus));
05667    oldmsgs = reg->messages;
05668    if (inaddrcmp(&reg->addr, sin)) {
05669       ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr));
05670       return -1;
05671    }
05672    memcpy(&reg->us, &us, sizeof(reg->us));
05673    if (ies->msgcount >= 0)
05674       reg->messages = ies->msgcount & 0xffff;      /* only low 16 bits are used in the transmission of the IE */
05675    /* always refresh the registration at the interval requested by the server
05676       we are registering to
05677    */
05678    reg->refresh = refresh;
05679    if (reg->expire > -1)
05680       ast_sched_del(sched, reg->expire);
05681    reg->expire = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
05682    if (inaddrcmp(&oldus, &reg->us) || (reg->messages != oldmsgs)) {
05683       if (option_verbose > 2) {
05684          if (reg->messages > 255)
05685             snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8);
05686          else if (reg->messages > 1)
05687             snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages);
05688          else if (reg->messages > 0)
05689             snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n");
05690          else
05691             snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n");
05692          snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
05693          ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus);
05694       }
05695       manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr));
05696    }
05697    reg->regstate = REG_STATE_REGISTERED;
05698    return 0;
05699 }

static int iax2_answer ( struct ast_channel c  )  [static]

Definition at line 3430 of file chan_iax2.c.

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

03431 {
03432    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03433    if (option_debug)
03434       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03435    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03436 }

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

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

03281 {
03282    struct ast_channel *cs[3];
03283    struct ast_channel *who, *other;
03284    int to = -1;
03285    int res = -1;
03286    int transferstarted=0;
03287    struct ast_frame *f;
03288    unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt);
03289    unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt);
03290    struct timeval waittimer = {0, 0}, tv;
03291 
03292    lock_both(callno0, callno1);
03293    if (!iaxs[callno0] || !iaxs[callno1]) {
03294       unlock_both(callno0, callno1);
03295       return AST_BRIDGE_FAILED;
03296    }
03297    /* Put them in native bridge mode */
03298    if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) {
03299       iaxs[callno0]->bridgecallno = callno1;
03300       iaxs[callno1]->bridgecallno = callno0;
03301    }
03302    unlock_both(callno0, callno1);
03303 
03304    /* If not, try to bridge until we can execute a transfer, if we can */
03305    cs[0] = c0;
03306    cs[1] = c1;
03307    for (/* ever */;;) {
03308       /* Check in case we got masqueraded into */
03309       if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) {
03310          if (option_verbose > 2)
03311             ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n");
03312          /* Remove from native mode */
03313          if (c0->tech == &iax2_tech) {
03314             ast_mutex_lock(&iaxsl[callno0]);
03315             iaxs[callno0]->bridgecallno = 0;
03316             ast_mutex_unlock(&iaxsl[callno0]);
03317          }
03318          if (c1->tech == &iax2_tech) {
03319             ast_mutex_lock(&iaxsl[callno1]);
03320             iaxs[callno1]->bridgecallno = 0;
03321             ast_mutex_unlock(&iaxsl[callno1]);
03322          }
03323          return AST_BRIDGE_FAILED_NOWARN;
03324       }
03325       if (c0->nativeformats != c1->nativeformats) {
03326          if (option_verbose > 2) {
03327             char buf0[255];
03328             char buf1[255];
03329             ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats);
03330             ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats);
03331             ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1);
03332          }
03333          /* Remove from native mode */
03334          lock_both(callno0, callno1);
03335          if (iaxs[callno0])
03336             iaxs[callno0]->bridgecallno = 0;
03337          if (iaxs[callno1])
03338             iaxs[callno1]->bridgecallno = 0;
03339          unlock_both(callno0, callno1);
03340          return AST_BRIDGE_FAILED_NOWARN;
03341       }
03342       /* check if transfered and if we really want native bridging */
03343       if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) {
03344          /* Try the transfer */
03345          if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) ||
03346                      ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA)))
03347             ast_log(LOG_WARNING, "Unable to start the transfer\n");
03348          transferstarted = 1;
03349       }
03350       if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) {
03351          /* Call has been transferred.  We're no longer involved */
03352          gettimeofday(&tv, NULL);
03353          if (ast_tvzero(waittimer)) {
03354             waittimer = tv;
03355          } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) {
03356             c0->_softhangup |= AST_SOFTHANGUP_DEV;
03357             c1->_softhangup |= AST_SOFTHANGUP_DEV;
03358             *fo = NULL;
03359             *rc = c0;
03360             res = AST_BRIDGE_COMPLETE;
03361             break;
03362          }
03363       }
03364       to = 1000;
03365       who = ast_waitfor_n(cs, 2, &to);
03366       if (timeoutms > -1) {
03367          timeoutms -= (1000 - to);
03368          if (timeoutms < 0)
03369             timeoutms = 0;
03370       }
03371       if (!who) {
03372          if (!timeoutms) {
03373             res = AST_BRIDGE_RETRY;
03374             break;
03375          }
03376          if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03377             res = AST_BRIDGE_FAILED;
03378             break;
03379          }
03380          continue;
03381       }
03382       f = ast_read(who);
03383       if (!f) {
03384          *fo = NULL;
03385          *rc = who;
03386          res = AST_BRIDGE_COMPLETE;
03387          break;
03388       }
03389       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03390          *fo = f;
03391          *rc = who;
03392          res =  AST_BRIDGE_COMPLETE;
03393          break;
03394       }
03395       other = (who == c0) ? c1 : c0;  /* the 'other' channel */
03396       if ((f->frametype == AST_FRAME_VOICE) ||
03397           (f->frametype == AST_FRAME_TEXT) ||
03398           (f->frametype == AST_FRAME_VIDEO) || 
03399           (f->frametype == AST_FRAME_IMAGE) ||
03400           (f->frametype == AST_FRAME_DTMF)) {
03401          /* monitored dtmf take out of the bridge.
03402           * check if we monitor the specific source.
03403           */
03404          int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1;
03405          if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) {
03406             *rc = who;
03407             *fo = f;
03408             res = AST_BRIDGE_COMPLETE;
03409             /* Remove from native mode */
03410             break;
03411          }
03412          /* everything else goes to the other side */
03413          ast_write(other, f);
03414       }
03415       ast_frfree(f);
03416       /* Swap who gets priority */
03417       cs[2] = cs[0];
03418       cs[0] = cs[1];
03419       cs[1] = cs[2];
03420    }
03421    lock_both(callno0, callno1);
03422    if(iaxs[callno0])
03423       iaxs[callno0]->bridgecallno = 0;
03424    if(iaxs[callno1])
03425       iaxs[callno1]->bridgecallno = 0;
03426    unlock_both(callno0, callno1);
03427    return res;
03428 }

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

Definition at line 3031 of file chan_iax2.c.

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

03032 {
03033    struct sockaddr_in sin;
03034    char *l=NULL, *n=NULL, *tmpstr;
03035    struct iax_ie_data ied;
03036    char *defaultrdest = "s";
03037    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03038    struct parsed_dial_string pds;
03039    struct create_addr_info cai;
03040 
03041    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
03042       ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name);
03043       return -1;
03044    }
03045 
03046    memset(&cai, 0, sizeof(cai));
03047    cai.encmethods = iax2_encryption;
03048 
03049    memset(&pds, 0, sizeof(pds));
03050    tmpstr = ast_strdupa(dest);
03051    parse_dial_string(tmpstr, &pds);
03052 
03053    if (!pds.exten)
03054       pds.exten = defaultrdest;
03055 
03056    if (create_addr(pds.peer, &sin, &cai)) {
03057       ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
03058       return -1;
03059    }
03060 
03061    if (!pds.username && !ast_strlen_zero(cai.username))
03062       pds.username = cai.username;
03063    if (!pds.password && !ast_strlen_zero(cai.secret))
03064       pds.password = cai.secret;
03065    if (!pds.key && !ast_strlen_zero(cai.outkey))
03066       pds.key = cai.outkey;
03067    if (!pds.context && !ast_strlen_zero(cai.peercontext))
03068       pds.context = cai.peercontext;
03069 
03070    /* Keep track of the context for outgoing calls too */
03071    ast_copy_string(c->context, cai.context, sizeof(c->context));
03072 
03073    if (pds.port)
03074       sin.sin_port = htons(atoi(pds.port));
03075 
03076    l = c->cid.cid_num;
03077    n = c->cid.cid_name;
03078 
03079    /* Now build request */ 
03080    memset(&ied, 0, sizeof(ied));
03081 
03082    /* On new call, first IE MUST be IAX version of caller */
03083    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
03084    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten);
03085    if (pds.options && strchr(pds.options, 'a')) {
03086       /* Request auto answer */
03087       iax_ie_append(&ied, IAX_IE_AUTOANSWER);
03088    }
03089 
03090    iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs);
03091 
03092    if (l) {
03093       iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
03094       iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03095    } else {
03096       if (n)
03097          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03098       else
03099          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
03100    }
03101 
03102    iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
03103    iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
03104 
03105    if (n)
03106       iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
03107    if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
03108       iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
03109 
03110    if (!ast_strlen_zero(c->language))
03111       iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
03112    if (!ast_strlen_zero(c->cid.cid_dnid))
03113       iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid);
03114    if (!ast_strlen_zero(c->cid.cid_rdnis))
03115       iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis);
03116 
03117    if (pds.context)
03118       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context);
03119 
03120    if (pds.username)
03121       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
03122 
03123    if (cai.encmethods)
03124       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods);
03125 
03126    ast_mutex_lock(&iaxsl[callno]);
03127 
03128    if (!ast_strlen_zero(c->context))
03129       ast_string_field_set(iaxs[callno], context, c->context);
03130 
03131    if (pds.username)
03132       ast_string_field_set(iaxs[callno], username, pds.username);
03133 
03134    iaxs[callno]->encmethods = cai.encmethods;
03135 
03136    iaxs[callno]->adsi = cai.adsi;
03137    
03138    ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret);
03139    ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest);
03140 
03141    if (pds.key)
03142       ast_string_field_set(iaxs[callno], outkey, pds.key);
03143    if (pds.password)
03144       ast_string_field_set(iaxs[callno], secret, pds.password);
03145 
03146    iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats);
03147    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability);
03148    iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe);
03149    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone));
03150 
03151    if (iaxs[callno]->maxtime) {
03152       /* Initialize pingtime and auto-congest time */
03153       iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2;
03154       iaxs[callno]->initid = ast_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno));
03155    } else if (autokill) {
03156       iaxs[callno]->pingtime = autokill / 2;
03157       iaxs[callno]->initid = ast_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno));
03158    }
03159 
03160    /* send the command using the appropriate socket for this peer */
03161    iaxs[callno]->sockfd = cai.sockfd;
03162 
03163    /* Transmit the string in a "NEW" request */
03164    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
03165 
03166    ast_mutex_unlock(&iaxsl[callno]);
03167    ast_setstate(c, AST_STATE_RINGING);
03168    
03169    return 0;
03170 }

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

10115 {
10116    int res = 0;
10117    struct iax2_dpcache *dp;
10118 #if 0
10119    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10120 #endif
10121    if ((priority != 1) && (priority != 2))
10122       return 0;
10123    ast_mutex_lock(&dpcache_lock);
10124    dp = find_cache(chan, data, context, exten, priority);
10125    if (dp) {
10126       if (dp->flags & CACHE_FLAG_CANEXIST)
10127          res= 1;
10128    }
10129    ast_mutex_unlock(&dpcache_lock);
10130    if (!dp) {
10131       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10132    }
10133    return res;
10134 }

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

Definition at line 2943 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

02944 {
02945    time_t t;
02946    struct tm tm;
02947    unsigned int tmp;
02948    time(&t);
02949    if (!ast_strlen_zero(tz))
02950       ast_localtime(&t, &tm, tz);
02951    else
02952       ast_localtime(&t, &tm, NULL);
02953    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
02954    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
02955    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
02956    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
02957    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
02958    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
02959    return tmp;
02960 }

static void iax2_destroy ( int  callno  )  [static]

Definition at line 1949 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), ast_set_flag, ast_string_field_free_pools, ast_variables_destroy(), iax2_registry::callno, chan_iax2_pvt::callno, iax_frame::callno, jb_frame::data, free, iax2_destroy_helper(), iax2_frame_free(), IAX_ALREADYGONE, iaxq, iaxs, iaxsl, chan_iax2_pvt::jb, jb_destroy(), jb_getall(), JB_OK, lastused, ast_channel::lock, LOG_NOTICE, chan_iax2_pvt::owner, chan_iax2_pvt::reg, iax_frame::retries, update_max_trunk(), and chan_iax2_pvt::vars.

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

01950 {
01951    struct chan_iax2_pvt *pvt;
01952    struct iax_frame *cur;
01953    struct ast_channel *owner;
01954 
01955 retry:
01956    pvt = iaxs[callno];
01957    gettimeofday(&lastused[callno], NULL);
01958    
01959    owner = pvt ? pvt->owner : NULL;
01960 
01961    if (owner) {
01962       if (ast_mutex_trylock(&owner->lock)) {
01963          ast_log(LOG_NOTICE, "Avoiding IAX destroy deadlock\n");
01964          ast_mutex_unlock(&iaxsl[callno]);
01965          usleep(1);
01966          ast_mutex_lock(&iaxsl[callno]);
01967          goto retry;
01968       }
01969    }
01970    if (!owner)
01971       iaxs[callno] = NULL;
01972    if (pvt) {
01973       if (!owner)
01974          pvt->owner = NULL;
01975       iax2_destroy_helper(pvt);
01976 
01977       /* Already gone */
01978       ast_set_flag(pvt, IAX_ALREADYGONE); 
01979 
01980       if (owner) {
01981          /* If there's an owner, prod it to give up */
01982          /* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup()
01983           * because we already hold the owner channel lock. */
01984          ast_queue_hangup(owner);
01985       }
01986 
01987       AST_LIST_LOCK(&iaxq.queue);
01988       AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
01989          /* Cancel any pending transmissions */
01990          if (cur->callno == pvt->callno) 
01991             cur->retries = -1;
01992       }
01993       AST_LIST_UNLOCK(&iaxq.queue);
01994 
01995       if (pvt->reg)
01996          pvt->reg->callno = 0;
01997       if (!owner) {
01998          jb_frame frame;
01999          if (pvt->vars) {
02000              ast_variables_destroy(pvt->vars);
02001              pvt->vars = NULL;
02002          }
02003 
02004          while (jb_getall(pvt->jb, &frame) == JB_OK)
02005             iax2_frame_free(frame.data);
02006          jb_destroy(pvt->jb);
02007          /* gotta free up the stringfields */
02008          ast_string_field_free_pools(pvt);
02009          free(pvt);
02010       }
02011    }
02012    if (owner) {
02013       ast_mutex_unlock(&owner->lock);
02014    }
02015    if (callno & 0x4000)
02016       update_max_trunk();
02017 }

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1886 of file chan_iax2.c.

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

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

01887 {
01888    /* Decrement AUTHREQ count if needed */
01889    if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
01890       struct iax2_user *user;
01891       struct iax2_user tmp_user = {
01892          .name = pvt->username,
01893       };
01894 
01895       user = ao2_find(users, &tmp_user, OBJ_POINTER);
01896       if (user) {
01897          ast_atomic_fetchadd_int(&user->curauthreq, -1);
01898          user_unref(user); 
01899       }
01900 
01901       ast_clear_flag(pvt, IAX_MAXAUTHREQ);
01902    }
01903    /* No more pings or lagrq's */
01904    if (pvt->pingid > -1)
01905       ast_sched_del(sched, pvt->pingid);
01906    pvt->pingid = -1;
01907    if (pvt->lagid > -1)
01908       ast_sched_del(sched, pvt->lagid);
01909    pvt->lagid = -1;
01910    if (pvt->autoid > -1)
01911       ast_sched_del(sched, pvt->autoid);
01912    pvt->autoid = -1;
01913    if (pvt->authid > -1)
01914       ast_sched_del(sched, pvt->authid);
01915    pvt->authid = -1;
01916    if (pvt->initid > -1)
01917       ast_sched_del(sched, pvt->initid);
01918    pvt->initid = -1;
01919    if (pvt->jbid > -1)
01920       ast_sched_del(sched, pvt->jbid);
01921    pvt->jbid = -1;
01922 }

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

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

10302 {
10303    struct parsed_dial_string pds;
10304    char *tmp = ast_strdupa(data);
10305    struct iax2_peer *p;
10306    int res = AST_DEVICE_INVALID;
10307 
10308    memset(&pds, 0, sizeof(pds));
10309    parse_dial_string(tmp, &pds);
10310    if (ast_strlen_zero(pds.peer))
10311       return res;
10312    
10313    if (option_debug > 2)
10314       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
10315 
10316    /* SLD: FIXME: second call to find_peer during registration */
10317    if (!(p = find_peer(pds.peer, 1)))
10318       return res;
10319 
10320    res = AST_DEVICE_UNAVAILABLE;
10321    if (option_debug > 2) 
10322       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
10323          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
10324    
10325    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
10326        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
10327       /* Peer is registered, or have default IP address
10328          and a valid registration */
10329       if (p->historicms == 0 || p->historicms <= p->maxms)
10330          /* let the core figure out whether it is in use or not */
10331          res = AST_DEVICE_UNKNOWN;  
10332    }
10333 
10334    peer_unref(p);
10335 
10336    return res;
10337 }

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

Definition at line 2633 of file chan_iax2.c.

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

02634 {
02635    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02636 }

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

Definition at line 2638 of file chan_iax2.c.

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

02639 {
02640    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02641 }

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

Definition at line 4691 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04692 {
04693    if (argc < 2 || argc > 3)
04694       return RESULT_SHOWUSAGE;
04695    iaxdebug = 1;
04696    ast_cli(fd, "IAX2 Debugging Enabled\n");
04697    return RESULT_SUCCESS;
04698 }

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

Definition at line 4709 of file chan_iax2.c.

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

04710 {
04711    if (argc < 3 || argc > 4)
04712       return RESULT_SHOWUSAGE;
04713    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04714    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04715    return RESULT_SUCCESS;
04716 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 8300 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_add(), ast_sched_del(), iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno(), iax2_destroy(), iax2_do_register_s(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, iaxsl, LOG_WARNING, NEW_FORCE, option_debug, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), and iax2_registry::username.

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

08301 {
08302    struct iax_ie_data ied;
08303    if (option_debug && iaxdebug)
08304       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
08305 
08306    if (reg->dnsmgr && 
08307        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
08308       /* Maybe the IP has changed, force DNS refresh */
08309       ast_dnsmgr_refresh(reg->dnsmgr);
08310    }
08311    
08312    /*
08313     * if IP has Changed, free allocated call to create a new one with new IP
08314     * call has the pointer to IP and must be updated to the new one
08315     */
08316    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
08317       ast_mutex_lock(&iaxsl[reg->callno]);
08318       iax2_destroy(reg->callno);
08319       ast_mutex_unlock(&iaxsl[reg->callno]);
08320       reg->callno = 0;
08321    }
08322    if (!reg->addr.sin_addr.s_addr) {
08323       if (option_debug && iaxdebug)
08324          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
08325       /* Setup the next registration attempt */
08326       if (reg->expire > -1)
08327          ast_sched_del(sched, reg->expire);
08328       reg->expire  = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08329       return -1;
08330    }
08331 
08332    if (!reg->callno) {
08333       if (option_debug)
08334          ast_log(LOG_DEBUG, "Allocate call number\n");
08335       reg->callno = find_callno(0, 0, &reg->addr, NEW_FORCE, defaultsockfd);
08336       if (reg->callno < 1) {
08337          ast_log(LOG_WARNING, "Unable to create call for registration\n");
08338          return -1;
08339       } else if (option_debug)
08340          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
08341       iaxs[reg->callno]->reg = reg;
08342    }
08343    /* Schedule the next registration attempt */
08344    if (reg->expire > -1)
08345       ast_sched_del(sched, reg->expire);
08346    /* Setup the next registration a little early */
08347    reg->expire  = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08348    /* Send the request */
08349    memset(&ied, 0, sizeof(ied));
08350    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
08351    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
08352    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
08353    reg->regstate = REG_STATE_REGSENT;
08354    return 0;
08355 }

static int iax2_do_register_s ( void *  data  )  [static]

Definition at line 5493 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05494 {
05495 #ifdef SCHED_MULTITHREADED
05496    if (schedule_action(__iax2_do_register_s, data))
05497 #endif      
05498       __iax2_do_register_s(data);
05499    return 0;
05500 }

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

Definition at line 4700 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04701 {
04702    if (argc < 3 || argc > 4)
04703       return RESULT_SHOWUSAGE;
04704    iaxtrunkdebug = 1;
04705    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04706    return RESULT_SUCCESS;
04707 }

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

Definition at line 6152 of file chan_iax2.c.

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

Referenced by find_cache(), and socket_process().

06153 {
06154    struct iax_ie_data ied;
06155    /* Auto-hangup with 30 seconds of inactivity */
06156    if (iaxs[callno]->autoid > -1)
06157       ast_sched_del(sched, iaxs[callno]->autoid);
06158    iaxs[callno]->autoid = ast_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06159    memset(&ied, 0, sizeof(ied));
06160    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06161    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06162    dp->flags |= CACHE_FLAG_TRANSMITTED;
06163 }

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

10161 {
10162    char odata[256];
10163    char req[256];
10164    char *ncontext;
10165    struct iax2_dpcache *dp;
10166    struct ast_app *dial;
10167 #if 0
10168    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);
10169 #endif
10170    if (priority == 2) {
10171       /* Indicate status, can be overridden in dialplan */
10172       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
10173       if (dialstatus) {
10174          dial = pbx_findapp(dialstatus);
10175          if (dial) 
10176             pbx_exec(chan, dial, "");
10177       }
10178       return -1;
10179    } else if (priority != 1)
10180       return -1;
10181    ast_mutex_lock(&dpcache_lock);
10182    dp = find_cache(chan, data, context, exten, priority);
10183    if (dp) {
10184       if (dp->flags & CACHE_FLAG_EXISTS) {
10185          ast_copy_string(odata, data, sizeof(odata));
10186          ncontext = strchr(odata, '/');
10187          if (ncontext) {
10188             *ncontext = '\0';
10189             ncontext++;
10190             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
10191          } else {
10192             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
10193          }
10194          if (option_verbose > 2)
10195             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
10196       } else {
10197          ast_mutex_unlock(&dpcache_lock);
10198          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
10199          return -1;
10200       }
10201    }
10202    ast_mutex_unlock(&dpcache_lock);
10203    dial = pbx_findapp("Dial");
10204    if (dial) {
10205       return pbx_exec(chan, dial, req);
10206    } else {
10207       ast_log(LOG_WARNING, "No dial application registered\n");
10208    }
10209    return -1;
10210 }

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

10092 {
10093    struct iax2_dpcache *dp;
10094    int res = 0;
10095 #if 0
10096    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10097 #endif
10098    if ((priority != 1) && (priority != 2))
10099       return 0;
10100    ast_mutex_lock(&dpcache_lock);
10101    dp = find_cache(chan, data, context, exten, priority);
10102    if (dp) {
10103       if (dp->flags & CACHE_FLAG_EXISTS)
10104          res= 1;
10105    }
10106    ast_mutex_unlock(&dpcache_lock);
10107    if (!dp) {
10108       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10109    }
10110    return res;
10111 }

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

Definition at line 2660 of file chan_iax2.c.

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

02661 {
02662    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02663    ast_mutex_lock(&iaxsl[callno]);
02664    if (iaxs[callno])
02665       iaxs[callno]->owner = newchan;
02666    else
02667       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02668    ast_mutex_unlock(&iaxsl[callno]);
02669    return 0;
02670 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

Definition at line 1410 of file chan_iax2.c.

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

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

01411 {
01412    if (fr->retrans > -1)
01413       ast_sched_del(sched, fr->retrans);
01414    iax_frame_free(fr);
01415 }

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

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

01142 {
01143    struct iax2_peer *peer = NULL;
01144    int res = 0;
01145    ao2_iterator i;
01146 
01147    i = ao2_iterator_init(peers, 0);
01148    while ((peer = ao2_iterator_next(&i))) {
01149       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
01150           (peer->addr.sin_port == sin.sin_port)) {
01151          ast_copy_string(host, peer->name, len);
01152          peer_unref(peer);
01153          res = 1;
01154          break;
01155       }
01156       peer_unref(peer);
01157    }
01158 
01159    if (!peer) {
01160       peer = realtime_peer(NULL, &sin);
01161       if (peer) {
01162          ast_copy_string(host, peer->name, len);
01163          peer_unref(peer);
01164          res = 1;
01165       }
01166    }
01167 
01168    return res;
01169 }

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

03493 {
03494    struct iax2_peer *peer;
03495    int res = 0;
03496    ao2_iterator i;
03497 
03498    i = ao2_iterator_init(peers, 0);
03499    while ((peer = ao2_iterator_next(&i))) {
03500       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03501           (peer->addr.sin_port == sin.sin_port)) {
03502          res = ast_test_flag(peer, IAX_TRUNK);
03503          peer_unref(peer);
03504          break;
03505       }
03506       peer_unref(peer);
03507    }
03508 
03509    return res;
03510 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 3172 of file chan_iax2.c.

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

03173 {
03174    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03175    int alreadygone;
03176    struct iax_ie_data ied;
03177    memset(&ied, 0, sizeof(ied));
03178    ast_mutex_lock(&iaxsl[callno]);
03179    if (callno && iaxs[callno]) {
03180       ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
03181       alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
03182       /* Send the hangup unless we have had a transmission error or are already gone */
03183       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
03184       if (!iaxs[callno]->error && !alreadygone) {
03185          send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
03186          if (!iaxs[callno]) {
03187             ast_mutex_unlock(&iaxsl[callno]);
03188             return 0;
03189          }
03190       }
03191       /* Explicitly predestroy it */
03192       iax2_predestroy(callno);
03193       /* If we were already gone to begin with, destroy us now */
03194       if (alreadygone && iaxs[callno]) {
03195          ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
03196          iax2_destroy(callno);
03197       }
03198    }
03199    ast_mutex_unlock(&iaxsl[callno]);
03200    if (option_verbose > 2) 
03201       ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
03202    return 0;
03203 }

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

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

03439 {
03440    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03441    struct chan_iax2_pvt *pvt;
03442    int res = 0;
03443 
03444    if (option_debug && iaxdebug)
03445       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03446 
03447    ast_mutex_lock(&iaxsl[callno]);
03448    pvt = iaxs[callno];
03449 
03450    switch (condition) {
03451    case AST_CONTROL_HOLD:
03452       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03453          ast_moh_start(c, data, pvt->mohinterpret);
03454          goto done;
03455       }
03456       break;
03457    case AST_CONTROL_UNHOLD:
03458       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03459          ast_moh_stop(c);
03460          goto done;
03461       }
03462    }
03463 
03464    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03465 
03466 done:
03467    ast_mutex_unlock(&iaxsl[callno]);
03468 
03469    return res;
03470 }

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

10138 {
10139    int res = 0;
10140    struct iax2_dpcache *dp;
10141 #if 0
10142    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10143 #endif
10144    if ((priority != 1) && (priority != 2))
10145       return 0;
10146    ast_mutex_lock(&dpcache_lock);
10147    dp = find_cache(chan, data, context, exten, priority);
10148    if (dp) {
10149       if (dp->flags & CACHE_FLAG_MATCHMORE)
10150          res= 1;
10151    }
10152    ast_mutex_unlock(&dpcache_lock);
10153    if (!dp) {
10154       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10155    }
10156    return res;
10157 }

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

Definition at line 4718 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04719 {
04720    if (argc < 3 || argc > 4)
04721       return RESULT_SHOWUSAGE;
04722    iaxdebug = 0;
04723    ast_cli(fd, "IAX2 Debugging Disabled\n");
04724    return RESULT_SUCCESS;
04725 }

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

Definition at line 4736 of file chan_iax2.c.

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

04737 {
04738    if (argc < 4 || argc > 5)
04739       return RESULT_SHOWUSAGE;
04740    jb_setoutput(jb_error_output, jb_warning_output, NULL);
04741    jb_debug_output("\n");
04742    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
04743    return RESULT_SUCCESS;
04744 }

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

Definition at line 4727 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04728 {
04729    if (argc < 4 || argc > 5)
04730       return RESULT_SHOWUSAGE;
04731    iaxtrunkdebug = 0;
04732    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
04733    return RESULT_SUCCESS;
04734 }

static int iax2_poke_noanswer ( void *  data  )  [static]

Definition at line 8496 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08497 {
08498    struct iax2_peer *peer = data;
08499    peer->pokeexpire = -1;
08500 #ifdef SCHED_MULTITHREADED
08501    if (schedule_action(__iax2_poke_noanswer, data))
08502 #endif      
08503       __iax2_poke_noanswer(data);
08504    return 0;
08505 }

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

Definition at line 8516 of file chan_iax2.c.

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

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

08517 {
08518    if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
08519       /* IF we have no IP, or this isn't to be monitored, return
08520         immediately after clearing things out */
08521       peer->lastms = 0;
08522       peer->historicms = 0;
08523       peer->pokeexpire = -1;
08524       peer->callno = 0;
08525       return 0;
08526    }
08527    if (peer->callno > 0) {
08528       ast_log(LOG_NOTICE, "Still have a callno...\n");
08529       ast_mutex_lock(&iaxsl[peer->callno]);
08530       iax2_destroy(peer->callno);
08531       ast_mutex_unlock(&iaxsl[peer->callno]);
08532    }
08533    if (heldcall)
08534       ast_mutex_unlock(&iaxsl[heldcall]);
08535    peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd);
08536    if (heldcall)
08537       ast_mutex_lock(&iaxsl[heldcall]);
08538    if (peer->callno < 1) {
08539       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
08540       return -1;
08541    }
08542 
08543    /* Speed up retransmission times for this qualify call */
08544    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
08545    iaxs[peer->callno]->peerpoke = peer;
08546    
08547    /* Remove any pending pokeexpire task */
08548    if (peer->pokeexpire > -1)
08549       ast_sched_del(sched, peer->pokeexpire);
08550 
08551    /* Queue up a new task to handle no reply */
08552    /* If the host is already unreachable then use the unreachable interval instead */
08553    if (peer->lastms < 0) {
08554       peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer);
08555    } else
08556       peer->pokeexpire = ast_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer);
08557 
08558    /* And send the poke */
08559    send_command(iaxs[peer->callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
08560 
08561    return 0;
08562 }

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

Definition at line 8507 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module(), and reload_config().

08508 {
08509    struct iax2_peer *peer = obj;
08510 
08511    iax2_poke_peer(peer, 0);
08512 
08513    return 0;
08514 }

static int iax2_poke_peer_s ( void *  data  )  [static]

Definition at line 6192 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

06193 {
06194    struct iax2_peer *peer = data;
06195    peer->pokeexpire = -1;
06196 #ifdef SCHED_MULTITHREADED
06197    if (schedule_action(__iax2_poke_peer_s, data))
06198 #endif      
06199       __iax2_poke_peer_s(data);
06200    return 0;
06201 }

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

01929 {
01930    struct ast_channel *c;
01931    struct chan_iax2_pvt *pvt = iaxs[callno];
01932 
01933    if (!pvt)
01934       return -1;
01935    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
01936       iax2_destroy_helper(pvt);
01937       ast_set_flag(pvt, IAX_ALREADYGONE); 
01938    }
01939    c = pvt->owner;
01940    if (c) {
01941       c->tech_pvt = NULL;
01942       iax2_queue_hangup(callno);
01943       pvt->owner = NULL;
01944       ast_module_unref(ast_module_info->self);
01945    }
01946    return 0;
01947 }

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

Definition at line 8187 of file chan_iax2.c.

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

Referenced by find_idle_thread(), and start_network_thread().

08188 {
08189    struct iax2_thread *thread = data;
08190    struct timeval tv;
08191    struct timespec ts;
08192    int put_into_idle = 0;
08193 
08194    ast_atomic_fetchadd_int(&iaxactivethreadcount,1);
08195    pthread_cleanup_push(iax2_process_thread_cleanup, data);
08196    for(;;) {
08197       /* Wait for something to signal us to be awake */
08198       ast_mutex_lock(&thread->lock);
08199 
08200       /* Flag that we're ready to accept signals */
08201       thread->ready_for_signal = 1;
08202       
08203       /* Put into idle list if applicable */
08204       if (put_into_idle)
08205          insert_idle_thread(thread);
08206 
08207       if (thread->type == IAX_TYPE_DYNAMIC) {
08208          struct iax2_thread *t = NULL;
08209          /* Wait to be signalled or time out */
08210          tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08211          ts.tv_sec = tv.tv_sec;
08212          ts.tv_nsec = tv.tv_usec * 1000;
08213          if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
08214             /* This thread was never put back into the available dynamic
08215              * thread list, so just go away. */
08216             if (!put_into_idle) {
08217                ast_mutex_unlock(&thread->lock);
08218                break;
08219             }
08220             AST_LIST_LOCK(&dynamic_list);
08221             /* Account for the case where this thread is acquired *right* after a timeout */
08222             if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list)))
08223                iaxdynamicthreadcount--;
08224             AST_LIST_UNLOCK(&dynamic_list);
08225             if (t) {
08226                /* This dynamic thread timed out waiting for a task and was
08227                 * not acquired immediately after the timeout, 
08228                 * so it's time to go away. */
08229                ast_mutex_unlock(&thread->lock);
08230                break;
08231             }
08232             /* Someone grabbed our thread *right* after we timed out.
08233              * Wait for them to set us up with something to do and signal
08234              * us to continue. */
08235             tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08236             ts.tv_sec = tv.tv_sec;
08237             ts.tv_nsec = tv.tv_usec * 1000;
08238             if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT)
08239             {
08240                ast_mutex_unlock(&thread->lock);
08241                break;
08242             }
08243          }
08244       } else {
08245          ast_cond_wait(&thread->cond, &thread->lock);
08246       }
08247 
08248       /* Go back into our respective list */
08249       put_into_idle = 1;
08250 
08251       ast_mutex_unlock(&thread->lock);
08252 
08253       if (thread->iostate == IAX_IOSTATE_IDLE)
08254          continue;
08255 
08256       /* Add ourselves to the active list now */
08257       AST_LIST_LOCK(&active_list);
08258       AST_LIST_INSERT_HEAD(&active_list, thread, list);
08259       AST_LIST_UNLOCK(&active_list);
08260 
08261       /* See what we need to do */
08262       switch(thread->iostate) {
08263       case IAX_IOSTATE_READY:
08264          thread->actions++;
08265          thread->iostate = IAX_IOSTATE_PROCESSING;
08266          socket_process(thread);
08267          handle_deferred_full_frames(thread);
08268          break;
08269       case IAX_IOSTATE_SCHEDREADY:
08270          thread->actions++;
08271          thread->iostate = IAX_IOSTATE_PROCESSING;
08272 #ifdef SCHED_MULTITHREADED
08273          thread->schedfunc(thread->scheddata);
08274 #endif      
08275          break;
08276       }
08277       time(&thread->checktime);
08278       thread->iostate = IAX_IOSTATE_IDLE;
08279 #ifdef DEBUG_SCHED_MULTITHREAD
08280       thread->curfunc[0]='\0';
08281 #endif      
08282 
08283       /* Now... remove ourselves from the active list, and return to the idle list */
08284       AST_LIST_LOCK(&active_list);
08285       AST_LIST_REMOVE(&active_list, thread, list);
08286       AST_LIST_UNLOCK(&active_list);
08287 
08288       /* Make sure another frame didn't sneak in there after we thought we were done. */
08289       handle_deferred_full_frames(thread);
08290    }
08291 
08292    /* I am exiting here on my own volition, I need to clean up my own data structures
08293    * Assume that I am no longer in any of the lists (idle, active, or dynamic)
08294    */
08295    pthread_cleanup_pop(1);
08296 
08297    return NULL;
08298 }

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8178 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08179 {
08180    struct iax2_thread *thread = data;
08181    ast_mutex_destroy(&thread->lock);
08182    ast_cond_destroy(&thread->cond);
08183    free(thread);
08184    ast_atomic_dec_and_test(&iaxactivethreadcount);
08185 }

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

Definition at line 8455 of file chan_iax2.c.

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

08456 {
08457    int force = 0;
08458    int res;
08459    if (argc < 4)
08460       return RESULT_SHOWUSAGE;
08461    if ((argc > 4)) {
08462       if (!strcasecmp(argv[4], "forced"))
08463          force = 1;
08464       else
08465          return RESULT_SHOWUSAGE;
08466    }
08467    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08468    if (res < 0)
08469       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08470    else if (res < 1)
08471       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08472    else
08473       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08474    return RESULT_SUCCESS;
08475 }

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

Definition at line 8357 of file chan_iax2.c.

References iax_prov_complete_template().

08358 {
08359    if (pos != 3)
08360       return NULL;
08361    return iax_prov_complete_template(line, word, pos, state);
08362 }

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

Definition at line 8364 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), ast_set_flag, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, create_addr(), find_callno(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), iaxs, iaxsl, NEW_FORCE, option_debug, iax_ie_data::pos, sched, and send_command().

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

08365 {
08366    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
08367       is found for template */
08368    struct iax_ie_data provdata;
08369    struct iax_ie_data ied;
08370    unsigned int sig;
08371    struct sockaddr_in sin;
08372    int callno;
08373    struct create_addr_info cai;
08374 
08375    memset(&cai, 0, sizeof(cai));
08376 
08377    if (option_debug)
08378       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
08379 
08380    if (iax_provision_build(&provdata, &sig, template, force)) {
08381       ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
08382       return 0;
08383    }
08384 
08385    if (end) {
08386       memcpy(&sin, end, sizeof(sin));
08387       cai.sockfd = sockfd;
08388    } else if (create_addr(dest, &sin, &cai))
08389       return -1;
08390 
08391    /* Build the rest of the message */
08392    memset(&ied, 0, sizeof(ied));
08393    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
08394 
08395    callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
08396    if (!callno)
08397       return -1;
08398 
08399    ast_mutex_lock(&iaxsl[callno]);
08400    if (iaxs[callno]) {
08401       /* Schedule autodestruct in case they don't ever give us anything back */
08402       if (iaxs[callno]->autoid > -1)
08403          ast_sched_del(sched, iaxs[callno]->autoid);
08404       iaxs[callno]->autoid = ast_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
08405       ast_set_flag(iaxs[callno], IAX_PROVISION);
08406       /* Got a call number now, so go ahead and send the provisioning information */
08407       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
08408    }
08409    ast_mutex_unlock(&iaxsl[callno]);
08410 
08411    return 1;
08412 }

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

Definition at line 2122 of file chan_iax2.c.

References ast_cli(), ast_set_flag, ast_test_flag, expire_registry(), find_peer(), IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, peer_unref(), reload_config(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02123 {
02124    struct iax2_peer *peer;
02125 
02126    if (argc != 4)
02127         return RESULT_SHOWUSAGE;
02128    if (!strcmp(argv[3],"all")) {
02129       reload_config();
02130       ast_cli(fd, "OK cache is flushed.\n");
02131    } else if ((peer = find_peer(argv[3], 0))) {
02132       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
02133          ast_set_flag(peer, IAX_RTAUTOCLEAR);
02134          expire_registry((void *)peer->name);
02135          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
02136       } else {
02137          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
02138       }
02139       peer_unref(peer);
02140    } else {
02141       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
02142    }
02143    
02144    return RESULT_SUCCESS;
02145 }

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

References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_control_data(), iaxs, and iaxsl.

Referenced by socket_process().

01495 {
01496    for (;;) {
01497       if (iaxs[callno] && iaxs[callno]->owner) {
01498          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01499             /* Avoid deadlock by pausing and trying again */
01500             ast_mutex_unlock(&iaxsl[callno]);
01501             usleep(1);
01502             ast_mutex_lock(&iaxsl[callno]);
01503          } else {
01504             ast_queue_control_data(iaxs[callno]->owner, control, data, datalen);
01505             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01506             break;
01507          }
01508       } else
01509          break;
01510    }
01511    return 0;
01512 }

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

References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), f, iaxs, and iaxsl.

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

01428 {
01429    for (;;) {
01430       if (iaxs[callno] && iaxs[callno]->owner) {
01431          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01432             /* Avoid deadlock by pausing and trying again */
01433             ast_mutex_unlock(&iaxsl[callno]);
01434             usleep(1);
01435             ast_mutex_lock(&iaxsl[callno]);
01436          } else {
01437             ast_queue_frame(iaxs[callno]->owner, f);
01438             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01439             break;
01440          }
01441       } else
01442          break;
01443    }
01444    return 0;
01445 }

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

References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), iaxs, and iaxsl.

Referenced by iax2_predestroy().

01461 {
01462    for (;;) {
01463       if (iaxs[callno] && iaxs[callno]->owner) {
01464          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01465             /* Avoid deadlock by pausing and trying again */
01466             ast_mutex_unlock(&iaxsl[callno]);
01467             usleep(1);
01468             ast_mutex_lock(&iaxsl[callno]);
01469          } else {
01470             ast_queue_hangup(iaxs[callno]->owner);
01471             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01472             break;
01473          }
01474       } else
01475          break;
01476    }
01477    return 0;
01478 }

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

Definition at line 3231 of file chan_iax2.c.

References ast_log(), ast_null_frame, and LOG_NOTICE.

03232 {
03233    ast_log(LOG_NOTICE, "I should never be called!\n");
03234    return &ast_null_frame;
03235 }

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

Definition at line 5701 of file chan_iax2.c.

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

Referenced by set_config().

05702 {
05703    struct iax2_registry *reg;
05704    char copy[256];
05705    char *username, *hostname, *secret;
05706    char *porta;
05707    char *stringp=NULL;
05708    
05709    if (!value)
05710       return -1;
05711    ast_copy_string(copy, value, sizeof(copy));
05712    stringp=copy;
05713    username = strsep(&stringp, "@");
05714    hostname = strsep(&stringp, "@");
05715    if (!hostname) {
05716       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
05717       return -1;
05718    }
05719    stringp=username;
05720    username = strsep(&stringp, ":");
05721    secret = strsep(&stringp, ":");
05722    stringp=hostname;
05723    hostname = strsep(&stringp, ":");
05724    porta = strsep(&stringp, ":");
05725    
05726    if (porta && !atoi(porta)) {
05727       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
05728       return -1;
05729    }
05730    if (!(reg = ast_calloc(1, sizeof(*reg))))
05731       return -1;
05732    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
05733       free(reg);
05734       return -1;
05735    }
05736    ast_copy_string(reg->username, username, sizeof(reg->username));
05737    if (secret)
05738       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
05739    reg->expire = -1;
05740    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
05741    reg->addr.sin_family = AF_INET;
05742    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
05743    AST_LIST_LOCK(&registrations);
05744    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
05745    AST_LIST_UNLOCK(&registrations);
05746    
05747    return 0;
05748 }

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

Definition at line 9865 of file chan_iax2.c.

References reload_config().

09866 {
09867    return reload_config();
09868 }

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

Definition at line 8574 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_lock(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strdupa, ast_string_field_set, ast_test_flag, ast_translator_best_choice(), create_addr(), find_callno(), fmt, globalflags, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iaxsl, LOG_WARNING, make_trunk(), chan_iax2_pvt::maxtime, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), ast_channel::readformat, and ast_channel::writeformat.

08575 {
08576    int callno;
08577    int res;
08578    int fmt, native;
08579    struct sockaddr_in sin;
08580    struct ast_channel *c;
08581    struct parsed_dial_string pds;
08582    struct create_addr_info cai;
08583    char *tmpstr;
08584 
08585    memset(&pds, 0, sizeof(pds));
08586    tmpstr = ast_strdupa(data);
08587    parse_dial_string(tmpstr, &pds);
08588 
08589    memset(&cai, 0, sizeof(cai));
08590    cai.capability = iax2_capability;
08591 
08592    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08593 
08594    if (!pds.peer) {
08595       ast_log(LOG_WARNING, "No peer given\n");
08596       return NULL;
08597    }
08598           
08599    
08600    /* Populate our address from the given */
08601    if (create_addr(pds.peer, &sin, &cai)) {
08602       *cause = AST_CAUSE_UNREGISTERED;
08603       return NULL;
08604    }
08605 
08606    if (pds.port)
08607       sin.sin_port = htons(atoi(pds.port));
08608 
08609    callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
08610    if (callno < 1) {
08611       ast_log(LOG_WARNING, "Unable to create call\n");
08612       *cause = AST_CAUSE_CONGESTION;
08613       return NULL;
08614    }
08615 
08616    ast_mutex_lock(&iaxsl[callno]);
08617 
08618    /* If this is a trunk, update it now */
08619    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
08620    if (ast_test_flag(&cai, IAX_TRUNK)) {
08621       int new_callno;
08622       if ((new_callno = make_trunk(callno, 1)) != -1)
08623          callno = new_callno;
08624    }
08625    iaxs[callno]->maxtime = cai.maxtime;
08626    if (cai.found)
08627       ast_string_field_set(iaxs[callno], host, pds.peer);
08628 
08629    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
08630 
08631    ast_mutex_unlock(&iaxsl[callno]);
08632 
08633    if (c) {
08634       /* Choose a format we can live with */
08635       if (c->nativeformats & format) 
08636          c->nativeformats &= format;
08637       else {
08638          native = c->nativeformats;
08639          fmt = format;
08640          res = ast_translator_best_choice(&fmt, &native);
08641          if (res < 0) {
08642             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
08643                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
08644             ast_hangup(c);
08645             return NULL;
08646          }
08647          c->nativeformats = native;
08648       }
08649       c->readformat = ast_best_codec(c->nativeformats);
08650       c->writeformat = c->readformat;
08651    }
08652 
08653    return c;
08654 }

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

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

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

04041 {
04042    /* Queue a packet for delivery on a given private structure.  Use "ts" for
04043       timestamp, or calculate if ts is 0.  Send immediately without retransmission
04044       or delayed, with retransmission */
04045    struct ast_iax2_full_hdr *fh;
04046    struct ast_iax2_mini_hdr *mh;
04047    struct ast_iax2_video_hdr *vh;
04048    struct {
04049       struct iax_frame fr2;
04050       unsigned char buffer[4096];
04051    } frb;
04052    struct iax_frame *fr;
04053    int res;
04054    int sendmini=0;
04055    unsigned int lastsent;
04056    unsigned int fts;
04057 
04058    frb.fr2.afdatalen = sizeof(frb.buffer);
04059 
04060    if (!pvt) {
04061       ast_log(LOG_WARNING, "No private structure for packet?\n");
04062       return -1;
04063    }
04064    
04065    lastsent = pvt->lastsent;
04066 
04067    /* Calculate actual timestamp */
04068    fts = calc_timestamp(pvt, ts, f);
04069 
04070    /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out
04071     * (the endpoint should detect the lost packet itself).  But, we want to do this here, so that we
04072     * increment the "predicted timestamps" for voice, if we're predecting */
04073    if(f->frametype == AST_FRAME_VOICE && f->datalen == 0)
04074        return 0;
04075 
04076 
04077    if ((ast_test_flag(pvt, IAX_TRUNK) || 
04078          (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) ||
04079          ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L))))
04080       /* High two bytes are the same on timestamp, or sending on a trunk */ &&
04081        (f->frametype == AST_FRAME_VOICE) 
04082       /* is a voice frame */ &&
04083       (f->subclass == pvt->svoiceformat) 
04084       /* is the same type */ ) {
04085          /* Force immediate rather than delayed transmission */
04086          now = 1;
04087          /* Mark that mini-style frame is appropriate */
04088          sendmini = 1;
04089    }
04090    if (((fts & 0xFFFF8000L) == (lastsent & 0xFFFF8000L)) && 
04091       (f->frametype == AST_FRAME_VIDEO) &&
04092       ((f->subclass & ~0x1) == pvt->svideoformat)) {
04093          now = 1;
04094          sendmini = 1;
04095    }
04096    /* Allocate an iax_frame */
04097    if (now) {
04098       fr = &frb.fr2;
04099    } else
04100       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));
04101    if (!fr) {
04102       ast_log(LOG_WARNING, "Out of memory\n");
04103       return -1;
04104    }
04105    /* Copy our prospective frame into our immediate or retransmitted wrapper */
04106    iax_frame_wrap(fr, f);
04107 
04108    fr->ts = fts;
04109    fr->callno = pvt->callno;
04110    fr->transfer = transfer;
04111    fr->final = final;
04112    if (!sendmini) {
04113       /* We need a full frame */
04114       if (seqno > -1)
04115          fr->oseqno = seqno;
04116       else
04117          fr->oseqno = pvt->oseqno++;
04118       fr->iseqno = pvt->iseqno;
04119       fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr));
04120       fh->scallno = htons(fr->callno | IAX_FLAG_FULL);
04121       fh->ts = htonl(fr->ts);
04122       fh->oseqno = fr->oseqno;
04123       if (transfer) {
04124          fh->iseqno = 0;
04125       } else
04126          fh->iseqno = fr->iseqno;
04127       /* Keep track of the last thing we've acknowledged */
04128       if (!transfer)
04129          pvt->aseqno = fr->iseqno;
04130       fh->type = fr->af.frametype & 0xFF;
04131       if (fr->af.frametype == AST_FRAME_VIDEO)
04132          fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6);
04133       else
04134          fh->csub = compress_subclass(fr->af.subclass);
04135       if (transfer) {
04136          fr->dcallno = pvt->transfercallno;
04137       } else
04138          fr->dcallno = pvt->peercallno;
04139       fh->dcallno = htons(fr->dcallno);
04140       fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr);
04141       fr->data = fh;
04142       fr->retries = 0;
04143       /* Retry after 2x the ping time has passed */
04144       fr->retrytime = pvt->pingtime * 2;
04145       if (fr->retrytime < MIN_RETRY_TIME)
04146          fr->retrytime = MIN_RETRY_TIME;
04147       if (fr->retrytime > MAX_RETRY_TIME)
04148          fr->retrytime = MAX_RETRY_TIME;
04149       /* Acks' don't get retried */
04150       if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK))
04151          fr->retries = -1;
04152       else if (f->frametype == AST_FRAME_VOICE)
04153          pvt->svoiceformat = f->subclass;
04154       else if (f->frametype == AST_FRAME_VIDEO)
04155          pvt->svideoformat = f->subclass & ~0x1;
04156       if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04157          if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04158             if (iaxdebug) {
04159                if (fr->transfer)
04160                   iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr));
04161                else
04162                   iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr));
04163             }
04164             encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen);
04165          } else
04166             ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04167       }
04168    
04169       if (now) {
04170          res = send_packet(fr);
04171       } else
04172          res = iax2_transmit(fr);
04173    } else {
04174       if (ast_test_flag(pvt, IAX_TRUNK)) {
04175          iax2_trunk_queue(pvt, fr);
04176          res = 0;
04177       } else if (fr->af.frametype == AST_FRAME_VIDEO) {
04178          /* Video frame have no sequence number */
04179          fr->oseqno = -1;
04180          fr->iseqno = -1;
04181          vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr));
04182          vh->zeros = 0;
04183          vh->callno = htons(0x8000 | fr->callno);
04184          vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0));
04185          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);
04186          fr->data = vh;
04187          fr->retries = -1;
04188          res = send_packet(fr);        
04189       } else {
04190          /* Mini-frames have no sequence number */
04191          fr->oseqno = -1;
04192          fr->iseqno = -1;
04193          /* Mini frame will do */
04194          mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr));
04195          mh->callno = htons(fr->callno);
04196          mh->ts = htons(fr->ts & 0xFFFF);
04197          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);
04198          fr->data = mh;
04199          fr->retries = -1;
04200          if (pvt->transferring == TRANSFER_MEDIAPASS)
04201             fr->transfer = 1;
04202          if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04203             if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04204                encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen);
04205             } else
04206                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04207          }
04208          res = send_packet(fr);
04209       }
04210    }
04211    return res;
04212 }

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

Definition at line 2655 of file chan_iax2.c.

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

02656 {
02657    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02658 }

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

Definition at line 2650 of file chan_iax2.c.

References AST_FRAME_IMAGE, ast_frame::data, ast_frame::datalen, PTR_TO_CALLNO, send_command_locked(), ast_frame::subclass, and ast_channel::tech_pvt.

02651 {
02652    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
02653 }

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

Definition at line 2643 of file chan_iax2.c.

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

02644 {
02645    
02646    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02647       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02648 }

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

Definition at line 3205 of file chan_iax2.c.

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

03206 {
03207    struct ast_option_header *h;
03208    int res;
03209 
03210    switch (option) {
03211    case AST_OPTION_TXGAIN:
03212    case AST_OPTION_RXGAIN:
03213       /* these two cannot be sent, because they require a result */
03214       errno = ENOSYS;
03215       return -1;
03216    default:
03217       if (!(h = ast_malloc(datalen + sizeof(*h))))
03218          return -1;
03219 
03220       h->flag = AST_OPTION_FLAG_REQUEST;
03221       h->option = htons(option);
03222       memcpy(h->data, data, datalen);
03223       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03224                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03225                  datalen + sizeof(*h), -1);
03226       free(h);
03227       return res;
03228    }
03229 }

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

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

02327 {
02328    struct iax2_dpcache *dp;
02329    char tmp[1024], *pc;
02330    int s;
02331    int x,y;
02332    struct timeval tv;
02333    gettimeofday(&tv, NULL);
02334    ast_mutex_lock(&dpcache_lock);
02335    dp = dpcache;
02336    ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02337    while(dp) {
02338       s = dp->expiry.tv_sec - tv.tv_sec;
02339       tmp[0] = '\0';
02340       if (dp->flags & CACHE_FLAG_EXISTS)
02341          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02342       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02343          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02344       if (dp->flags & CACHE_FLAG_CANEXIST)
02345          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02346       if (dp->flags & CACHE_FLAG_PENDING)
02347          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02348       if (dp->flags & CACHE_FLAG_TIMEOUT)
02349          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02350       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02351          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02352       if (dp->flags & CACHE_FLAG_MATCHMORE)
02353          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02354       if (dp->flags & CACHE_FLAG_UNKNOWN)
02355          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02356       /* Trim trailing pipe */
02357       if (!ast_strlen_zero(tmp))
02358          tmp[strlen(tmp) - 1] = '\0';
02359       else
02360          ast_copy_string(tmp, "(none)", sizeof(tmp));
02361       y=0;
02362       pc = strchr(dp->peercontext, '@');
02363       if (!pc)
02364          pc = dp->peercontext;
02365       else
02366          pc++;
02367       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
02368          if (dp->waiters[x] > -1)
02369             y++;
02370       if (s > 0)
02371          ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02372       else
02373          ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02374       dp = dp->next;
02375    }
02376    ast_mutex_unlock(&dpcache_lock);
02377    return RESULT_SUCCESS;
02378 }

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

Definition at line 4556 of file chan_iax2.c.

References 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_MAX_CALLS, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), jb_info::jitter, jb_info::min, chan_iax2_pvt::remote_rr, RESULT_SHOWUSAGE, RESULT_SUCCESS, and S_OR.

04557 {
04558 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04559 #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"
04560 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04561    int x;
04562    int numchans = 0;
04563 
04564    if (argc != 3)
04565       return RESULT_SHOWUSAGE;
04566    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04567    for (x=0;x<IAX_MAX_CALLS;x++) {
04568       ast_mutex_lock(&iaxsl[x]);
04569       if (iaxs[x]) {
04570          int lag, jitter, localdelay;
04571          jb_info jbinfo;
04572          
04573          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04574             jb_getinfo(iaxs[x]->jb, &jbinfo);
04575             jitter = jbinfo.jitter;
04576             localdelay = jbinfo.current - jbinfo.min;
04577          } else {
04578             jitter = -1;
04579             localdelay = 0;
04580          }
04581          lag = iaxs[x]->remote_rr.delay;
04582          ast_cli(fd, FORMAT,
04583             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04584             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04585             S_OR(iaxs[x]->username, "(None)"),
04586             iaxs[x]->callno, iaxs[x]->peercallno,
04587             iaxs[x]->oseqno, iaxs[x]->iseqno,
04588             lag,
04589             jitter,
04590             localdelay,
04591             ast_getformatname(iaxs[x]->voiceformat) );
04592          numchans++;
04593       }
04594       ast_mutex_unlock(&iaxsl[x]);
04595    }
04596    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04597    return RESULT_SUCCESS;
04598 #undef FORMAT
04599 #undef FORMAT2
04600 #undef FORMATB
04601 }

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

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

04468 {
04469 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04470 #if !defined(__FreeBSD__)
04471 #define FORMAT "%-15.15s  %-15d %-15d\n"
04472 #else /* __FreeBSD__ */
04473 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04474 #endif /* __FreeBSD__ */
04475    struct iax_firmware *cur;
04476    if ((argc != 3) && (argc != 4))
04477       return RESULT_SHOWUSAGE;
04478    ast_mutex_lock(&waresl.lock);
04479    
04480    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04481    for (cur = waresl.wares;cur;cur = cur->next) {
04482       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04483          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04484             (int)ntohl(cur->fwh->datalen));
04485    }
04486    ast_mutex_unlock(&waresl.lock);
04487    return RESULT_SUCCESS;
04488 #undef FORMAT
04489 #undef FORMAT2
04490 }

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

Definition at line 4679 of file chan_iax2.c.

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

04680 {
04681    int numchans = 0;
04682    if (argc != 3)
04683       return RESULT_SHOWUSAGE;
04684    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04685    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04686    numchans = ast_cli_netstats(NULL, fd, 1);
04687    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04688    return RESULT_SUCCESS;
04689 }

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

Show one peer in detail.

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

02217 {
02218    char status[30];
02219    char cbuf[256];
02220    struct iax2_peer *peer;
02221    char codec_buf[512];
02222    int x = 0, codec = 0, load_realtime = 0;
02223 
02224    if (argc < 4)
02225       return RESULT_SHOWUSAGE;
02226 
02227    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0;
02228 
02229    peer = find_peer(argv[3], load_realtime);
02230    if (peer) {
02231       ast_cli(fd,"\n\n");
02232       ast_cli(fd, "  * Name       : %s\n", peer->name);
02233       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
02234       ast_cli(fd, "  Context      : %s\n", peer->context);
02235       ast_cli(fd, "  Mailbox      : %s\n", peer->mailbox);
02236       ast_cli(fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No");
02237       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
02238       ast_cli(fd, "  Expire       : %d\n", peer->expire);
02239       ast_cli(fd, "  ACL          : %s\n", (peer->ha?"Yes":"No"));
02240       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));
02241       ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
02242       ast_cli(fd, "  Username     : %s\n", peer->username);
02243       ast_cli(fd, "  Codecs       : ");
02244       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
02245       ast_cli(fd, "%s\n", codec_buf);
02246 
02247       ast_cli(fd, "  Codec Order  : (");
02248       for(x = 0; x < 32 ; x++) {
02249          codec = ast_codec_pref_index(&peer->prefs,x);
02250          if(!codec)
02251             break;
02252          ast_cli(fd, "%s", ast_getformatname(codec));
02253          if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1))
02254             ast_cli(fd, "|");
02255       }
02256 
02257       if (!x)
02258          ast_cli(fd, "none");
02259       ast_cli(fd, ")\n");
02260 
02261       ast_cli(fd, "  Status       : ");
02262       peer_status(peer, status, sizeof(status));   
02263       ast_cli(fd, "%s\n",status);
02264       ast_cli(fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
02265       ast_cli(fd,"\n");
02266       peer_unref(peer);
02267    } else {
02268       ast_cli(fd,"Peer %s not found.\n", argv[3]);
02269       ast_cli(fd,"\n");
02270    }
02271 
02272    return RESULT_SUCCESS;
02273 }

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

Definition at line 4456 of file chan_iax2.c.

References __iax2_show_peers().

04457 {
04458    return __iax2_show_peers(0, fd, NULL, argc, argv);
04459 }

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

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

04529 {
04530 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04531 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04532    struct iax2_registry *reg = NULL;
04533 
04534    char host[80];
04535    char perceived[80];
04536    if (argc != 3)
04537       return RESULT_SHOWUSAGE;
04538    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04539    AST_LIST_LOCK(&registrations);
04540    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04541       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04542       if (reg->us.sin_addr.s_addr) 
04543          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04544       else
04545          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04546       ast_cli(fd, FORMAT, host, 
04547                (reg->dnsmgr) ? "Y" : "N", 
04548                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04549    }
04550    AST_LIST_UNLOCK(&registrations);
04551    return RESULT_SUCCESS;
04552 #undef FORMAT
04553 #undef FORMAT2
04554 }

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

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

02301 {
02302    struct iax_frame *cur;
02303    int cnt = 0, dead=0, final=0;
02304 
02305    if (argc != 3)
02306       return RESULT_SHOWUSAGE;
02307 
02308    AST_LIST_LOCK(&iaxq.queue);
02309    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02310       if (cur->retries < 0)
02311          dead++;
02312       if (cur->final)
02313          final++;
02314       cnt++;
02315    }
02316    AST_LIST_UNLOCK(&iaxq.queue);
02317 
02318    ast_cli(fd, "    IAX Statistics\n");
02319    ast_cli(fd, "---------------------\n");
02320    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02321    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02322    
02323    return RESULT_SUCCESS;
02324 }

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

Definition at line 4397 of file chan_iax2.c.

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

04398 {
04399    struct iax2_thread *thread = NULL;
04400    time_t t;
04401    int threadcount = 0, dynamiccount = 0;
04402    char type;
04403 
04404    if (argc != 3)
04405       return RESULT_SHOWUSAGE;
04406       
04407    ast_cli(fd, "IAX2 Thread Information\n");
04408    time(&t);
04409    ast_cli(fd, "Idle Threads:\n");
04410    AST_LIST_LOCK(&idle_list);
04411    AST_LIST_TRAVERSE(&idle_list, thread, list) {
04412 #ifdef DEBUG_SCHED_MULTITHREAD
04413       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04414          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04415 #else
04416       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
04417          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04418 #endif
04419       threadcount++;
04420    }
04421    AST_LIST_UNLOCK(&idle_list);
04422    ast_cli(fd, "Active Threads:\n");
04423    AST_LIST_LOCK(&active_list);
04424    AST_LIST_TRAVERSE(&active_list, thread, list) {
04425       if (thread->type == IAX_TYPE_DYNAMIC)
04426          type = 'D';
04427       else
04428          type = 'P';
04429 #ifdef DEBUG_SCHED_MULTITHREAD
04430       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04431          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04432 #else
04433       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04434          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04435 #endif
04436       threadcount++;
04437    }
04438    AST_LIST_UNLOCK(&active_list);
04439    ast_cli(fd, "Dynamic Threads:\n");
04440         AST_LIST_LOCK(&dynamic_list);
04441         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04442 #ifdef DEBUG_SCHED_MULTITHREAD
04443                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04444                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04445 #else
04446                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04447                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04448 #endif
04449       dynamiccount++;
04450         }
04451         AST_LIST_UNLOCK(&dynamic_list);
04452    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04453    return RESULT_SUCCESS;
04454 }

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

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

04215 {
04216    regex_t regexbuf;
04217    int havepattern = 0;
04218 
04219 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
04220 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
04221 
04222    struct iax2_user *user = NULL;
04223    char auth[90];
04224    char *pstr = "";
04225    ao2_iterator i;
04226 
04227    switch (argc) {
04228    case 5:
04229       if (!strcasecmp(argv[3], "like")) {
04230          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04231             return RESULT_SHOWUSAGE;
04232          havepattern = 1;
04233       } else
04234          return RESULT_SHOWUSAGE;
04235    case 3:
04236       break;
04237    default:
04238       return RESULT_SHOWUSAGE;
04239    }
04240 
04241    ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
04242    i = ao2_iterator_init(users, 0);
04243    for (user = ao2_iterator_next(&i); user; 
04244       user_unref(user), user = ao2_iterator_next(&i)) {
04245       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
04246          continue;
04247       
04248       if (!ast_strlen_zero(user->secret)) {
04249          ast_copy_string(auth,user->secret,sizeof(auth));
04250       } else if (!ast_strlen_zero(user->inkeys)) {
04251          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
04252       } else
04253          ast_copy_string(auth, "-no secret-", sizeof(auth));
04254       
04255       if(ast_test_flag(user,IAX_CODEC_NOCAP))
04256          pstr = "REQ Only";
04257       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
04258          pstr = "Disabled";
04259       else
04260          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
04261       
04262       ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
04263          user->contexts ? user->contexts->context : context,
04264          user->ha ? "Yes" : "No", pstr);
04265    }
04266 
04267    if (havepattern)
04268       regfree(&regexbuf);
04269 
04270    return RESULT_SUCCESS;
04271 #undef FORMAT
04272 #undef FORMAT2
04273 }

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

Definition at line 3237 of file chan_iax2.c.

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

03238 {
03239    int res;
03240    struct iax_ie_data ied0;
03241    struct iax_ie_data ied1;
03242    unsigned int transferid = (unsigned int)ast_random();
03243    memset(&ied0, 0, sizeof(ied0));
03244    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03245    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03246    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03247 
03248    memset(&ied1, 0, sizeof(ied1));
03249    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03250    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03251    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03252    
03253    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03254    if (res)
03255       return -1;
03256    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03257    if (res)
03258       return -1;
03259    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03260    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03261    return 0;
03262 }

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

Definition at line 2147 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02148 {
02149        if (argc != 4)
02150                return RESULT_SHOWUSAGE;
02151 
02152        test_losspct = atoi(argv[3]);
02153 
02154        return RESULT_SUCCESS;
02155 }

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

Definition at line 3472 of file chan_iax2.c.

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

03473 {
03474    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03475    struct iax_ie_data ied;
03476    char tmp[256], *context;
03477    ast_copy_string(tmp, dest, sizeof(tmp));
03478    context = strchr(tmp, '@');
03479    if (context) {
03480       *context = '\0';
03481       context++;
03482    }
03483    memset(&ied, 0, sizeof(ied));
03484    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03485    if (context)
03486       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03487    if (option_debug)
03488       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03489    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03490 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

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

02615 {
02616    /* Lock the queue and place this packet at the end */
02617    /* By setting this to 0, the network thread will send it for us, and
02618       queue retransmission if necessary */
02619    fr->sentyet = 0;
02620    AST_LIST_LOCK(&iaxq.queue);
02621    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02622    iaxq.count++;
02623    AST_LIST_UNLOCK(&iaxq.queue);
02624    /* Wake up the network and scheduler thread */
02625    if (netthreadid != AST_PTHREADT_NULL)
02626       pthread_kill(netthreadid, SIGURG);
02627    signal_condition(&sched_lock, &sched_cond);
02628    return 0;
02629 }

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

Definition at line 6246 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06247 {
06248    /* Drop when trunk is about 5 seconds idle */
06249    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06250       return 1;
06251    return 0;
06252 }

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

Definition at line 3815 of file chan_iax2.c.

References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, ast_iax2_meta_trunk_entry::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, iax2_trunk_peer::calls, DEFAULT_TRUNKDATA, f, find_tpeer(), globalflags, IAX2_TRUNK_PREFACE, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_WARNING, MAX_TRUNKDATA, ast_iax2_meta_trunk_mini::mini, 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().

03816 {
03817    struct ast_frame *f;
03818    struct iax2_trunk_peer *tpeer;
03819    void *tmp, *ptr;
03820    struct ast_iax2_meta_trunk_entry *met;
03821    struct ast_iax2_meta_trunk_mini *mtm;
03822 
03823    f = &fr->af;
03824    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
03825    if (tpeer) {
03826       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
03827          /* Need to reallocate space */
03828          if (tpeer->trunkdataalloc < MAX_TRUNKDATA) {
03829             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
03830                ast_mutex_unlock(&tpeer->lock);
03831                return -1;
03832             }
03833             
03834             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
03835             tpeer->trunkdata = tmp;
03836             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);
03837          } else {
03838             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));
03839             ast_mutex_unlock(&tpeer->lock);
03840             return -1;
03841          }
03842       }
03843 
03844       /* Append to meta frame */
03845       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
03846       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
03847          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
03848          mtm->len = htons(f->datalen);
03849          mtm->mini.callno = htons(pvt->callno);
03850          mtm->mini.ts = htons(0xffff & fr->ts);
03851          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
03852          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
03853       } else {
03854          met = (struct ast_iax2_meta_trunk_entry *)ptr;
03855          /* Store call number and length in meta header */
03856          met->callno = htons(pvt->callno);
03857          met->len = htons(f->datalen);
03858          /* Advance pointers/decrease length past trunk entry header */
03859          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
03860          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
03861       }
03862       /* Copy actual trunk data */
03863       memcpy(ptr, f->data, f->datalen);
03864       tpeer->trunkdatalen += f->datalen;
03865 
03866       tpeer->calls++;
03867       ast_mutex_unlock(&tpeer->lock);
03868    }
03869    return 0;
03870 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6165 of file chan_iax2.c.

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

Referenced by socket_process().

06166 {
06167    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06168 }

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

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

04747 {
04748    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
04749    int res = -1;
04750    ast_mutex_lock(&iaxsl[callno]);
04751    if (iaxs[callno]) {
04752    /* If there's an outstanding error, return failure now */
04753       if (!iaxs[callno]->error) {
04754          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
04755             res = 0;
04756             /* Don't waste bandwidth sending null frames */
04757          else if (f->frametype == AST_FRAME_NULL)
04758             res = 0;
04759          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
04760             res = 0;
04761          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
04762             res = 0;
04763          else
04764          /* Simple, just queue for transmission */
04765             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
04766       } else {
04767          ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
04768       }
04769    }
04770    /* If it's already gone, just return */
04771    ast_mutex_unlock(&iaxsl[callno]);
04772    return res;
04773 }

static int iax_check_version ( char *  dev  )  [static]

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

01669 {
01670    int res = 0;
01671    struct iax_firmware *cur;
01672    if (!ast_strlen_zero(dev)) {
01673       ast_mutex_lock(&waresl.lock);
01674       cur = waresl.wares;
01675       while(cur) {
01676          if (!strcmp(dev, (char *)cur->fwh->devname)) {
01677             res = ntohs(cur->fwh->version);
01678             break;
01679          }
01680          cur = cur->next;
01681       }
01682       ast_mutex_unlock(&waresl.lock);
01683    }
01684    return res;
01685 }

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

Definition at line 762 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

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

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

Definition at line 768 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

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

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

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

01688 {
01689    int res = -1;
01690    unsigned int bs = desc & 0xff;
01691    unsigned int start = (desc >> 8) & 0xffffff;
01692    unsigned int bytes;
01693    struct iax_firmware *cur;
01694    if (!ast_strlen_zero((char *)dev) && bs) {
01695       start *= bs;
01696       ast_mutex_lock(&waresl.lock);
01697       cur = waresl.wares;
01698       while(cur) {
01699          if (!strcmp((char *)dev, (char *)cur->fwh->devname)) {
01700             iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
01701             if (start < ntohl(cur->fwh->datalen)) {
01702                bytes = ntohl(cur->fwh->datalen) - start;
01703                if (bytes > bs)
01704                   bytes = bs;
01705                iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
01706             } else {
01707                bytes = 0;
01708                iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
01709             }
01710             if (bytes == bs)
01711                res = 0;
01712             else
01713                res = 1;
01714             break;
01715          }
01716          cur = cur->next;
01717       }
01718       ast_mutex_unlock(&waresl.lock);
01719    }
01720    return res;
01721 }

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

Definition at line 6428 of file chan_iax2.c.

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

Referenced by socket_process().

06429 {
06430    struct iax_dual *d;
06431    struct ast_channel *chan1m, *chan2m;
06432    pthread_t th;
06433    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
06434    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
06435    if (chan2m && chan1m) {
06436       /* Make formats okay */
06437       chan1m->readformat = chan1->readformat;
06438       chan1m->writeformat = chan1->writeformat;
06439       ast_channel_masquerade(chan1m, chan1);
06440       /* Setup the extensions and such */
06441       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
06442       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
06443       chan1m->priority = chan1->priority;
06444       
06445       /* We make a clone of the peer channel too, so we can play
06446          back the announcement */
06447       /* Make formats okay */
06448       chan2m->readformat = chan2->readformat;
06449       chan2m->writeformat = chan2->writeformat;
06450       ast_channel_masquerade(chan2m, chan2);
06451       /* Setup the extensions and such */
06452       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
06453       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
06454       chan2m->priority = chan2->priority;
06455       if (ast_do_masquerade(chan2m)) {
06456          ast_log(LOG_WARNING, "Masquerade failed :(\n");
06457          ast_hangup(chan2m);
06458          return -1;
06459       }
06460    } else {
06461       if (chan1m)
06462          ast_hangup(chan1m);
06463       if (chan2m)
06464          ast_hangup(chan2m);
06465       return -1;
06466    }
06467    if ((d = ast_calloc(1, sizeof(*d)))) {
06468       pthread_attr_t attr;
06469 
06470       pthread_attr_init(&attr);
06471       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06472 
06473       d->chan1 = chan1m;
06474       d->chan2 = chan2m;
06475       if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
06476          pthread_attr_destroy(&attr);
06477          return 0;
06478       }
06479       pthread_attr_destroy(&attr);
06480       free(d);
06481    }
06482    return -1;
06483 }

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

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

06409 {
06410    struct ast_channel *chan1, *chan2;
06411    struct iax_dual *d;
06412    struct ast_frame *f;
06413    int ext;
06414    int res;
06415    d = stuff;
06416    chan1 = d->chan1;
06417    chan2 = d->chan2;
06418    free(d);
06419    f = ast_read(chan1);
06420    if (f)
06421       ast_frfree(f);
06422    res = ast_park_call(chan1, chan2, 0, &ext);
06423    ast_hangup(chan2);
06424    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06425    return NULL;
06426 }

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

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

01210 {
01211    struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable);
01212    if (new) {
01213       size_t afdatalen = new->afdatalen;
01214       memcpy(new, fr, sizeof(*new));
01215       iax_frame_wrap(new, &fr->af);
01216       new->afdatalen = afdatalen;
01217       new->data = NULL;
01218       new->datalen = 0;
01219       new->direction = DIRECTION_INGRESS;
01220       new->retrans = -1;
01221    }
01222    return new;
01223 }

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

Definition at line 874 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

00875 {
00876    if (thread->type == IAX_TYPE_DYNAMIC) {
00877       AST_LIST_LOCK(&dynamic_list);
00878       AST_LIST_INSERT_TAIL(&dynamic_list, thread, list);
00879       AST_LIST_UNLOCK(&dynamic_list);
00880    } else {
00881       AST_LIST_LOCK(&idle_list);
00882       AST_LIST_INSERT_TAIL(&idle_list, thread, list);
00883       AST_LIST_UNLOCK(&idle_list);
00884    }
00885 
00886    return;
00887 }

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

Definition at line 797 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 773 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

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

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

Definition at line 785 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 10670 of file chan_iax2.c.

References __unload_module(), ao2_callback(), ao2_container_alloc(), ao2_ref(), 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, iax2_do_register(), iax2_poke_peer_cb(), iax2_prov_app(), iax2_switch, iax2_tech, iax_debug_output(), iax_error_output(), IAX_MAX_CALLS, iax_provision_reload(), iax_set_error(), iax_set_output(), iaxpeer_function, iaxq, iaxs, iaxsl, io, io_context_create(), jb_error_output(), jb_setoutput(), jb_warning_output(), ast_firmware_list::lock, LOG_ERROR, LOG_WARNING, manager_iax2_show_netstats(), manager_iax2_show_peers(), MAX_PEER_BUCKETS, MAX_USER_BUCKETS, netsock, option_verbose, outsock, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), peers, reload_firmware(), sched, sched_context_create(), set_config(), start_network_thread(), user_cmp_cb(), user_hash_cb(), users, VERBOSE_PREFIX_2, and waresl.

10671 {
10672    char *config = "iax.conf";
10673    int res = 0;
10674    int x;
10675    struct iax2_registry *reg = NULL;
10676 
10677    peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
10678    if (!peers)
10679       return AST_MODULE_LOAD_FAILURE;
10680    users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
10681    if (!users) {
10682       ao2_ref(peers, -1);
10683       return AST_MODULE_LOAD_FAILURE;
10684    }
10685 
10686    ast_custom_function_register(&iaxpeer_function);
10687 
10688    iax_set_output(iax_debug_output);
10689    iax_set_error(iax_error_output);
10690    jb_setoutput(jb_error_output, jb_warning_output, NULL);
10691    
10692 #ifdef HAVE_ZAPTEL
10693 #ifdef ZT_TIMERACK
10694    timingfd = open("/dev/zap/timer", O_RDWR);
10695    if (timingfd < 0)
10696 #endif
10697       timingfd = open("/dev/zap/pseudo", O_RDWR);
10698    if (timingfd < 0) 
10699       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
10700 #endif      
10701 
10702    memset(iaxs, 0, sizeof(iaxs));
10703 
10704    for (x=0;x<IAX_MAX_CALLS;x++)
10705       ast_mutex_init(&iaxsl[x]);
10706    
10707    ast_cond_init(&sched_cond, NULL);
10708 
10709    io = io_context_create();
10710    sched = sched_context_create();
10711    
10712    if (!io || !sched) {
10713       ast_log(LOG_ERROR, "Out of memory\n");
10714       return -1;
10715    }
10716 
10717    netsock = ast_netsock_list_alloc();
10718    if (!netsock) {
10719       ast_log(LOG_ERROR, "Could not allocate netsock list.\n");
10720       return -1;
10721    }
10722    ast_netsock_init(netsock);
10723 
10724    outsock = ast_netsock_list_alloc();
10725    if (!outsock) {
10726       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
10727       return -1;
10728    }
10729    ast_netsock_init(outsock);
10730 
10731    ast_mutex_init(&waresl.lock);
10732 
10733    AST_LIST_HEAD_INIT(&iaxq.queue);
10734    
10735    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10736 
10737    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
10738    
10739    ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" );
10740    ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" );
10741 
10742    if(set_config(config, 0) == -1)
10743       return AST_MODULE_LOAD_DECLINE;
10744 
10745    if (ast_channel_register(&iax2_tech)) {
10746       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
10747       __unload_module();
10748       return -1;
10749    }
10750 
10751    if (ast_register_switch(&iax2_switch)) 
10752       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
10753 
10754    res = start_network_thread();
10755    if (!res) {
10756       if (option_verbose > 1) 
10757          ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n");
10758    } else {
10759       ast_log(LOG_ERROR, "Unable to start network thread\n");
10760       ast_netsock_release(netsock);
10761       ast_netsock_release(outsock);
10762    }
10763 
10764    AST_LIST_LOCK(&registrations);
10765    AST_LIST_TRAVERSE(&registrations, reg, entry)
10766       iax2_do_register(reg);
10767    AST_LIST_UNLOCK(&registrations); 
10768 
10769    ao2_callback(peers, 0, peer_set_sock_cb, NULL);
10770    ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
10771 
10772    reload_firmware();
10773    iax_provision_reload();
10774    return res;
10775 }

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

Definition at line 3264 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03265 {
03266    ast_mutex_lock(&iaxsl[callno0]);
03267    while (ast_mutex_trylock(&iaxsl[callno1])) {
03268       ast_mutex_unlock(&iaxsl[callno0]);
03269       usleep(10);
03270       ast_mutex_lock(&iaxsl[callno0]);
03271    }
03272 }

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

Definition at line 1277 of file chan_iax2.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), chan_iax2_pvt::callno, iaxs, iaxsl, chan_iax2_pvt::lagid, LOG_WARNING, MIN_REUSE_TIME, chan_iax2_pvt::pingid, sched, send_lagrq(), send_ping(), and TRUNK_CALL_START.

Referenced by iax2_request(), and socket_process().

01278 {
01279    int x;
01280    int res= 0;
01281    struct timeval now;
01282    if (iaxs[callno]->oseqno) {
01283       ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n");
01284       return -1;
01285    }
01286    if (callno & TRUNK_CALL_START) {
01287       ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno);
01288       return -1;
01289    }
01290    gettimeofday(&now, NULL);
01291    for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) {
01292       ast_mutex_lock(&iaxsl[x]);
01293       if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01294          iaxs[x] = iaxs[callno];
01295          iaxs[x]->callno = x;
01296          iaxs[callno] = NULL;
01297          /* Update the two timers that should have been started */
01298          if (iaxs[x]->pingid > -1)
01299             ast_sched_del(sched, iaxs[x]->pingid);
01300          if (iaxs[x]->lagid > -1)
01301             ast_sched_del(sched, iaxs[x]->lagid);
01302          iaxs[x]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01303          iaxs[x]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01304          if (locked)
01305             ast_mutex_unlock(&iaxsl[callno]);
01306          res = x;
01307          if (!locked)
01308             ast_mutex_unlock(&iaxsl[x]);
01309          break;
01310       }
01311       ast_mutex_unlock(&iaxsl[x]);
01312    }
01313    if (x >= IAX_MAX_CALLS - 1) {
01314       ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n");
01315       return -1;
01316    }
01317    ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x);
01318    /* We move this call from a non-trunked to a trunked call */
01319    update_max_trunk();
01320    update_max_nontrunk();
01321    return res;
01322 }

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

Definition at line 4460 of file chan_iax2.c.

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

Referenced by load_module().

04461 {
04462    ast_cli_netstats(s, -1, 0);
04463    astman_append(s, "\r\n");
04464    return RESULT_SUCCESS;
04465 }

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

Definition at line 4493 of file chan_iax2.c.

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

Referenced by load_module().

04494 {
04495    char *a[] = { "iax2", "show", "users" };
04496    int ret;
04497    const char *id = astman_get_header(m,"ActionID");
04498 
04499    if (!ast_strlen_zero(id))
04500       astman_append(s, "ActionID: %s\r\n",id);
04501    ret = __iax2_show_peers(1, -1, s, 3, a );
04502    astman_append(s, "\r\n\r\n" );
04503    return ret;
04504 } /* /JDG */

static int match ( struct sockaddr_in *  sin,
unsigned short  callno,
unsigned short  dcallno,
struct chan_iax2_pvt cur 
) [static]

Definition at line 1229 of file chan_iax2.c.

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

Referenced by ao2_callback(), ast_parse_device_state(), find_callno(), find_command(), get_sip_pvt_byid_locked(), handle_updates(), pbx_find_extension(), realtime_switch_common(), and softhangup_exec().

01230 {
01231    if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01232       (cur->addr.sin_port == sin->sin_port)) {
01233       /* This is the main host */
01234       if ((cur->peercallno == callno) ||
01235          ((dcallno == cur->callno) && !cur->peercallno)) {
01236          /* That's us.  Be sure we keep track of the peer call number */
01237          return 1;
01238       }
01239    }
01240    if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01241        (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {
01242       /* We're transferring */
01243       if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno))
01244          return 1;
01245    }
01246    return 0;
01247 }

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

Definition at line 3878 of file chan_iax2.c.

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

Referenced by decode_frame().

03879 {
03880 #if 0
03881    /* Debug with "fake encryption" */
03882    int x;
03883    if (len % 16)
03884       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
03885    for (x=0;x<len;x++)
03886       dst[x] = src[x] ^ 0xff;
03887 #else 
03888    unsigned char lastblock[16] = { 0 };
03889    int x;
03890    while(len > 0) {
03891       aes_decrypt(src, dst, dcx);
03892       for (x=0;x<16;x++)
03893          dst[x] ^= lastblock[x];
03894       memcpy(lastblock, src, sizeof(lastblock));
03895       dst += 16;
03896       src += 16;
03897       len -= 16;
03898    }
03899 #endif
03900 }

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

Definition at line 3902 of file chan_iax2.c.

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

Referenced by encrypt_frame().

03903 {
03904 #if 0
03905    /* Debug with "fake encryption" */
03906    int x;
03907    if (len % 16)
03908       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
03909    for (x=0;x<len;x++)
03910       dst[x] = src[x] ^ 0xff;
03911 #else
03912    unsigned char curblock[16] = { 0 };
03913    int x;
03914    while(len > 0) {
03915       for (x=0;x<16;x++)
03916          curblock[x] ^= src[x];
03917       aes_encrypt(curblock, dst, ecx);
03918       memcpy(curblock, dst, sizeof(curblock)); 
03919       dst += 16;
03920       src += 16;
03921       len -= 16;
03922    }
03923 #endif
03924 }

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

Definition at line 5072 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05073 {
05074    /* Select exactly one common encryption if there are any */
05075    p->encmethods &= enc;
05076    if (p->encmethods) {
05077       if (p->encmethods & IAX_ENCRYPT_AES128)
05078          p->encmethods = IAX_ENCRYPT_AES128;
05079       else
05080          p->encmethods = 0;
05081    }
05082 }

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

Definition at line 8684 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(), ast_sched_add(), attempt_transmit(), f, iax_frame_free(), iaxq, iaxs, iaxsl, io, sched, send_packet(), signal_condition(), and timing_read().

Referenced by start_network_thread().

08685 {
08686    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
08687       from the network, and queue them for delivery to the channels */
08688    int res, count, wakeup;
08689    struct iax_frame *f;
08690 
08691    if (timingfd > -1)
08692       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
08693    
08694    for(;;) {
08695       pthread_testcancel();
08696 
08697       /* Go through the queue, sending messages which have not yet been
08698          sent, and scheduling retransmissions if appropriate */
08699       AST_LIST_LOCK(&iaxq.queue);
08700       count = 0;
08701       wakeup = -1;
08702       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
08703          if (f->sentyet)
08704             continue;
08705          
08706          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
08707          if (ast_mutex_trylock(&iaxsl[f->callno])) {
08708             wakeup = 1;
08709             continue;
08710          }
08711 
08712          f->sentyet++;
08713 
08714          if (iaxs[f->callno]) {
08715             send_packet(f);
08716             count++;
08717          } 
08718 
08719          ast_mutex_unlock(&iaxsl[f->callno]);
08720 
08721          if (f->retries < 0) {
08722             /* This is not supposed to be retransmitted */
08723             AST_LIST_REMOVE_CURRENT(&iaxq.queue, list);
08724             iaxq.count--;
08725             /* Free the iax frame */
08726             iax_frame_free(f);
08727          } else {
08728             /* We need reliable delivery.  Schedule a retransmission */
08729             f->retries++;
08730             f->retrans = ast_sched_add(sched, f->retrytime, attempt_transmit, f);
08731             signal_condition(&sched_lock, &sched_cond);
08732          }
08733       }
08734       AST_LIST_TRAVERSE_SAFE_END
08735       AST_LIST_UNLOCK(&iaxq.queue);
08736 
08737       pthread_testcancel();
08738 
08739       if (count >= 20)
08740          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
08741 
08742       /* Now do the IO, and run scheduled tasks */
08743       res = ast_io_wait(io, wakeup);
08744       if (res >= 0) {
08745          if (res >= 20)
08746             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
08747       }
08748    }
08749    return NULL;
08750 }

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

Definition at line 1171 of file chan_iax2.c.

References ast_calloc, ast_string_field_init, ast_string_field_set, exten, free, jb_new(), jb_setconf(), jb_conf::max_contig_interp, jb_conf::max_jitterbuf, prefs, and jb_conf::resync_threshold.

Referenced by find_callno().

01172 {
01173    struct chan_iax2_pvt *tmp;
01174    jb_conf jbconf;
01175 
01176    if (!(tmp = ast_calloc(1, sizeof(*tmp))))
01177       return NULL;
01178 
01179    if (ast_string_field_init(tmp, 32)) {
01180       free(tmp);
01181       tmp = NULL;
01182       return NULL;
01183    }
01184       
01185    tmp->prefs = prefs;
01186    tmp->callno = 0;
01187    tmp->peercallno = 0;
01188    tmp->transfercallno = 0;
01189    tmp->bridgecallno = 0;
01190    tmp->pingid = -1;
01191    tmp->lagid = -1;
01192    tmp->autoid = -1;
01193    tmp->authid = -1;
01194    tmp->initid = -1;
01195 
01196    ast_string_field_set(tmp,exten, "s");
01197    ast_string_field_set(tmp,host, host);
01198 
01199    tmp->jb = jb_new();
01200    tmp->jbid = -1;
01201    jbconf.max_jitterbuf = maxjitterbuffer;
01202    jbconf.resync_threshold = resyncthreshold;
01203    jbconf.max_contig_interp = maxjitterinterps;
01204    jb_setconf(tmp->jb,&jbconf);
01205 
01206    return tmp;
01207 }

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

02992 {
02993    if (ast_strlen_zero(data))
02994       return;
02995 
02996    pds->peer = strsep(&data, "/");
02997    pds->exten = strsep(&data, "/");
02998    pds->options = data;
02999 
03000    if (pds->exten) {
03001       data = pds->exten;
03002       pds->exten = strsep(&data, "@");
03003       pds->context = data;
03004    }
03005 
03006    if (strchr(pds->peer, '@')) {
03007       data = pds->peer;
03008       pds->username = strsep(&data, "@");
03009       pds->peer = data;
03010    }
03011 
03012    if (pds->username) {
03013       data = pds->username;
03014       pds->username = strsep(&data, ":");
03015       pds->password = data;
03016    }
03017 
03018    data = pds->peer;
03019    pds->peer = strsep(&data, ":");
03020    pds->port = data;
03021 
03022    /* check for a key name wrapped in [] in the secret position, if found,
03023       move it to the key field instead
03024    */
03025    if (pds->password && (pds->password[0] == '[')) {
03026       pds->key = ast_strip_quoted(pds->password, "[", "]");
03027       pds->password = NULL;
03028    }
03029 }

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

Referenced by load_module().

01071 {
01072    struct iax2_peer *peer = obj, *peer2 = arg;
01073 
01074    return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0;
01075 }

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

Definition at line 9392 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09393 {
09394    struct iax2_peer *peer = obj;
09395 
09396    ast_set_flag(peer, IAX_DELME);
09397 
09398    return 0;
09399 }

static void peer_destructor ( void *  obj  )  [static]

Definition at line 8906 of file chan_iax2.c.

References ast_dnsmgr_release(), ast_free_ha(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), ast_string_field_free_pools, iax2_peer::callno, iax2_peer::dnsmgr, iax2_peer::expire, iax2_peer::ha, iax2_destroy(), iaxsl, iax2_peer::pokeexpire, register_peer_exten(), and sched.

Referenced by build_peer().

08907 {
08908    struct iax2_peer *peer = obj;
08909 
08910    ast_free_ha(peer->ha);
08911 
08912    /* Delete it, it needs to disappear */
08913    if (peer->expire > -1)
08914       ast_sched_del(sched, peer->expire);
08915    if (peer->pokeexpire > -1)
08916       ast_sched_del(sched, peer->pokeexpire);
08917    if (peer->callno > 0) {
08918       ast_mutex_lock(&iaxsl[peer->callno]);
08919       iax2_destroy(peer->callno);
08920       ast_mutex_unlock(&iaxsl[peer->callno]);
08921    }
08922 
08923    register_peer_exten(peer, 0);
08924 
08925    if (peer->dnsmgr)
08926       ast_dnsmgr_release(peer->dnsmgr);
08927 
08928    ast_string_field_free_pools(peer);
08929 }

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

References ast_str_hash().

Referenced by load_module().

01061 {
01062    const struct iax2_peer *peer = obj;
01063 
01064    return ast_str_hash(peer->name);
01065 }

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

Definition at line 1117 of file chan_iax2.c.

References ao2_ref().

01118 {
01119    ao2_ref(peer, +1);
01120    return peer;
01121 }

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

Definition at line 10659 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

10660 {
10661    struct iax2_peer *peer = obj;
10662 
10663    if (peer->sockfd < 0)
10664       peer->sockfd = defaultsockfd;
10665 
10666    return 0;
10667 }

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

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

Referenced by build_peer().

08835 {
08836    struct sockaddr_in sin;
08837    int nonlocal = 1;
08838    int port = IAX_DEFAULT_PORTNO;
08839    int sockfd = defaultsockfd;
08840    char *tmp;
08841    char *addr;
08842    char *portstr;
08843 
08844    if (!(tmp = ast_strdupa(srcaddr)))
08845       return -1;
08846 
08847    addr = strsep(&tmp, ":");
08848    portstr = tmp;
08849 
08850    if (portstr) {
08851       port = atoi(portstr);
08852       if (port < 1)
08853          port = IAX_DEFAULT_PORTNO;
08854    }
08855    
08856    if (!ast_get_ip(&sin, addr)) {
08857       struct ast_netsock *sock;
08858       int res;
08859 
08860       sin.sin_port = 0;
08861       sin.sin_family = AF_INET;
08862       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
08863       if (res == 0) {
08864          /* ip address valid. */
08865          sin.sin_port = htons(port);
08866          if (!(sock = ast_netsock_find(netsock, &sin)))
08867             sock = ast_netsock_find(outsock, &sin);
08868          if (sock) {
08869             sockfd = ast_netsock_sockfd(sock);
08870             nonlocal = 0;
08871          } else {
08872             unsigned int orig_saddr = sin.sin_addr.s_addr;
08873             /* INADDR_ANY matches anyway! */
08874             sin.sin_addr.s_addr = INADDR_ANY;
08875             if (ast_netsock_find(netsock, &sin)) {
08876                sin.sin_addr.s_addr = orig_saddr;
08877                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
08878                if (sock) {
08879                   sockfd = ast_netsock_sockfd(sock);
08880                   ast_netsock_unref(sock);
08881                   nonlocal = 0;
08882                } else {
08883                   nonlocal = 2;
08884                }
08885             }
08886          }
08887       }
08888    }
08889       
08890    peer->sockfd = sockfd;
08891 
08892    if (nonlocal == 1) {
08893       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
08894          srcaddr, peer->name);
08895       return -1;
08896         } else if (nonlocal == 2) {
08897       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
08898          srcaddr, peer->name);
08899          return -1;
08900    } else {
08901       ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
08902       return 0;
08903    }
08904 }

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

peer_status: Report Peer status in character string

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

02194 {
02195    int res = 0;
02196    if (peer->maxms) {
02197       if (peer->lastms < 0) {
02198          ast_copy_string(status, "UNREACHABLE", statuslen);
02199       } else if (peer->lastms > peer->maxms) {
02200          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02201          res = 1;
02202       } else if (peer->lastms) {
02203          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02204          res = 1;
02205       } else {
02206          ast_copy_string(status, "UNKNOWN", statuslen);
02207       }
02208    } else { 
02209       ast_copy_string(status, "Unmonitored", statuslen);
02210       res = -1;
02211    }
02212    return res;
02213 }

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

Definition at line 1123 of file chan_iax2.c.

References ao2_ref().

Referenced by __expire_registry(), __iax2_show_peers(), authenticate_reply(), build_peer(), complete_iax2_show_peer(), create_addr(), function_iaxpeer(), iax2_devicestate(), iax2_getpeername(), iax2_getpeertrunk(), iax2_prune_realtime(), iax2_show_peer(), prune_peers(), realtime_peer(), registry_authrequest(), and update_registry().

01124 {
01125    ao2_ref(peer, -1);
01126    return NULL;
01127 }

static void prune_peers ( void   )  [static]

Definition at line 9451 of file chan_iax2.c.

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

09452 {
09453    struct iax2_peer *peer;
09454    ao2_iterator i;
09455 
09456    i = ao2_iterator_init(peers, 0);
09457    while ((peer = ao2_iterator_next(&i))) {
09458       if (ast_test_flag(peer, IAX_DELME))
09459          ao2_unlink(peers, peer);
09460       peer_unref(peer);
09461    }
09462 }

static void prune_users ( void   )  [static]

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

09438 {
09439    struct iax2_user *user;
09440    ao2_iterator i;
09441 
09442    i = ao2_iterator_init(users, 0);
09443    while ((user = ao2_iterator_next(&i))) {
09444       if (ast_test_flag(user, IAX_DELME))
09445          ao2_unlink(users, user);
09446       user_unref(user);
09447    }
09448 }

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

Definition at line 5052 of file chan_iax2.c.

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

Referenced by socket_process().

05053 {
05054    struct ast_iax2_full_hdr fh;
05055    fh.scallno = htons(src | IAX_FLAG_FULL);
05056    fh.dcallno = htons(dst);
05057    fh.ts = 0;
05058    fh.oseqno = 0;
05059    fh.iseqno = 0;
05060    fh.type = AST_FRAME_IAX;
05061    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
05062    if (iaxdebug)
05063        iax_showframe(NULL, &fh, 0, sin, 0);
05064 #if 0
05065    if (option_debug)
05066 #endif   
05067       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
05068          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
05069    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
05070 }

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

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

Definition at line 2676 of file chan_iax2.c.

References ast_inet_ntoa(), ast_load_realtime(), ast_test_flag, ast_variables_destroy(), build_peer(), globalflags, IAX_RTCACHEFRIENDS, ast_variable::name, ast_variable::next, peer_unref(), ast_variable::value, and var.

02677 {
02678    struct ast_variable *var;
02679    struct ast_variable *tmp;
02680    struct iax2_peer *peer=NULL;
02681    time_t regseconds = 0, nowtime;
02682    int dynamic=0;
02683 
02684    if (peername)
02685       var = ast_load_realtime("iaxpeers", "name", peername, NULL);
02686    else {
02687       char porta[25];
02688       sprintf(porta, "%d", ntohs(sin->sin_port));
02689       var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02690       if (var) {
02691          /* We'll need the peer name in order to build the structure! */
02692          for (tmp = var; tmp; tmp = tmp->next) {
02693             if (!strcasecmp(tmp->name, "name"))
02694                peername = tmp->value;
02695          }
02696       }
02697    }
02698    if (!var)
02699       return NULL;
02700 
02701    peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
02702    
02703    if (!peer) {
02704       ast_variables_destroy(var);
02705       return NULL;
02706    }
02707 
02708    for (tmp = var; tmp; tmp = tmp->next) {
02709       /* Make sure it's not a user only... */
02710       if (!strcasecmp(tmp->name, "type")) {
02711          if (strcasecmp(tmp->value, "friend") &&
02712              strcasecmp(tmp->value, "peer")) {
02713             /* Whoops, we weren't supposed to exist! */
02714             peer = peer_unref(peer);
02715             break;
02716          } 
02717       } else if (!strcasecmp(tmp->name, "regseconds")) {
02718          ast_get_time_t(tmp->value, &regseconds, 0, NULL);
02719       } else if (!strcasecmp(tmp->name, "ipaddr")) {
02720          inet_aton(tmp->value, &(peer->addr.sin_addr));
02721       } else if (!strcasecmp(tmp->name, "port")) {
02722          peer->addr.sin_port = htons(atoi(tmp->value));
02723       } else if (!strcasecmp(tmp->name, "host")) {
02724          if (!strcasecmp(tmp->value, "dynamic"))
02725             dynamic = 1;
02726       }
02727    }
02728 
02729    ast_variables_destroy(var);
02730 
02731    if (!peer)
02732       return NULL;
02733 
02734    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02735       ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
02736       if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
02737          if (peer->expire > -1)
02738             ast_sched_del(sched, peer->expire);
02739          peer->expire = ast_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, (void*)peer->name);
02740       }
02741       ao2_link(peers, peer_ref(peer));
02742       if (ast_test_flag(peer, IAX_DYNAMIC))
02743          reg_source_db(peer);
02744    } else {
02745       ast_set_flag(peer, IAX_TEMPONLY);   
02746    }
02747 
02748    if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) {
02749       time(&nowtime);
02750       if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) {
02751          memset(&peer->addr, 0, sizeof(peer->addr));
02752          realtime_update_peer(peer->name, &peer->addr, 0);
02753          if (option_debug)
02754             ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n",
02755                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02756       }
02757       else {
02758          if (option_debug)
02759             ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n",
02760                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02761       }
02762    }
02763 
02764    return peer;
02765 }

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

Definition at line 2806 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

02807 {
02808    char port[10];
02809    char regseconds[20];
02810    
02811    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
02812    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
02813    ast_update_realtime("iaxpeers", "name", peername, 
02814       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
02815       "regseconds", regseconds, NULL);
02816 }

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

Definition at line 2767 of file chan_iax2.c.

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

02768 {
02769    struct ast_variable *var;
02770    struct ast_variable *tmp;
02771    struct iax2_user *user=NULL;
02772 
02773    var = ast_load_realtime("iaxusers", "name", username, NULL);
02774    if (!var)
02775       return NULL;
02776 
02777    tmp = var;
02778    while(tmp) {
02779       /* Make sure it's not a peer only... */
02780       if (!strcasecmp(tmp->name, "type")) {
02781          if (strcasecmp(tmp->value, "friend") &&
02782              strcasecmp(tmp->value, "user")) {
02783             return NULL;
02784          } 
02785       }
02786       tmp = tmp->next;
02787    }
02788 
02789    user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
02790 
02791    ast_variables_destroy(var);
02792 
02793    if (!user)
02794       return NULL;
02795 
02796    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02797       ast_set_flag(user, IAX_RTCACHEFRIENDS);
02798       ao2_link(users, user_ref(user));
02799    } else {
02800       ast_set_flag(user, IAX_TEMPONLY);   
02801    }
02802 
02803    return user;
02804 }

static void reg_source_db ( struct iax2_peer p  )  [static]

Definition at line 5815 of file chan_iax2.c.

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

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

05816 {
05817    char data[80];
05818    struct in_addr in;
05819    char *c, *d;
05820    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
05821       c = strchr(data, ':');
05822       if (c) {
05823          *c = '\0';
05824          c++;
05825          if (inet_aton(data, &in)) {
05826             d = strchr(c, ':');
05827             if (d) {
05828                *d = '\0';
05829                d++;
05830                if (option_verbose > 2)
05831                   ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 
05832                   ast_inet_ntoa(in), atoi(c), atoi(d));
05833                iax2_poke_peer(p, 0);
05834                p->expiry = atoi(d);
05835                memset(&p->addr, 0, sizeof(p->addr));
05836                p->addr.sin_family = AF_INET;
05837                p->addr.sin_addr = in;
05838                p->addr.sin_port = htons(atoi(c));
05839                if (p->expire > -1)
05840                   ast_sched_del(sched, p->expire);
05841                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05842                p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name);
05843                if (iax2_regfunk)
05844                   iax2_regfunk(p->name, 1);
05845                register_peer_exten(p, 1);
05846             }              
05847                
05848          }
05849       }
05850    }
05851 }

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

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

05751 {
05752    char multi[256];
05753    char *stringp, *ext;
05754    if (!ast_strlen_zero(regcontext)) {
05755       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
05756       stringp = multi;
05757       while((ext = strsep(&stringp, "&"))) {
05758          if (onoff) {
05759             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
05760                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
05761                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
05762          } else
05763             ast_context_remove_extension(regcontext, ext, 1, NULL);
05764       }
05765    }
05766 }

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

Verify inbound registration.

Definition at line 5218 of file chan_iax2.c.

References iax2_peer::addr, ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, IAX_STATE_UNCHANGED, iaxs, iaxsl, ies, inaddrcmp(), key(), LOG_NOTICE, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), secret, and strsep().

Referenced by handle_request_register(), and socket_process().

05219 {
05220    char requeststr[256] = "";
05221    char peer[256] = "";
05222    char md5secret[256] = "";
05223    char rsasecret[256] = "";
05224    char secret[256] = "";
05225    struct iax2_peer *p = NULL;
05226    struct ast_key *key;
05227    char *keyn;
05228    int x;
05229    int expire = 0;
05230    int res = -1;
05231 
05232    ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED);
05233    /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
05234    if (ies->username)
05235       ast_copy_string(peer, ies->username, sizeof(peer));
05236    if (ies->password)
05237       ast_copy_string(secret, ies->password, sizeof(secret));
05238    if (ies->md5_result)
05239       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05240    if (ies->rsa_result)
05241       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05242    if (ies->refresh)
05243       expire = ies->refresh;
05244 
05245    if (ast_strlen_zero(peer)) {
05246       ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr));
05247       return -1;
05248    }
05249 
05250    /* SLD: first call to lookup peer during registration */
05251    ast_mutex_unlock(&iaxsl[callno]);
05252    p = find_peer(peer, 1);
05253    ast_mutex_lock(&iaxsl[callno]);
05254    if (!p || !iaxs[callno]) {
05255       if (authdebug && !p)
05256          ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05257       goto return_unref;
05258    }
05259 
05260    if (!ast_test_flag(p, IAX_DYNAMIC)) {
05261       if (authdebug)
05262          ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05263       goto return_unref;
05264    }
05265 
05266    if (!ast_apply_ha(p->ha, sin)) {
05267       if (authdebug)
05268          ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05269       goto return_unref;
05270    }
05271    if (!inaddrcmp(&p->addr, sin))
05272       ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED);
05273    ast_string_field_set(iaxs[callno], secret, p->secret);
05274    ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
05275    /* Check secret against what we have on file */
05276    if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05277       if (!ast_strlen_zero(p->inkeys)) {
05278          char tmpkeys[256];
05279          char *stringp=NULL;
05280          ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys));
05281          stringp=tmpkeys;
05282          keyn = strsep(&stringp, ":");
05283          while(keyn) {
05284             key = ast_key_get(keyn, AST_KEY_PUBLIC);
05285             if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
05286                ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05287                break;
05288             } else if (!key) 
05289                ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
05290             keyn = strsep(&stringp, ":");
05291          }
05292          if (!keyn) {
05293             if (authdebug)
05294                ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
05295             goto return_unref;
05296          }
05297       } else {
05298          if (authdebug)
05299             ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
05300          goto return_unref;
05301       }
05302    } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05303       struct MD5Context md5;
05304       unsigned char digest[16];
05305       char *tmppw, *stringp;
05306       
05307       tmppw = ast_strdupa(p->secret);
05308       stringp = tmppw;
05309       while((tmppw = strsep(&stringp, ";"))) {
05310          MD5Init(&md5);
05311          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
05312          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05313          MD5Final(digest, &md5);
05314          for (x=0;x<16;x++)
05315             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05316          if (!strcasecmp(requeststr, md5secret)) 
05317             break;
05318       }
05319       if (tmppw) {
05320          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05321       } else {
05322          if (authdebug)
05323             ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret);
05324          goto return_unref;
05325       }
05326    } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
05327       /* They've provided a plain text password and we support that */
05328       if (strcmp(secret, p->secret)) {
05329          if (authdebug)
05330             ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05331          goto return_unref;
05332       } else
05333          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05334    } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) {
05335       if (authdebug)
05336          ast_log(LOG_NOTICE, "Inappropriate authentication received\n");
05337       goto return_unref;
05338    }
05339    ast_string_field_set(iaxs[callno], peer, peer);
05340    /* Choose lowest expiry number */
05341    if (expire && (expire < iaxs[callno]->expiry)) 
05342       iaxs[callno]->expiry = expire;
05343 
05344    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05345 
05346    res = 0;
05347 
05348 return_unref:
05349    if (p)
05350       peer_unref(p);
05351 
05352    return res;
05353 }

static int registry_authrequest ( int  callno  )  [static]

Definition at line 5981 of file chan_iax2.c.

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

Referenced by socket_process().

05982 {
05983    struct iax_ie_data ied;
05984    struct iax2_peer *p;
05985    char challenge[10];
05986    const char *peer_name;
05987    int res = -1;
05988 
05989    peer_name = ast_strdupa(iaxs[callno]->peer);
05990 
05991    /* SLD: third call to find_peer in registration */
05992    ast_mutex_unlock(&iaxsl[callno]);
05993    p = find_peer(peer_name, 1);
05994    ast_mutex_lock(&iaxsl[callno]);
05995    if (!iaxs[callno])
05996       goto return_unref;
05997    if (!p) {
05998       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
05999       goto return_unref;
06000    }
06001    
06002    memset(&ied, 0, sizeof(ied));
06003    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
06004    if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06005       /* Build the challenge */
06006       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06007       ast_string_field_set(iaxs[callno], challenge, challenge);
06008       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06009    }
06010    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06011 
06012    res = 0;
06013 
06014 return_unref:
06015    peer_unref(p);
06016 
06017    return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
06018 }

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

Definition at line 6020 of file chan_iax2.c.

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

Referenced by socket_process().

06021 {
06022    struct iax2_registry *reg;
06023    /* Start pessimistic */
06024    struct iax_ie_data ied;
06025    char peer[256] = "";
06026    char challenge[256] = "";
06027    int res;
06028    int authmethods = 0;
06029    if (ies->authmethods)
06030       authmethods = ies->authmethods;
06031    if (ies->username)
06032       ast_copy_string(peer, ies->username, sizeof(peer));
06033    if (ies->challenge)
06034       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
06035    memset(&ied, 0, sizeof(ied));
06036    reg = iaxs[callno]->reg;
06037    if (reg) {
06038          if (inaddrcmp(&reg->addr, sin)) {
06039             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
06040             return -1;
06041          }
06042          if (ast_strlen_zero(reg->secret)) {
06043             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
06044             reg->regstate = REG_STATE_NOAUTH;
06045             return -1;
06046          }
06047          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
06048          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
06049          if (reg->secret[0] == '[') {
06050             char tmpkey[256];
06051             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
06052             tmpkey[strlen(tmpkey) - 1] = '\0';
06053             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL);
06054          } else
06055             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL);
06056          if (!res) {
06057             reg->regstate = REG_STATE_AUTHSENT;
06058             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
06059          } else
06060             return -1;
06061          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
06062    } else   
06063       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
06064    return -1;
06065 }

static char* regstate2str ( int  regstate  )  [static]

Definition at line 4506 of file chan_iax2.c.

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

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

04507 {
04508    switch(regstate) {
04509    case REG_STATE_UNREGISTERED:
04510       return "Unregistered";
04511    case REG_STATE_REGSENT:
04512       return "Request Sent";
04513    case REG_STATE_AUTHSENT:
04514       return "Auth. Sent";
04515    case REG_STATE_REGISTERED:
04516       return "Registered";
04517    case REG_STATE_REJECTED:
04518       return "Rejected";
04519    case REG_STATE_TIMEOUT:
04520       return "Timeout";
04521    case REG_STATE_NOAUTH:
04522       return "No Authentication";
04523    default:
04524       return "Unknown";
04525    }
04526 }

static int reload ( void   )  [static]

Definition at line 9870 of file chan_iax2.c.

References reload_config().

09871 {
09872    return reload_config();
09873 }

static int reload_config ( void   )  [static]

Definition at line 9834 of file chan_iax2.c.

References ao2_callback(), ast_clear_flag, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, config, delete_users(), globalflags, iax2_do_register(), iax2_poke_peer_cb(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, iax_provision_reload(), IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, peers, prune_peers(), prune_users(), reload_firmware(), and set_config().

09835 {
09836    char *config = "iax.conf";
09837    struct iax2_registry *reg;
09838 
09839    strcpy(accountcode, "");
09840    strcpy(language, "");
09841    strcpy(mohinterpret, "default");
09842    strcpy(mohsuggest, "");
09843    amaflags = 0;
09844    delayreject = 0;
09845    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09846    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09847    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09848    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09849    delete_users();
09850    set_config(config, 1);
09851    prune_peers();
09852    prune_users();
09853    AST_LIST_LOCK(&registrations);
09854    AST_LIST_TRAVERSE(&registrations, reg, entry)
09855       iax2_do_register(reg);
09856    AST_LIST_UNLOCK(&registrations);
09857    /* Qualify hosts, too */
09858    ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
09859    reload_firmware();
09860    iax_provision_reload();
09861 
09862    return 0;
09863 }

static void reload_firmware ( void   )  [static]

Definition at line 1724 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(), ast_firmware_list::lock, LOG_WARNING, iax_firmware::next, option_verbose, try_firmware(), VERBOSE_PREFIX_2, ast_firmware_list::wares, and waresl.

Referenced by load_module(), and reload_config().

01725 {
01726    struct iax_firmware *cur, *curl, *curp;
01727    DIR *fwd;
01728    struct dirent *de;
01729    char dir[256];
01730    char fn[256];
01731    /* Mark all as dead */
01732    ast_mutex_lock(&waresl.lock);
01733    cur = waresl.wares;
01734    while(cur) {
01735       cur->dead = 1;
01736       cur = cur->next;
01737    }
01738    /* Now that we've freed them, load the new ones */
01739    snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
01740    fwd = opendir(dir);
01741    if (fwd) {
01742       while((de = readdir(fwd))) {
01743          if (de->d_name[0] != '.') {
01744             snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name);
01745             if (!try_firmware(fn)) {
01746                if (option_verbose > 1)
01747                   ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name);
01748             }
01749          }
01750       }
01751       closedir(fwd);
01752    } else 
01753       ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
01754 
01755    /* Clean up leftovers */
01756    cur = waresl.wares;
01757    curp = NULL;
01758    while(cur) {
01759       curl = cur;
01760       cur = cur->next;
01761       if (curl->dead) {
01762          if (curp) {
01763             curp->next = cur;
01764          } else {
01765             waresl.wares = cur;
01766          }
01767          destroy_firmware(curl);
01768       } else {
01769          curp = cur;
01770       }
01771    }
01772    ast_mutex_unlock(&waresl.lock);
01773 }

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

Definition at line 6518 of file chan_iax2.c.

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

Referenced by socket_process().

06519 {
06520    iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter;
06521    iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24;
06522    iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff;
06523    iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts;
06524    iaxs[fr->callno]->remote_rr.delay = ies->rr_delay;
06525    iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped;
06526    iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo;
06527 }

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

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

Referenced by start_network_thread().

08657 {
08658    int count;
08659    int res;
08660    struct timeval tv;
08661    struct timespec ts;
08662 
08663    for (;;) {
08664       res = ast_sched_wait(sched);
08665       if ((res > 1000) || (res < 0))
08666          res = 1000;
08667       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
08668       ts.tv_sec = tv.tv_sec;
08669       ts.tv_nsec = tv.tv_usec * 1000;
08670 
08671       pthread_testcancel();
08672       ast_mutex_lock(&sched_lock);
08673       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
08674       ast_mutex_unlock(&sched_lock);
08675       pthread_testcancel();
08676 
08677       count = ast_sched_runq(sched);
08678       if (count >= 20)
08679          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
08680    }
08681    return NULL;
08682 }

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 2530 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, chan_iax2_pvt::owner, ast_channel_tech::properties, chan_iax2_pvt::rxcore, sched, ast_channel::tech, iax_frame::ts, type, unwrap_timestamp(), and update_jbsched().

Referenced by socket_process().

02531 {
02532    int type, len;
02533    int ret;
02534    int needfree = 0;
02535 
02536    /* Attempt to recover wrapped timestamps */
02537    unwrap_timestamp(fr);
02538 
02539    /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
02540    if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore))
02541       fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000));
02542    else {
02543 #if 0
02544       ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n");
02545 #endif
02546       fr->af.delivery = ast_tv(0,0);
02547    }
02548 
02549    type = JB_TYPE_CONTROL;
02550    len = 0;
02551 
02552    if(fr->af.frametype == AST_FRAME_VOICE) {
02553       type = JB_TYPE_VOICE;
02554       len = ast_codec_get_samples(&fr->af) / 8;
02555    } else if(fr->af.frametype == AST_FRAME_CNG) {
02556       type = JB_TYPE_SILENCE;
02557    }
02558 
02559    if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
02560       if (tsout)
02561          *tsout = fr->ts;
02562       __do_deliver(fr);
02563       return -1;
02564    }
02565 
02566    /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
02567     * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
02568    if( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) &&
02569        iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner) &&
02570        (ast_bridged_channel(iaxs[fr->callno]->owner)->tech->properties & AST_CHAN_TP_WANTSJITTER)) {
02571       jb_frame frame;
02572 
02573       /* deliver any frames in the jb */
02574       while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
02575          __do_deliver(frame.data);
02576          /* __do_deliver() can make the call disappear */
02577          if (!iaxs[fr->callno])
02578             return -1;
02579       }
02580 
02581       jb_reset(iaxs[fr->callno]->jb);
02582 
02583       if (iaxs[fr->callno]->jbid > -1)
02584          ast_sched_del(sched, iaxs[fr->callno]->jbid);
02585 
02586       iaxs[fr->callno]->jbid = -1;
02587 
02588       /* deliver this frame now */
02589       if (tsout)
02590          *tsout = fr->ts;
02591       __do_deliver(fr);
02592       return -1;
02593    }
02594 
02595    /* insert into jitterbuffer */
02596    /* TODO: Perhaps we could act immediately if it's not droppable and late */
02597    ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
02598          calc_rxstamp(iaxs[fr->callno],fr->ts));
02599    if (ret == JB_DROP) {
02600       needfree++;
02601    } else if (ret == JB_SCHED) {
02602       update_jbsched(iaxs[fr->callno]);
02603    }
02604    if (tsout)
02605       *tsout = fr->ts;
02606    if (needfree) {
02607       /* Free our iax frame */
02608       iax2_frame_free(fr);
02609       return -1;
02610    }
02611    return 0;
02612 }

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

Definition at line 4789 of file chan_iax2.c.

References __send_command().

Referenced by __attempt_transmit(), __send_lagrq(), __send_ping(), authenticate_reply(), authenticate_request(), cache_get_callno_locked(), dp_lookup(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_indicate(), iax2_poke_peer(), iax2_provision(), iax2_start_transfer(), registry_authrequest(), registry_rerequest(), send_command_locked(), and socket_process().

04790 {
04791    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
04792 }

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

04809 {
04810    int call_num = i->callno;
04811    /* It is assumed that the callno has already been locked */
04812    iax2_predestroy(i->callno);
04813    if (!iaxs[call_num])
04814       return -1;
04815    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
04816 }

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

Definition at line 4818 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

04819 {
04820    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
04821 }

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

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

04795 {
04796    int res;
04797    ast_mutex_lock(&iaxsl[callno]);
04798    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
04799    ast_mutex_unlock(&iaxsl[callno]);
04800    return res;
04801 }

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

Definition at line 4823 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

04824 {
04825    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
04826 }

static int send_lagrq ( void *  data  )  [static]

Definition at line 1014 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

01015 {
01016 #ifdef SCHED_MULTITHREADED
01017    if (schedule_action(__send_lagrq, data))
01018 #endif      
01019       __send_lagrq(data);
01020    return 0;
01021 }

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 1846 of file chan_iax2.c.

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

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

01847 {
01848    int res;
01849    int callno;
01850 
01851    if( f == NULL ) {
01852        ast_log(LOG_ERROR, "send_packet( NULL )\n");
01853        ast_backtrace();
01854        return -1;
01855    }
01856    
01857    callno = f->callno;
01858 
01859    /* Don't send if there was an error, but return error instead */
01860    if (!callno || !iaxs[callno] || iaxs[callno]->error)
01861        return -1;
01862    
01863    /* Called with iaxsl held */
01864    if (option_debug > 2 && iaxdebug)
01865       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));
01866    if (f->transfer) {
01867       if (iaxdebug)
01868          iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
01869       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer,
01870                sizeof(iaxs[callno]->transfer));
01871    } else {
01872       if (iaxdebug)
01873          iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
01874       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr,
01875                sizeof(iaxs[callno]->addr));
01876    }
01877    if (res < 0) {
01878       if (option_debug && iaxdebug)
01879          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
01880       handle_error();
01881    } else
01882       res = 0;
01883    return res;
01884 }

static int send_ping ( void *  data  )  [static]

Definition at line 979 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

00980 {
00981 #ifdef SCHED_MULTITHREADED
00982    if (schedule_action(__send_ping, data))
00983 #endif      
00984       __send_ping(data);
00985    return 0;
00986 }

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

Definition at line 6203 of file chan_iax2.c.

References iax2_trunk_peer::addr, iax_frame::afdata, ast_inet_ntoa(), ast_log(), ast_test_flag, calc_txpeerstamp(), iax2_trunk_peer::calls, ast_iax2_meta_hdr::cmddata, iax_frame::data, ast_iax2_meta_hdr::data, iax_frame::datalen, iax_frame::direction, DIRECTION_OUTGRESS, globalflags, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_hdr::metacmd, 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().

06204 {
06205    int res = 0;
06206    struct iax_frame *fr;
06207    struct ast_iax2_meta_hdr *meta;
06208    struct ast_iax2_meta_trunk_hdr *mth;
06209    int calls = 0;
06210    
06211    /* Point to frame */
06212    fr = (struct iax_frame *)tpeer->trunkdata;
06213    /* Point to meta data */
06214    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
06215    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
06216    if (tpeer->trunkdatalen) {
06217       /* We're actually sending a frame, so fill the meta trunk header and meta header */
06218       meta->zeros = 0;
06219       meta->metacmd = IAX_META_TRUNK;
06220       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
06221          meta->cmddata = IAX_META_TRUNK_MINI;
06222       else
06223          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
06224       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
06225       /* And the rest of the ast_iax2 header */
06226       fr->direction = DIRECTION_OUTGRESS;
06227       fr->retrans = -1;
06228       fr->transfer = 0;
06229       /* Any appropriate call will do */
06230       fr->data = fr->afdata;
06231       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
06232       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
06233       calls = tpeer->calls;
06234 #if 0
06235       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));
06236 #endif      
06237       /* Reset transmit trunk side data */
06238       tpeer->trunkdatalen = 0;
06239       tpeer->calls = 0;
06240    }
06241    if (res < 0)
06242       return res;
06243    return calls;
06244 }

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

Load configuration.

Definition at line 9481 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, format, gen, get_encrypt_methods(), globalflags, iax2_register(), IAX_CAPABILITY_FULLBANDWIDTH, IAX_CAPABILITY_LOWBANDWIDTH, IAX_CAPABILITY_MEDBANDWIDTH, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_RTUPDATE, IAX_TRANSFERMEDIA, IAX_TRUNKTIMESTAMPS, IAX_USEJITTERBUF, iaxmaxthreadcount, iaxthreadcount, io, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MAX_PEER_BUCKETS, ast_variable::name, netsock, ast_variable::next, option_verbose, outsock, peers, portno, prefs, reg_source_db(), secret, set_timing(), socket_read(), users, ast_variable::value, and VERBOSE_PREFIX_2.

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

09482 {
09483    struct ast_config *cfg, *ucfg;
09484    int capability=iax2_capability;
09485    struct ast_variable *v;
09486    char *cat;
09487    const char *utype;
09488    const char *tosval;
09489    int format;
09490    int portno = IAX_DEFAULT_PORTNO;
09491    int  x;
09492    struct iax2_user *user;
09493    struct iax2_peer *peer;
09494    struct ast_netsock *ns;
09495 #if 0
09496    static unsigned short int last_port=0;
09497 #endif
09498 
09499    cfg = ast_config_load(config_file);
09500    
09501    if (!cfg) {
09502       ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
09503       return -1;
09504    }
09505 
09506    /* Reset global codec prefs */   
09507    memset(&prefs, 0 , sizeof(struct ast_codec_pref));
09508    
09509    /* Reset Global Flags */
09510    memset(&globalflags, 0, sizeof(globalflags));
09511    ast_set_flag(&globalflags, IAX_RTUPDATE);
09512 
09513 #ifdef SO_NO_CHECK
09514    nochecksums = 0;
09515 #endif
09516 
09517    min_reg_expire = IAX_DEFAULT_REG_EXPIRE;
09518    max_reg_expire = IAX_DEFAULT_REG_EXPIRE;
09519 
09520    maxauthreq = 3;
09521 
09522    v = ast_variable_browse(cfg, "general");
09523 
09524    /* Seed initial tos value */
09525    tosval = ast_variable_retrieve(cfg, "general", "tos");
09526    if (tosval) {
09527       if (ast_str2tos(tosval, &tos))
09528          ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n");
09529    }
09530    while(v) {
09531       if (!strcasecmp(v->name, "bindport")){ 
09532          if (reload)
09533             ast_log(LOG_NOTICE, "Ignoring bindport on reload\n");
09534          else
09535             portno = atoi(v->value);
09536       } else if (!strcasecmp(v->name, "pingtime")) 
09537          ping_time = atoi(v->value);
09538       else if (!strcasecmp(v->name, "iaxthreadcount")) {
09539          if (reload) {
09540             if (atoi(v->value) != iaxthreadcount)
09541                ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n");
09542          } else {
09543             iaxthreadcount = atoi(v->value);
09544             if (iaxthreadcount < 1) {
09545                ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n");
09546                iaxthreadcount = 1;
09547             } else if (iaxthreadcount > 256) {
09548                ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n");
09549                iaxthreadcount = 256;
09550             }
09551          }
09552       } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) {
09553          if (reload) {
09554             AST_LIST_LOCK(&dynamic_list);
09555             iaxmaxthreadcount = atoi(v->value);
09556             AST_LIST_UNLOCK(&dynamic_list);
09557          } else {
09558             iaxmaxthreadcount = atoi(v->value);
09559             if (iaxmaxthreadcount < 0) {
09560                ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n");
09561                iaxmaxthreadcount = 0;
09562             } else if (iaxmaxthreadcount > 256) {
09563                ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n");
09564                iaxmaxthreadcount = 256;
09565             }
09566          }
09567       } else if (!strcasecmp(v->name, "nochecksums")) {
09568 #ifdef SO_NO_CHECK
09569          if (ast_true(v->value))
09570             nochecksums = 1;
09571          else
09572             nochecksums = 0;
09573 #else
09574          if (ast_true(v->value))
09575             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
09576 #endif
09577       }
09578       else if (!strcasecmp(v->name, "maxjitterbuffer")) 
09579          maxjitterbuffer = atoi(v->value);
09580       else if (!strcasecmp(v->name, "resyncthreshold")) 
09581          resyncthreshold = atoi(v->value);
09582       else if (!strcasecmp(v->name, "maxjitterinterps")) 
09583          maxjitterinterps = atoi(v->value);
09584       else if (!strcasecmp(v->name, "lagrqtime")) 
09585          lagrq_time = atoi(v->value);
09586       else if (!strcasecmp(v->name, "maxregexpire")) 
09587          max_reg_expire = atoi(v->value);
09588       else if (!strcasecmp(v->name, "minregexpire")) 
09589          min_reg_expire = atoi(v->value);
09590       else if (!strcasecmp(v->name, "bindaddr")) {
09591          if (reload) {
09592             ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n");
09593          } else {
09594             if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) {
09595                ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno);
09596             } else {
09597                if (option_verbose > 1) {
09598                   if (strchr(v->value, ':'))
09599                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value);
09600                   else
09601                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno);
09602                }
09603                if (defaultsockfd < 0) 
09604                   defaultsockfd = ast_netsock_sockfd(ns);
09605                ast_netsock_unref(ns);
09606             }
09607          }
09608       } else if (!strcasecmp(v->name, "authdebug"))
09609          authdebug = ast_true(v->value);
09610       else if (!strcasecmp(v->name, "encryption"))
09611          iax2_encryption = get_encrypt_methods(v->value);
09612       else if (!strcasecmp(v->name, "notransfer")) {
09613          ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09614          ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09615          ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER);   
09616       } else if (!strcasecmp(v->name, "transfer")) {
09617          if (!strcasecmp(v->value, "mediaonly")) {
09618             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 
09619          } else if (ast_true(v->value)) {
09620             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09621          } else 
09622             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09623       } else if (!strcasecmp(v->name, "codecpriority")) {
09624          if(!strcasecmp(v->value, "caller"))
09625             ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST);
09626          else if(!strcasecmp(v->value, "disabled"))
09627             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
09628          else if(!strcasecmp(v->value, "reqonly")) {
09629             ast_set_flag((&globalflags), IAX_CODEC_NOCAP);
09630             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
09631          }
09632       } else if (!strcasecmp(v->name, "jitterbuffer"))
09633          ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 
09634       else if (!strcasecmp(v->name, "forcejitterbuffer"))
09635          ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);  
09636       else if (!strcasecmp(v->name, "delayreject"))
09637          delayreject = ast_true(v->value);
09638       else if (!strcasecmp(v->name, "rtcachefriends"))
09639          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS);  
09640       else if (!strcasecmp(v->name, "rtignoreregexpire"))
09641          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE);  
09642       else if (!strcasecmp(v->name, "rtupdate"))
09643          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE);
09644       else if (!strcasecmp(v->name, "trunktimestamps"))
09645          ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS);
09646       else if (!strcasecmp(v->name, "rtautoclear")) {
09647          int i = atoi(v->value);
09648          if(i > 0)
09649             global_rtautoclear = i;
09650          else
09651             i = 0;
09652          ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR);   
09653       } else if (!strcasecmp(v->name, "trunkfreq")) {
09654          trunkfreq = atoi(v->value);
09655          if (trunkfreq < 10)
09656             trunkfreq = 10;
09657       } else if (!strcasecmp(v->name, "autokill")) {
09658          if (sscanf(v->value, "%d", &x) == 1) {
09659             if (x >= 0)
09660                autokill = x;
09661             else
09662                ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
09663          } else if (ast_true(v->value)) {
09664             autokill = DEFAULT_MAXMS;
09665          } else {
09666             autokill = 0;
09667          }
09668       } else if (!strcasecmp(v->name, "bandwidth")) {
09669          if (!strcasecmp(v->value, "low")) {
09670             capability = IAX_CAPABILITY_LOWBANDWIDTH;
09671          } else if (!strcasecmp(v->value, "medium")) {
09672             capability = IAX_CAPABILITY_MEDBANDWIDTH;
09673          } else if (!strcasecmp(v->value, "high")) {
09674             capability = IAX_CAPABILITY_FULLBANDWIDTH;
09675          } else
09676             ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n");
09677       } else if (!strcasecmp(v->name, "allow")) {
09678          ast_parse_allow_disallow(&prefs, &capability, v->value, 1);
09679       } else if (!strcasecmp(v->name, "disallow")) {
09680          ast_parse_allow_disallow(&prefs, &capability, v->value, 0);
09681       } else if (!strcasecmp(v->name, "register")) {
09682          iax2_register(v->value, v->lineno);
09683       } else if (!strcasecmp(v->name, "iaxcompat")) {
09684          iaxcompat = ast_true(v->value);
09685       } else if (!strcasecmp(v->name, "regcontext")) {
09686          ast_copy_string(regcontext, v->value, sizeof(regcontext));
09687          /* Create context if it doesn't exist already */
09688          if (!ast_context_find(regcontext))
09689             ast_context_create(NULL, regcontext, "IAX2");
09690       } else if (!strcasecmp(v->name, "tos")) {
09691          if (ast_str2tos(v->value, &tos))
09692             ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno);
09693       } else if (!strcasecmp(v->name, "accountcode")) {
09694          ast_copy_string(accountcode, v->value, sizeof(accountcode));
09695       } else if (!strcasecmp(v->name, "mohinterpret")) {
09696          ast_copy_string(mohinterpret, v->value, sizeof(user->mohinterpret));
09697       } else if (!strcasecmp(v->name, "mohsuggest")) {
09698          ast_copy_string(mohsuggest, v->value, sizeof(user->mohsuggest));
09699       } else if (!strcasecmp(v->name, "amaflags")) {
09700          format = ast_cdr_amaflags2int(v->value);
09701          if (format < 0) {
09702             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
09703          } else {
09704             amaflags = format;
09705          }
09706       } else if (!strcasecmp(v->name, "language")) {
09707          ast_copy_string(language, v->value, sizeof(language));
09708       } else if (!strcasecmp(v->name, "maxauthreq")) {
09709          maxauthreq = atoi(v->value);
09710          if (maxauthreq < 0)
09711             maxauthreq = 0;
09712       } else if (!strcasecmp(v->name, "adsi")) {
09713          adsi = ast_true(v->value);
09714       } /*else if (strcasecmp(v->name,"type")) */
09715       /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09716       v = v->next;
09717    }
09718    
09719    if (defaultsockfd < 0) {
09720       if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) {
09721          ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
09722       } else {
09723          if (option_verbose > 1)
09724             ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno);
09725          defaultsockfd = ast_netsock_sockfd(ns);
09726          ast_netsock_unref(ns);
09727       }
09728    }
09729    if (reload) {
09730       ast_netsock_release(outsock);
09731       outsock = ast_netsock_list_alloc();
09732       if (!outsock) {
09733          ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
09734          return -1;
09735       }
09736       ast_netsock_init(outsock);
09737    }
09738 
09739    if (min_reg_expire > max_reg_expire) {
09740       ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n",
09741          min_reg_expire, max_reg_expire, max_reg_expire);
09742       min_reg_expire = max_reg_expire;
09743    }
09744    iax2_capability = capability;
09745    
09746    ucfg = ast_config_load("users.conf");
09747    if (ucfg) {
09748       struct ast_variable *gen;
09749       int genhasiax;
09750       int genregisteriax;
09751       const char *hasiax, *registeriax;
09752       
09753       genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax"));
09754       genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax"));
09755       gen = ast_variable_browse(ucfg, "general");
09756       cat = ast_category_browse(ucfg, NULL);
09757       while (cat) {
09758          if (strcasecmp(cat, "general")) {
09759             hasiax = ast_variable_retrieve(ucfg, cat, "hasiax");
09760             registeriax = ast_variable_retrieve(ucfg, cat, "registeriax");
09761             if (ast_true(hasiax) || (!hasiax && genhasiax)) {
09762                /* Start with general parameters, then specific parameters, user and peer */
09763                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
09764                if (user) {
09765                   __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
09766                   user = NULL;
09767                }
09768                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
09769                if (peer) {
09770                   if (ast_test_flag(peer, IAX_DYNAMIC))
09771                      reg_source_db(peer);
09772                   __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
09773                   peer = NULL;
09774                }
09775             }
09776             if (ast_true(registeriax) || (!registeriax && genregisteriax)) {
09777                char tmp[256];
09778                const char *host = ast_variable_retrieve(ucfg, cat, "host");
09779                const char *username = ast_variable_retrieve(ucfg, cat, "username");
09780                const char *secret = ast_variable_retrieve(ucfg, cat, "secret");
09781                if (!host)
09782                   host = ast_variable_retrieve(ucfg, "general", "host");
09783                if (!username)
09784                   username = ast_variable_retrieve(ucfg, "general", "username");
09785                if (!secret)
09786                   secret = ast_variable_retrieve(ucfg, "general", "secret");
09787                if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
09788                   if (!ast_strlen_zero(secret))
09789                      snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host);
09790                   else
09791                      snprintf(tmp, sizeof(tmp), "%s@%s", username, host);
09792                   iax2_register(tmp, 0);
09793                }
09794             }
09795          }
09796          cat = ast_category_browse(ucfg, cat);
09797       }
09798       ast_config_destroy(ucfg);
09799    }
09800    
09801    cat = ast_category_browse(cfg, NULL);
09802    while(cat) {
09803       if (strcasecmp(cat, "general")) {
09804          utype = ast_variable_retrieve(cfg, cat, "type");
09805          if (utype) {
09806             if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
09807                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
09808                if (user) {
09809                   __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
09810                   user = NULL;
09811                }
09812             }
09813             if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
09814                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
09815                if (peer) {
09816                   if (ast_test_flag(peer, IAX_DYNAMIC))
09817                      reg_source_db(peer);
09818                   __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
09819                   peer = NULL;
09820                }
09821             } else if (strcasecmp(utype, "user")) {
09822                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file);
09823             }
09824          } else
09825             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
09826       }
09827       cat = ast_category_browse(cfg, cat);
09828    }
09829    ast_config_destroy(cfg);
09830    set_timing();
09831    return capability;
09832 }

static void set_timing ( void   )  [static]

Definition at line 9464 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09465 {
09466 #ifdef HAVE_ZAPTEL
09467    int bs = trunkfreq * 8;
09468    if (timingfd > -1) {
09469       if (
09470 #ifdef ZT_TIMERACK
09471          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09472 #endif         
09473          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09474          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09475    }
09476 #endif
09477 }

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

Definition at line 755 of file chan_iax2.c.

References ast_cond_signal(), ast_mutex_lock(), and ast_mutex_unlock().

Referenced by __schedule_action(), iax2_transmit(), network_thread(), socket_read(), and update_jbsched().

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

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 6670 of file chan_iax2.c.

References chan_iax2_pvt::addr, 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_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_add(), ast_sched_del(), ast_set_flag, ast_set_read_format(), ast_set_write_format(), AST_STATE_RING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose(), auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, calc_timestamp(), iax2_peer::callno, iax2_dpcache::callno, chan_iax2_pvt::callno, iax_frame::callno, ast_iax2_mini_hdr::callno, check_access(), check_provisioning(), cid_num, complete_dpreply(), complete_transfer(), construct_rr(), ast_channel::context, decrypt_frame(), dp_lookup(), EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, f, iax_frame::final, find_callno(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, format, chan_iax2_pvt::frames_received, iax2_peer::historicms, iax2_ack_registry(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_queue_control_data(), iax2_send(), iax2_vnak(), IAX_ALREADYGONE, IAX_AUTH_MD5, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, IAX_COMMAND_DIAL, IAX_COMMAND_DPREP, IAX_COMMAND_DPREQ, IAX_COMMAND_FWDATA, IAX_COMMAND_FWDOWNL, IAX_COMMAND_HANGUP, IAX_COMMAND_INVAL, IAX_COMMAND_LAGRP, IAX_COMMAND_LAGRQ, IAX_COMMAND_NEW, IAX_COMMAND_PING, IAX_COMMAND_POKE, IAX_COMMAND_PONG, IAX_COMMAND_QUELCH, IAX_COMMAND_REGACK, IAX_COMMAND_REGAUTH, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, IAX_COMMAND_TRANSFER, IAX_COMMAND_TXACC, IAX_COMMAND_TXCNT, IAX_COMMAND_TXMEDIA, IAX_COMMAND_TXREADY, IAX_COMMAND_TXREJ, IAX_COMMAND_TXREL, IAX_COMMAND_TXREQ, IAX_COMMAND_UNQUELCH, IAX_COMMAND_UNSUPPORT, IAX_COMMAND_VNAK, IAX_DELAYPBXSTART, IAX_ENCRYPTED, iax_firmware_append(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_wrap(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLNO, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_FORMAT, IAX_IE_IAX_UNKNOWN, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_STATE_UNCHANGED, IAX_TRUNK, iaxfrdup2(), iaxq, iaxs, iaxsl, ies, inaddrcmp(), chan_iax2_pvt::initid, chan_iax2_pvt::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_iax2_meta_trunk_mini::len, len, ast_channel::lock, iax2_trunk_peer::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_trunk(), manager_event(), iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, NEW_ALLOW, NEW_PREVENT, option_debug, option_verbose, iax_frame::oseqno, chan_iax2_pvt::oseqno, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), iax2_dpcache::peer, chan_iax2_pvt::peercallno, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, raw_hangup(), REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), iax_frame::retries, chan_iax2_pvt::rseqno, iax2_trunk_peer::rxtrunktime, S_OR, save_rr(), sched, schedule_delivery(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax2_peer::smoothing, spawn_dp_lookup(), chan_iax2_pvt::state, stop_stuff(), thread, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, iax2_trunk_peer::trunkact, try_transfer(), iax_frame::ts, ast_iax2_mini_hdr::ts, uncompress_subclass(), update_registry(), VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, chan_iax2_pvt::videoformat, vnak_retransmit(), chan_iax2_pvt::voiceformat, and ast_iax2_meta_hdr::zeros.

Referenced by handle_deferred_full_frames().

06671 {
06672    struct sockaddr_in sin;
06673    int res;
06674    int updatehistory=1;
06675    int new = NEW_PREVENT;
06676    void *ptr;
06677    int dcallno = 0;
06678    struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf;
06679    struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf;
06680    struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf;
06681    struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf;
06682    struct ast_iax2_meta_trunk_hdr *mth;
06683    struct ast_iax2_meta_trunk_entry *mte;
06684    struct ast_iax2_meta_trunk_mini *mtm;
06685    struct iax_frame *fr;
06686    struct iax_frame *cur;
06687    struct ast_frame f = { 0, };
06688    struct ast_channel *c;
06689    struct iax2_dpcache *dp;
06690    struct iax2_peer *peer;
06691    struct iax2_trunk_peer *tpeer;
06692    struct timeval rxtrunktime;
06693    struct iax_ies ies;
06694    struct iax_ie_data ied0, ied1;
06695    int format;
06696    int fd;
06697    int exists;
06698    int minivid = 0;
06699    unsigned int ts;
06700    char empty[32]="";      /* Safety measure */
06701    struct iax_frame *duped_fr;
06702    char host_pref_buf[128];
06703    char caller_pref_buf[128];
06704    struct ast_codec_pref pref;
06705    char *using_prefs = "mine";
06706 
06707    /* allocate an iax_frame with 4096 bytes of data buffer */
06708    fr = alloca(sizeof(*fr) + 4096);
06709    fr->callno = 0;
06710    fr->afdatalen = 4096; /* From alloca() above */
06711 
06712    /* Copy frequently used parameters to the stack */
06713    res = thread->buf_len;
06714    fd = thread->iofd;
06715    memcpy(&sin, &thread->iosin, sizeof(sin));
06716 
06717    if (res < sizeof(*mh)) {
06718       ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*mh));
06719       return 1;
06720    }
06721    if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) {
06722       if (res < sizeof(*vh)) {
06723          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));
06724          return 1;
06725       }
06726 
06727       /* This is a video frame, get call number */
06728       fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd);
06729       minivid = 1;
06730    } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) {
06731       unsigned char metatype;
06732 
06733       if (res < sizeof(*meta)) {
06734          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));
06735          return 1;
06736       }
06737 
06738       /* This is a meta header */
06739       switch(meta->metacmd) {
06740       case IAX_META_TRUNK:
06741          if (res < (sizeof(*meta) + sizeof(*mth))) {
06742             ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %zd min)\n", res,
06743                sizeof(*meta) + sizeof(*mth));
06744             return 1;
06745          }
06746          mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data);
06747          ts = ntohl(mth->ts);
06748          metatype = meta->cmddata;
06749          res -= (sizeof(*meta) + sizeof(*mth));
06750          ptr = mth->data;
06751          tpeer = find_tpeer(&sin, fd);
06752          if (!tpeer) {
06753             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));
06754             return 1;
06755          }
06756          tpeer->trunkact = ast_tvnow();
06757          if (!ts || ast_tvzero(tpeer->rxtrunktime))
06758             tpeer->rxtrunktime = tpeer->trunkact;
06759          rxtrunktime = tpeer->rxtrunktime;
06760          ast_mutex_unlock(&tpeer->lock);
06761          while(res >= sizeof(*mte)) {
06762             /* Process channels */
06763             unsigned short callno, trunked_ts, len;
06764 
06765             if (metatype == IAX_META_TRUNK_MINI) {
06766                mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
06767                ptr += sizeof(*mtm);
06768                res -= sizeof(*mtm);
06769                len = ntohs(mtm->len);
06770                callno = ntohs(mtm->mini.callno);
06771                trunked_ts = ntohs(mtm->mini.ts);
06772             } else if (metatype == IAX_META_TRUNK_SUPERMINI) {
06773                mte = (struct ast_iax2_meta_trunk_entry *)ptr;
06774                ptr += sizeof(*mte);
06775                res -= sizeof(*mte);
06776                len = ntohs(mte->len);
06777                callno = ntohs(mte->callno);
06778                trunked_ts = 0;
06779             } else {
06780                ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
06781                break;
06782             }
06783             /* Stop if we don't have enough data */
06784             if (len > res)
06785                break;
06786             fr->callno = find_callno(callno & ~IAX_FLAG_FULL, 0, &sin, NEW_PREVENT, fd);
06787             if (fr->callno) {
06788                ast_mutex_lock(&iaxsl[fr->callno]);
06789                /* If it's a valid call, deliver the contents.  If not, we
06790                   drop it, since we don't have a scallno to use for an INVAL */
06791                /* Process as a mini frame */
06792                memset(&f, 0, sizeof(f));
06793                f.frametype = AST_FRAME_VOICE;
06794                if (iaxs[fr->callno]) {
06795                   if (iaxs[fr->callno]->voiceformat > 0) {
06796                      f.subclass = iaxs[fr->callno]->voiceformat;
06797                      f.datalen = len;
06798                      if (f.datalen >= 0) {
06799                         if (f.datalen)
06800                            f.data = ptr;
06801                         if(trunked_ts) {
06802                            fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff);
06803                         } else
06804                            fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts);
06805                         /* Don't pass any packets until we're started */
06806                         if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
06807                            /* Common things */
06808                            f.src = "IAX2";
06809                            if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 
06810                               f.samples = ast_codec_get_samples(&f);
06811                            iax_frame_wrap(fr, &f);
06812                            duped_fr = iaxfrdup2(fr);
06813                            if (duped_fr) {
06814                               schedule_delivery(duped_fr, updatehistory, 1, &fr->ts);
06815                            }
06816                            /* It is possible for the pvt structure to go away after we call schedule_delivery */
06817                            if (fr && fr->callno && iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) {
06818                               iaxs[fr->callno]->last = fr->ts;
06819 #if 1
06820                               if (option_debug && iaxdebug)
06821                                  ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts);
06822 #endif
06823                            }
06824                         }
06825                      } else {
06826                         ast_log(LOG_WARNING, "Datalen < 0?\n");
06827                      }
06828                   } else {
06829                      ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n ");
06830                      iax2_vnak(fr->callno);
06831                   }
06832                }
06833                ast_mutex_unlock(&iaxsl[fr->callno]);
06834             }
06835             ptr += len;
06836             res -= len;
06837          }
06838          
06839       }
06840       return 1;
06841    }
06842 
06843 #ifdef DEBUG_SUPPORT
06844    if (iaxdebug && (res >= sizeof(*fh)))
06845       iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh));
06846 #endif
06847    if (ntohs(mh->callno) & IAX_FLAG_FULL) {
06848       if (res < sizeof(*fh)) {
06849          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));
06850          return 1;
06851       }
06852 
06853       /* Get the destination call number */
06854       dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS;
06855       /* Retrieve the type and subclass */
06856       f.frametype = fh->type;
06857       if (f.frametype == AST_FRAME_VIDEO) {
06858          f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
06859       } else {
06860          f.subclass = uncompress_subclass(fh->csub);
06861       }
06862       if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) ||
06863                          (f.subclass == IAX_COMMAND_POKE) || (f.subclass == IAX_COMMAND_FWDOWNL) ||
06864                          (f.subclass == IAX_COMMAND_REGREL)))
06865          new = NEW_ALLOW;
06866    } else {
06867       /* Don't know anything about it yet */
06868       f.frametype = AST_FRAME_NULL;
06869       f.subclass = 0;
06870    }
06871 
06872    if (!fr->callno)
06873       fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd);
06874 
06875    if (fr->callno > 0)
06876       ast_mutex_lock(&iaxsl[fr->callno]);
06877 
06878    if (!fr->callno || !iaxs[fr->callno]) {
06879       /* A call arrived for a nonexistent destination.  Unless it's an "inval"
06880          frame, reply with an inval */
06881       if (ntohs(mh->callno) & IAX_FLAG_FULL) {
06882          /* We can only raw hangup control frames */
06883          if (((f.subclass != IAX_COMMAND_INVAL) &&
06884              (f.subclass != IAX_COMMAND_TXCNT) &&
06885              (f.subclass != IAX_COMMAND_TXACC) &&
06886              (f.subclass != IAX_COMMAND_FWDOWNL))||
06887              (f.frametype != AST_FRAME_IAX))
06888             raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL,
06889             fd);
06890       }
06891       if (fr->callno > 0) 
06892          ast_mutex_unlock(&iaxsl[fr->callno]);
06893       return 1;
06894    }
06895    if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) {
06896       if (decrypt_frame(fr->callno, fh, &f, &res)) {
06897          ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n");
06898          ast_mutex_unlock(&iaxsl[fr->callno]);
06899          return 1;
06900       }
06901 #ifdef DEBUG_SUPPORT
06902       else if (iaxdebug)
06903          iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh));
06904 #endif
06905    }
06906 
06907    /* count this frame */
06908    iaxs[fr->callno]->frames_received++;
06909 
06910    if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid &&
06911       f.subclass != IAX_COMMAND_TXCNT &&     /* for attended transfer */
06912       f.subclass != IAX_COMMAND_TXACC)    /* for attended transfer */
06913       iaxs[fr->callno]->peercallno = (unsigned short)(ntohs(mh->callno) & ~IAX_FLAG_FULL);
06914    if (ntohs(mh->callno) & IAX_FLAG_FULL) {
06915       if (option_debug  && iaxdebug)
06916          ast_log(LOG_DEBUG, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass);
06917       /* Check if it's out of order (and not an ACK or INVAL) */
06918       fr->oseqno = fh->oseqno;
06919       fr->iseqno = fh->iseqno;
06920       fr->ts = ntohl(fh->ts);
06921 #ifdef IAXTESTS
06922       if (test_resync) {
06923          if (option_debug)
06924             ast_log(LOG_DEBUG, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync);
06925          fr->ts += test_resync;
06926       }
06927 #endif /* IAXTESTS */
06928 #if 0
06929       if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) ||
06930            ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX &&
06931                         (f.subclass == IAX_COMMAND_NEW ||
06932                          f.subclass == IAX_COMMAND_AUTHREQ ||
06933                          f.subclass == IAX_COMMAND_ACCEPT ||
06934                          f.subclass == IAX_COMMAND_REJECT))      ) )
06935 #endif
06936       if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE))
06937          updatehistory = 0;
06938       if ((iaxs[fr->callno]->iseqno != fr->oseqno) &&
06939          (iaxs[fr->callno]->iseqno ||
06940             ((f.subclass != IAX_COMMAND_TXCNT) &&
06941             (f.subclass != IAX_COMMAND_TXREADY) &&    /* for attended transfer */
06942             (f.subclass != IAX_COMMAND_TXREL) &&      /* for attended transfer */
06943             (f.subclass != IAX_COMMAND_UNQUELCH ) &&  /* for attended transfer */
06944             (f.subclass != IAX_COMMAND_TXACC)) ||
06945             (f.frametype != AST_FRAME_IAX))) {
06946          if (
06947           ((f.subclass != IAX_COMMAND_ACK) &&
06948            (f.subclass != IAX_COMMAND_INVAL) &&
06949            (f.subclass != IAX_COMMAND_TXCNT) &&
06950            (f.subclass != IAX_COMMAND_TXREADY) &&     /* for attended transfer */
06951            (f.subclass != IAX_COMMAND_TXREL) &&    /* for attended transfer */
06952            (f.subclass != IAX_COMMAND_UNQUELCH ) &&   /* for attended transfer */
06953            (f.subclass != IAX_COMMAND_TXACC) &&
06954            (f.subclass != IAX_COMMAND_VNAK)) ||
06955            (f.frametype != AST_FRAME_IAX)) {
06956             /* If it's not an ACK packet, it's out of order. */
06957             if (option_debug)
06958                ast_log(LOG_DEBUG, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 
06959                iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass);
06960             /* Check to see if we need to request retransmission,
06961              * and take sequence number wraparound into account */
06962             if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) {
06963                /* If we've already seen it, ack it XXX There's a border condition here XXX */
06964                if ((f.frametype != AST_FRAME_IAX) || 
06965                      ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) {
06966                   if (option_debug)
06967                      ast_log(LOG_DEBUG, "Acking anyway\n");
06968                   /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if
06969                      we have anything to send, we'll retransmit and get an ACK back anyway XXX */
06970                   send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
06971                }
06972             } else {
06973                /* Send a VNAK requesting retransmission */
06974                iax2_vnak(fr->callno);
06975             }
06976             ast_mutex_unlock(&iaxsl[fr->callno]);
06977             return 1;
06978          }
06979       } else {
06980          /* Increment unless it's an ACK or VNAK */
06981          if (((f.subclass != IAX_COMMAND_ACK) &&
06982              (f.subclass != IAX_COMMAND_INVAL) &&
06983              (f.subclass != IAX_COMMAND_TXCNT) &&
06984              (f.subclass != IAX_COMMAND_TXACC) &&
06985             (f.subclass != IAX_COMMAND_VNAK)) ||
06986              (f.frametype != AST_FRAME_IAX))
06987             iaxs[fr->callno]->iseqno++;
06988       }
06989       /* A full frame */
06990       if (res < sizeof(*fh)) {
06991          ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*fh));
06992          ast_mutex_unlock(&iaxsl[fr->callno]);
06993          return 1;
06994       }
06995       /* Ensure text frames are NULL-terminated */
06996       if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') {
06997          if (res < thread->buf_size)
06998             thread->buf[res++] = '\0';
06999          else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */
07000             thread->buf[res - 1] = '\0';
07001       }
07002       f.datalen = res - sizeof(*fh);
07003 
07004       /* Handle implicit ACKing unless this is an INVAL, and only if this is 
07005          from the real peer, not the transfer peer */
07006       if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 
07007           ((f.subclass != IAX_COMMAND_INVAL) ||
07008            (f.frametype != AST_FRAME_IAX))) {
07009          unsigned char x;
07010          int call_to_destroy;
07011          /* XXX This code is not very efficient.  Surely there is a better way which still
07012                 properly handles boundary conditions? XXX */
07013          /* First we have to qualify that the ACKed value is within our window */
07014          for (x=iaxs[fr->callno]->rseqno; x != iaxs[fr->callno]->oseqno; x++)
07015             if (fr->iseqno == x)
07016                break;
07017          if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) {
07018             /* The acknowledgement is within our window.  Time to acknowledge everything
07019                that it says to */
07020             for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) {
07021                /* Ack the packet with the given timestamp */
07022                if (option_debug && iaxdebug)
07023                   ast_log(LOG_DEBUG, "Cancelling transmission of packet %d\n", x);
07024                call_to_destroy = 0;
07025                AST_LIST_LOCK(&iaxq.queue);
07026                AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
07027                   /* If it's our call, and our timestamp, mark -1 retries */
07028                   if ((fr->callno == cur->callno) && (x == cur->oseqno)) {
07029                      cur->retries = -1;
07030                      /* Destroy call if this is the end */
07031                      if (cur->final)
07032                         call_to_destroy = fr->callno;
07033                   }
07034                }
07035                AST_LIST_UNLOCK(&iaxq.queue);
07036                if (call_to_destroy) {
07037                   if (iaxdebug && option_debug)
07038                      ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", call_to_destroy);
07039                   iax2_destroy(call_to_destroy);
07040                }
07041             }
07042             /* Note how much we've received acknowledgement for */
07043             if (iaxs[fr->callno])
07044                iaxs[fr->callno]->rseqno = fr->iseqno;
07045             else {
07046                /* Stop processing now */
07047                ast_mutex_unlock(&iaxsl[fr->callno]);
07048                return 1;
07049             }
07050          } else
07051             ast_log(LOG_DEBUG, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno);
07052       }
07053       if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 
07054          ((f.frametype != AST_FRAME_IAX) || 
07055           ((f.subclass != IAX_COMMAND_TXACC) &&
07056            (f.subclass != IAX_COMMAND_TXCNT)))) {
07057          /* Only messages we accept from a transfer host are TXACC and TXCNT */
07058          ast_mutex_unlock(&iaxsl[fr->callno]);
07059          return 1;
07060       }
07061 
07062       if (f.datalen) {
07063          if (f.frametype == AST_FRAME_IAX) {
07064             if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) {
07065                ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr));
07066                ast_mutex_unlock(&iaxsl[fr->callno]);
07067                return 1;
07068             }
07069             f.data = NULL;
07070             f.datalen = 0;
07071          } else
07072             f.data = thread->buf + sizeof(*fh);
07073       } else {
07074          if (f.frametype == AST_FRAME_IAX)
07075             f.data = NULL;
07076          else
07077             f.data = empty;
07078          memset(&ies, 0, sizeof(ies));
07079       }
07080 
07081       /* when we receive the first full frame for a new incoming channel,
07082          it is safe to start the PBX on the channel because we have now
07083          completed a 3-way handshake with the peer */
07084       if ((f.frametype == AST_FRAME_VOICE) ||
07085           (f.frametype == AST_FRAME_VIDEO) ||
07086           (f.frametype == AST_FRAME_IAX)) {
07087          if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) {
07088             ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART);
07089             if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) {
07090                ast_mutex_unlock(&iaxsl[fr->callno]);
07091                return 1;
07092             }
07093          }
07094       }
07095 
07096       if (f.frametype == AST_FRAME_VOICE) {
07097          if (f.subclass != iaxs[fr->callno]->voiceformat) {
07098                iaxs[fr->callno]->voiceformat = f.subclass;
07099                ast_log(LOG_DEBUG, "Ooh, voice format changed to %d\n", f.subclass);
07100                if (iaxs[fr->callno]->owner) {
07101                   int orignative;
07102 retryowner:
07103                   if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) {
07104                      ast_mutex_unlock(&iaxsl[fr->callno]);
07105                      usleep(1);
07106                      ast_mutex_lock(&iaxsl[fr->callno]);
07107                      if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner;
07108                   }
07109                   if (iaxs[fr->callno]) {
07110                      if (iaxs[fr->callno]->owner) {
07111                         orignative = iaxs[fr->callno]->owner->nativeformats;
07112                         iaxs[fr->callno]->owner->nativeformats = f.subclass;
07113                         if (iaxs[fr->callno]->owner->readformat)
07114                            ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat);
07115                         iaxs[fr->callno]->owner->nativeformats = orignative;
07116                         ast_mutex_unlock(&iaxs[fr->callno]->owner->lock);
07117                      }
07118                   } else {
07119                      ast_log(LOG_DEBUG, "Neat, somebody took away the channel at a magical time but i found it!\n");
07120                      ast_mutex_unlock(&iaxsl[fr->callno]);
07121                      return 1;
07122                   }
07123                }
07124          }
07125       }
07126       if (f.frametype == AST_FRAME_VIDEO) {
07127          if (f.subclass != iaxs[fr->callno]->videoformat) {
07128             ast_log(LOG_DEBUG, "Ooh, video format changed to %d\n", f.subclass & ~0x1);
07129             iaxs[fr->callno]->videoformat = f.subclass & ~0x1;
07130          }
07131       }
07132       if (f.frametype == AST_FRAME_IAX) {
07133          if (iaxs[fr->callno]->initid > -1) {
07134             /* Don't auto congest anymore since we've gotten something usefulb ack */
07135             ast_sched_del(sched, iaxs[fr->callno]->initid);
07136             iaxs[fr->callno]->initid = -1;
07137          }
07138          /* Handle the IAX pseudo frame itself */
07139          if (option_debug && iaxdebug)
07140             ast_log(LOG_DEBUG, "IAX subclass %d received\n", f.subclass);
07141 
07142                         /* Update last ts unless the frame's timestamp originated with us. */
07143          if (iaxs[fr->callno]->last < fr->ts &&
07144                             f.subclass != IAX_COMMAND_ACK &&
07145                             f.subclass != IAX_COMMAND_PONG &&
07146                             f.subclass != IAX_COMMAND_LAGRP) {
07147             iaxs[fr->callno]->last = fr->ts;
07148             if (option_debug && iaxdebug)
07149                ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts);
07150          }
07151 
07152          switch(f.subclass) {
07153          case IAX_COMMAND_ACK:
07154             /* Do nothing */
07155             break;
07156          case IAX_COMMAND_QUELCH:
07157             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
07158                     /* Generate Manager Hold event, if necessary*/
07159                if (iaxs[fr->callno]->owner) {
07160                   manager_event(EVENT_FLAG_CALL, "Hold",
07161                      "Channel: %s\r\n"
07162                      "Uniqueid: %s\r\n",
07163                      iaxs[fr->callno]->owner->name, 
07164                      iaxs[fr->callno]->owner->uniqueid);
07165                }
07166 
07167                ast_set_flag(iaxs[fr->callno], IAX_QUELCH);
07168                if (ies.musiconhold) {
07169                   if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) {
07170                      const char *mohsuggest = iaxs[fr->callno]->mohsuggest;
07171                      iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, 
07172                         S_OR(mohsuggest, NULL),
07173                         !ast_strlen_zero(mohsuggest) ? strlen(mohsuggest) + 1 : 0);
07174                      if (!iaxs[fr->callno]) {
07175                         ast_mutex_unlock(&iaxsl[fr->callno]);
07176                         return 1;
07177                      }
07178                   }
07179                }
07180             }
07181             break;
07182          case IAX_COMMAND_UNQUELCH:
07183             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
07184                     /* Generate Manager Unhold event, if necessary*/
07185                if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) {
07186                   manager_event(EVENT_FLAG_CALL, "Unhold",
07187                      "Channel: %s\r\n"
07188                      "Uniqueid: %s\r\n",
07189                      iaxs[fr->callno]->owner->name, 
07190                      iaxs[fr->callno]->owner->uniqueid);
07191                }
07192 
07193                ast_clear_flag(iaxs[fr->callno], IAX_QUELCH);
07194                if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) {
07195                   iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0);
07196                   if (!iaxs[fr->callno]) {
07197                      ast_mutex_unlock(&iaxsl[fr->callno]);
07198                      return 1;
07199                   }
07200                }
07201             }
07202             break;
07203          case IAX_COMMAND_TXACC:
07204             if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) {
07205                /* Ack the packet with the given timestamp */
07206                AST_LIST_LOCK(&iaxq.queue);
07207                AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
07208                   /* Cancel any outstanding txcnt's */
07209                   if ((fr->callno == cur->callno) && (cur->transfer))
07210                      cur->retries = -1;
07211                }
07212                AST_LIST_UNLOCK(&iaxq.queue);
07213                memset(&ied1, 0, sizeof(ied1));
07214                iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno);
07215                send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1);
07216                iaxs[fr->callno]->transferring = TRANSFER_READY;
07217             }
07218             break;
07219          case IAX_COMMAND_NEW:
07220             /* Ignore if it's already up */
07221             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD))
07222                break;
07223             if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) {
07224                ast_mutex_unlock(&iaxsl[fr->callno]);
07225                check_provisioning(&sin, fd, ies.serviceident, ies.provver);
07226                ast_mutex_lock(&iaxsl[fr->callno]);
07227                if (!iaxs[fr->callno]) {
07228                   ast_mutex_unlock(&iaxsl[fr->callno]);
07229                   return 1;
07230                }
07231             }
07232             /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */
07233             if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) {
07234                int new_callno;
07235                if ((new_callno = make_trunk(fr->callno, 1)) != -1)
07236                   fr->callno = new_callno;
07237             }
07238             /* For security, always ack immediately */
07239             if (delayreject)
07240                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07241             if (check_access(fr->callno, &sin, &ies)) {
07242                /* They're not allowed on */
07243                auth_fail(fr->callno, IAX_COMMAND_REJECT);
07244                if (authdebug)
07245                   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);
07246                break;
07247             }
07248             if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) {
07249                const char *context, *exten, *cid_num;
07250 
07251                context = ast_strdupa(iaxs[fr->callno]->context);
07252                exten = ast_strdupa(iaxs[fr->callno]->exten);
07253                cid_num = ast_strdupa(iaxs[fr->callno]->cid_num);
07254 
07255                /* This might re-enter the IAX code and need the lock */
07256                ast_mutex_unlock(&iaxsl[fr->callno]);
07257                exists = ast_exists_extension(NULL, context, exten, 1, cid_num);
07258                ast_mutex_lock(&iaxsl[fr->callno]);
07259 
07260                if (!iaxs[fr->callno]) {
07261                   ast_mutex_unlock(&iaxsl[fr->callno]);
07262                   return 1;
07263                }
07264             } else
07265                exists = 0;
07266             if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) {
07267                if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) {
07268                   memset(&ied0, 0, sizeof(ied0));
07269                   iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
07270                   iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
07271                   send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07272                   if (!iaxs[fr->callno]) {
07273                      ast_mutex_unlock(&iaxsl[fr->callno]);
07274                      return 1;
07275                   }
07276                   if (authdebug)
07277                      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);
07278                } else {
07279                   /* Select an appropriate format */
07280 
07281                   if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
07282                      if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07283                         using_prefs = "reqonly";
07284                      } else {
07285                         using_prefs = "disabled";
07286                      }
07287                      format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability;
07288                      memset(&pref, 0, sizeof(pref));
07289                      strcpy(caller_pref_buf, "disabled");
07290                      strcpy(host_pref_buf, "disabled");
07291                   } else {
07292                      using_prefs = "mine";
07293                      /* If the information elements are in here... use them */
07294                      if (ies.codec_prefs)
07295                         ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
07296                      if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
07297                         /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
07298                         if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
07299                            pref = iaxs[fr->callno]->rprefs;
07300                            using_prefs = "caller";
07301                         } else {
07302                            pref = iaxs[fr->callno]->prefs;
07303                         }
07304                      } else
07305                         pref = iaxs[fr->callno]->prefs;
07306                      
07307                      format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
07308                      ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
07309                      ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
07310                   }
07311                   if (!format) {
07312                      if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
07313                         format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
07314                      if (!format) {
07315                         memset(&ied0, 0, sizeof(ied0));
07316                         iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07317                         iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07318                         send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07319                         if (!iaxs[fr->callno]) {
07320                            ast_mutex_unlock(&iaxsl[fr->callno]);
07321                            return 1;
07322                         }
07323                         if (authdebug) {
07324                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
07325                               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);
07326                            else 
07327                               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);
07328                         }
07329                      } else {
07330                         /* Pick one... */
07331                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07332                            if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability))
07333                               format = 0;
07334                         } else {
07335                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
07336                               using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
07337                               memset(&pref, 0, sizeof(pref));
07338                               format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
07339                               strcpy(caller_pref_buf,"disabled");
07340                               strcpy(host_pref_buf,"disabled");
07341                            } else {
07342                               using_prefs = "mine";
07343                               if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
07344                                  /* Do the opposite of what we tried above. */
07345                                  if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
07346                                     pref = iaxs[fr->callno]->prefs;                       
07347                                  } else {
07348                                     pref = iaxs[fr->callno]->rprefs;
07349                                     using_prefs = "caller";
07350                                  }
07351                                  format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1);
07352                            
07353                               } else /* if no codec_prefs IE do it the old way */
07354                                  format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 
07355                            }
07356                         }
07357 
07358                         if (!format) {
07359                            memset(&ied0, 0, sizeof(ied0));
07360                            iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07361                            iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07362                            ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
07363                            send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07364                            if (!iaxs[fr->callno]) {
07365                               ast_mutex_unlock(&iaxsl[fr->callno]);
07366                               return 1;
07367                            }
07368                            if (authdebug)
07369                               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);
07370                            ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);   
07371                            break;
07372                         }
07373                      }
07374                   }
07375                   if (format) {
07376                      /* No authentication required, let them in */
07377                      memset(&ied1, 0, sizeof(ied1));
07378                      iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
07379                      send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
07380                      if (strcmp(iaxs[fr->callno]->exten, "TBD")) {
07381                         ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07382                         if (option_verbose > 2) 
07383                            ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n"
07384                                     "%srequested format = %s,\n"
07385                                     "%srequested prefs = %s,\n"
07386                                     "%sactual format = %s,\n"
07387                                     "%shost prefs = %s,\n"
07388                                     "%spriority = %s\n",
07389                                     ast_inet_ntoa(sin.sin_addr), 
07390                                     VERBOSE_PREFIX_4,
07391                                     ast_getformatname(iaxs[fr->callno]->peerformat), 
07392                                     VERBOSE_PREFIX_4,
07393                                     caller_pref_buf,
07394                                     VERBOSE_PREFIX_4,
07395                                     ast_getformatname(format), 
07396                                     VERBOSE_PREFIX_4,
07397                                     host_pref_buf, 
07398                                     VERBOSE_PREFIX_4,
07399                                     using_prefs);
07400                         
07401                         iaxs[fr->callno]->chosenformat = format;
07402                         ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART);
07403                      } else {
07404                         ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
07405                         /* If this is a TBD call, we're ready but now what...  */
07406                         if (option_verbose > 2)
07407                            ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr));
07408                      }
07409                   }
07410                }
07411                break;
07412             }
07413             if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5)
07414                merge_encryption(iaxs[fr->callno],ies.encmethods);
07415             else
07416                iaxs[fr->callno]->encmethods = 0;
07417             if (!authenticate_request(fr->callno) && iaxs[fr->callno])
07418                ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED);
07419             if (!iaxs[fr->callno]) {
07420                ast_mutex_unlock(&iaxsl[fr->callno]);
07421                return 1;
07422             }
07423             break;
07424          case IAX_COMMAND_DPREQ:
07425             /* Request status in the dialplan */
07426             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) &&
07427                !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) {
07428                if (iaxcompat) {
07429                   /* Spawn a thread for the lookup */
07430                   spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num);
07431                } else {
07432                   /* Just look it up */
07433                   dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1);
07434                }
07435             }
07436             break;
07437          case IAX_COMMAND_HANGUP:
07438             ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
07439             ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr->callno);
07440             /* Set hangup cause according to remote */
07441             if (ies.causecode && iaxs[fr->callno]->owner)
07442                iaxs[fr->callno]->owner->hangupcause = ies.causecode;
07443             /* Send ack immediately, before we destroy */
07444             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07445             iax2_destroy(fr->callno);
07446             break;
07447          case IAX_COMMAND_REJECT:
07448             /* Set hangup cause according to remote */
07449             if (ies.causecode && iaxs[fr->callno]->owner)
07450                iaxs[fr->callno]->owner->hangupcause = ies.causecode;
07451 
07452             if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) {
07453                if (iaxs[fr->callno]->owner && authdebug)
07454                   ast_log(LOG_WARNING, "Call rejected by %s: %s\n",
07455                      ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr),
07456                      ies.cause ? ies.cause : "<Unknown>");
07457                ast_log(LOG_DEBUG, "Immediately destroying %d, having received reject\n",
07458                   fr->callno);
07459             }
07460             /* Send ack immediately, before we destroy */
07461             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK,
07462                          fr->ts, NULL, 0, fr->iseqno);
07463             if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION))
07464                iaxs[fr->callno]->error = EPERM;
07465             iax2_destroy(fr->callno);
07466             break;
07467          case IAX_COMMAND_TRANSFER:
07468             if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner) && ies.called_number) {
07469                /* Set BLINDTRANSFER channel variables */
07470                pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", ast_bridged_channel(iaxs[fr->callno]->owner)->name);
07471                pbx_builtin_setvar_helper(ast_bridged_channel(iaxs[fr->callno]->owner), "BLINDTRANSFER", iaxs[fr->callno]->owner->name);
07472                if (!strcmp(ies.called_number, ast_parking_ext())) {
07473                   if (iax_park(ast_bridged_channel(iaxs[fr->callno]->owner), iaxs[fr->callno]->owner)) {
07474                      ast_log(LOG_WARNING, "Failed to park call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name);
07475                   } else if (ast_bridged_channel(iaxs[fr->callno]->owner))
07476                      ast_log(LOG_DEBUG, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name);
07477                } else {
07478                   if (ast_async_goto(ast_bridged_channel(iaxs[fr->callno]->owner), iaxs[fr->callno]->context, ies.called_number, 1))
07479                      ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name, 
07480                         ies.called_number, iaxs[fr->callno]->context);
07481                   else
07482                      ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name, 
07483                         ies.called_number, iaxs[fr->callno]->context);
07484                }
07485             } else
07486                   ast_log(LOG_DEBUG, "Async goto not applicable on call %d\n", fr->callno);
07487             break;
07488          case IAX_COMMAND_ACCEPT:
07489             /* Ignore if call is already up or needs authentication or is a TBD */
07490             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED))
07491                break;
07492             if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) {
07493                /* Send ack immediately, before we destroy */
07494                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07495                iax2_destroy(fr->callno);
07496                break;
07497             }
07498             if (ies.format) {
07499                iaxs[fr->callno]->peerformat = ies.format;
07500             } else {
07501                if (iaxs[fr->callno]->owner)
07502                   iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats;
07503                else
07504                   iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability;
07505             }
07506             if (option_verbose > 2)
07507                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));
07508             if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) {
07509                memset(&ied0, 0, sizeof(ied0));
07510                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07511                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07512                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07513                if (!iaxs[fr->callno]) {
07514                   ast_mutex_unlock(&iaxsl[fr->callno]);
07515                   return 1;
07516                }
07517                if (authdebug)
07518                   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);
07519             } else {
07520                ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07521                if (iaxs[fr->callno]->owner) {
07522                   /* Switch us to use a compatible format */
07523                   iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat;
07524                   if (option_verbose > 2)
07525                      ast_verbose(VERBOSE_PREFIX_3 "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats));
07526 retryowner2:
07527                   if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) {
07528                      ast_mutex_unlock(&iaxsl[fr->callno]);
07529                      usleep(1);
07530                      ast_mutex_lock(&iaxsl[fr->callno]);
07531                      if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2;
07532                   }
07533                   
07534                   if (iaxs[fr->callno] && iaxs[fr->callno]->owner) {
07535                      /* Setup read/write formats properly. */
07536                      if (iaxs[fr->callno]->owner->writeformat)
07537                         ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat);   
07538                      if (iaxs[fr->callno]->owner->readformat)
07539                         ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat);  
07540                      ast_mutex_unlock(&iaxs[fr->callno]->owner->lock);
07541                   }
07542                }
07543             }
07544             if (iaxs[fr->callno]) {
07545                ast_mutex_lock(&dpcache_lock);
07546                dp = iaxs[fr->callno]->dpentries;
07547                while(dp) {
07548                   if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) {
07549                      iax2_dprequest(dp, fr->callno);
07550                   }
07551                   dp = dp->peer;
07552                }
07553                ast_mutex_unlock(&dpcache_lock);
07554             }
07555             break;
07556          case IAX_COMMAND_POKE:
07557             /* Send back a pong packet with the original timestamp */
07558             send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1);
07559             if (!iaxs[fr->callno]) {
07560                ast_mutex_unlock(&iaxsl[fr->callno]);
07561                return 1;
07562             }
07563             break;
07564          case IAX_COMMAND_PING:
07565          {
07566             struct iax_ie_data pingied;
07567             construct_rr(iaxs[fr->callno], &pingied);
07568             /* Send back a pong packet with the original timestamp */
07569             send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1);
07570          }
07571             break;
07572          case IAX_COMMAND_PONG:
07573             /* Calculate ping time */
07574             iaxs[fr->callno]->pingtime =  calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts;
07575             /* save RR info */
07576             save_rr(fr, &ies);
07577 
07578             if (iaxs[fr->callno]->peerpoke) {
07579                peer = iaxs[fr->callno]->peerpoke;
07580                if ((peer->lastms < 0)  || (peer->historicms > peer->maxms)) {
07581                   if (iaxs[fr->callno]->pingtime <= peer->maxms) {
07582                      ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime);
07583                      manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 
07584                      ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
07585                   }
07586                } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) {
07587                   if (iaxs[fr->callno]->pingtime > peer->maxms) {
07588                      ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime);
07589                      manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 
07590                      ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
07591                   }
07592                }
07593                peer->lastms = iaxs[fr->callno]->pingtime;
07594                if (peer->smoothing && (peer->lastms > -1))
07595                   peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2;
07596                else if (peer->smoothing && peer->lastms < 0)
07597                   peer->historicms = (0 + peer->historicms) / 2;
07598                else              
07599                   peer->historicms = iaxs[fr->callno]->pingtime;
07600 
07601                /* Remove scheduled iax2_poke_noanswer */
07602                if (peer->pokeexpire > -1)
07603                   ast_sched_del(sched, peer->pokeexpire);
07604                /* Schedule the next cycle */
07605                if ((peer->lastms < 0)  || (peer->historicms > peer->maxms)) 
07606                   peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer);
07607                else
07608                   peer->pokeexpire = ast_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer);
07609                /* and finally send the ack */
07610                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07611                /* And wrap up the qualify call */
07612                iax2_destroy(fr->callno);
07613                peer->callno = 0;
07614                if (option_debug)
07615                   ast_log(LOG_DEBUG, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms);
07616             }
07617             break;
07618          case IAX_COMMAND_LAGRQ:
07619          case IAX_COMMAND_LAGRP:
07620             f.src = "LAGRQ";
07621             f.mallocd = 0;
07622             f.offset = 0;
07623             f.samples = 0;
07624             /* f.data should never be NULL before a iax_frame_wrap call.
07625              * -- wad@google.com, 9 July 2007 */
07626             if (!f.data) {
07627                ast_log(LOG_ERROR,
07628                   "Non-zero data length for NULL data in LAGRP from peer %s.\n",
07629                   ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr));
07630                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP,
07631                   fr->ts, NULL, 0, fr->iseqno);
07632                iax2_destroy(fr->callno);
07633                break;
07634             }
07635             iax_frame_wrap(fr, &f);
07636             if(f.subclass == IAX_COMMAND_LAGRQ) {
07637                /* Received a LAGRQ - echo back a LAGRP */
07638                fr->af.subclass = IAX_COMMAND_LAGRP;
07639                iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0);
07640             } else {
07641                /* Received LAGRP in response to our LAGRQ */
07642                unsigned int ts;
07643                /* This is a reply we've been given, actually measure the difference */
07644                ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af);
07645                iaxs[fr->callno]->lag = ts - fr->ts;
07646                if (option_debug && iaxdebug)
07647                   ast_log(LOG_DEBUG, "Peer %s lag measured as %dms\n",
07648                      ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag);
07649             }
07650             break;
07651          case IAX_COMMAND_AUTHREQ:
07652             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
07653                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>");
07654                break;
07655             }
07656             if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) {
07657                ast_log(LOG_WARNING, 
07658                   "I don't know how to authenticate %s to %s\n", 
07659                   ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr));
07660             }
07661             if (!iaxs[fr->callno]) {
07662                ast_mutex_unlock(&iaxsl[fr->callno]);
07663                return 1;
07664             }
07665             break;
07666          case IAX_COMMAND_AUTHREP:
07667             /* For security, always ack immediately */
07668             if (delayreject)
07669                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07670             /* Ignore once we've started */
07671             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
07672                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>");
07673                break;
07674             }
07675             if (authenticate_verify(iaxs[fr->callno], &ies)) {
07676                if (authdebug)
07677                   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);
07678                memset(&ied0, 0, sizeof(ied0));
07679                auth_fail(fr->callno, IAX_COMMAND_REJECT);
07680                break;
07681             }
07682             if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) {
07683                /* This might re-enter the IAX code and need the lock */
07684                exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num);
07685             } else
07686                exists = 0;
07687             if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) {
07688                if (authdebug)
07689                   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);
07690                memset(&ied0, 0, sizeof(ied0));
07691                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
07692                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
07693                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07694                if (!iaxs[fr->callno]) {
07695                   ast_mutex_unlock(&iaxsl[fr->callno]);
07696                   return 1;
07697                }
07698             } else {
07699                /* Select an appropriate format */
07700                if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
07701                   if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07702                      using_prefs = "reqonly";
07703                   } else {
07704                      using_prefs = "disabled";
07705                   }
07706                   format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability;
07707                   memset(&pref, 0, sizeof(pref));
07708                   strcpy(caller_pref_buf, "disabled");
07709                   strcpy(host_pref_buf, "disabled");
07710                } else {
07711                   using_prefs = "mine";
07712                   if (ies.codec_prefs)
07713                      ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
07714                   if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
07715                      if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
07716                         pref = iaxs[fr->callno]->rprefs;
07717                         using_prefs = "caller";
07718                      } else {
07719                         pref = iaxs[fr->callno]->prefs;
07720                      }
07721                   } else /* if no codec_prefs IE do it the old way */
07722                      pref = iaxs[fr->callno]->prefs;
07723                
07724                   format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
07725                   ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
07726                   ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
07727                }
07728                if (!format) {
07729                   if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07730                      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);
07731                      format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
07732                   }
07733                   if (!format) {
07734                      if (authdebug) {
07735                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 
07736                            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);
07737                         else
07738                            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);
07739                      }
07740                      memset(&ied0, 0, sizeof(ied0));
07741                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07742                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07743                      send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07744                      if (!iaxs[fr->callno]) {
07745                         ast_mutex_unlock(&iaxsl[fr->callno]);
07746                         return 1;
07747                      }
07748                   } else {
07749                      /* Pick one... */
07750                      if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07751                         if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability))
07752                            format = 0;
07753                      } else {
07754                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
07755                            using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
07756                            memset(&pref, 0, sizeof(pref));
07757                            format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ?
07758                               iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
07759                            strcpy(caller_pref_buf,"disabled");
07760                            strcpy(host_pref_buf,"disabled");
07761                         } else {
07762                            using_prefs = "mine";
07763                            if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
07764                               /* Do the opposite of what we tried above. */
07765                               if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
07766                                  pref = iaxs[fr->callno]->prefs;                 
07767                               } else {
07768                                  pref = iaxs[fr->callno]->rprefs;
07769                                  using_prefs = "caller";
07770                               }
07771                               format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1);
07772                            } else /* if no codec_prefs IE do it the old way */
07773                               format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 
07774                         }
07775                      }
07776                      if (!format) {
07777                         ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
07778                         if (authdebug) {
07779                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
07780                               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);
07781                            else
07782                               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);
07783                         }
07784                         memset(&ied0, 0, sizeof(ied0));
07785                         iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07786                         iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07787                         send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07788                         if (!iaxs[fr->callno]) {
07789                            ast_mutex_unlock(&iaxsl[fr->callno]);
07790                            return 1;
07791                         }
07792                      }
07793                   }
07794                }
07795                if (format) {
07796                   /* Authentication received */
07797                   memset(&ied1, 0, sizeof(ied1));
07798                   iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
07799                   send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
07800                   if (strcmp(iaxs[fr->callno]->exten, "TBD")) {
07801                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07802                      if (option_verbose > 2) 
07803                         ast_verbose(VERBOSE_PREFIX_3 "Accepting AUTHENTICATED call from %s:\n"
07804                                  "%srequested format = %s,\n"
07805                                  "%srequested prefs = %s,\n"
07806                                  "%sactual format = %s,\n"
07807                                  "%shost prefs = %s,\n"
07808                                  "%spriority = %s\n", 
07809                                  ast_inet_ntoa(sin.sin_addr), 
07810                                  VERBOSE_PREFIX_4,
07811                                  ast_getformatname(iaxs[fr->callno]->peerformat),
07812                                  VERBOSE_PREFIX_4,
07813                                  caller_pref_buf,
07814                                  VERBOSE_PREFIX_4,
07815                                  ast_getformatname(format),
07816                                  VERBOSE_PREFIX_4,
07817                                  host_pref_buf,
07818                                  VERBOSE_PREFIX_4,
07819                                  using_prefs);
07820 
07821                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07822                      if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format)))
07823                         iax2_destroy(fr->callno);
07824                   } else {
07825                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
07826                      /* If this is a TBD call, we're ready but now what...  */
07827                      if (option_verbose > 2)
07828                         ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr));
07829                   }
07830                }
07831             }
07832             break;
07833          case IAX_COMMAND_DIAL:
07834             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) {
07835                ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
07836                ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s");
07837                if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) {
07838                   if (authdebug)
07839                      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);
07840                   memset(&ied0, 0, sizeof(ied0));
07841                   iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
07842                   iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
07843                   send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07844                   if (!iaxs[fr->callno]) {
07845                      ast_mutex_unlock(&iaxsl[fr->callno]);
07846                      return 1;
07847                   }
07848                } else {
07849                   ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07850                   if (option_verbose > 2) 
07851                      ast_verbose(VERBOSE_PREFIX_3 "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat);
07852                   ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07853                   send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1);
07854                   if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat)))
07855                      iax2_destroy(fr->callno);
07856                }
07857             }
07858             break;
07859          case IAX_COMMAND_INVAL:
07860             iaxs[fr->callno]->error = ENOTCONN;
07861             ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr->callno);
07862             iax2_destroy(fr->callno);
07863             if (option_debug)
07864                ast_log(LOG_DEBUG, "Destroying call %d\n", fr->callno);
07865             break;
07866          case IAX_COMMAND_VNAK:
07867             ast_log(LOG_DEBUG, "Received VNAK: resending outstanding frames\n");
07868             /* Force retransmission */
07869             vnak_retransmit(fr->callno, fr->iseqno);
07870             break;
07871          case IAX_COMMAND_REGREQ:
07872          case IAX_COMMAND_REGREL:
07873             /* For security, always ack immediately */
07874             if (delayreject)
07875                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07876             if (register_verify(fr->callno, &sin, &ies)) {
07877                if (!iaxs[fr->callno]) {
07878                   ast_mutex_unlock(&iaxsl[fr->callno]);
07879                   return 1;
07880                }
07881                /* Send delayed failure */
07882                auth_fail(fr->callno, IAX_COMMAND_REGREJ);
07883                break;
07884             }
07885             if (!iaxs[fr->callno]) {
07886                ast_mutex_unlock(&iaxsl[fr->callno]);
07887                return 1;
07888             }
07889             if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 
07890                   ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED)) {
07891                if (f.subclass == IAX_COMMAND_REGREL)
07892                   memset(&sin, 0, sizeof(sin));
07893                if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh))
07894                   ast_log(LOG_WARNING, "Registry error\n");
07895                if (!iaxs[fr->callno]) {
07896                   ast_mutex_unlock(&iaxsl[fr->callno]);
07897                   return 1;
07898                }
07899                if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) {
07900                   ast_mutex_unlock(&iaxsl[fr->callno]);
07901                   check_provisioning(&sin, fd, ies.serviceident, ies.provver);
07902                   ast_mutex_lock(&iaxsl[fr->callno]);
07903                   if (!iaxs[fr->callno]) {
07904                      ast_mutex_unlock(&iaxsl[fr->callno]);
07905                      return 1;
07906                   }
07907                }
07908                break;
07909             }
07910             registry_authrequest(fr->callno);
07911             if (!iaxs[fr->callno]) {
07912                ast_mutex_unlock(&iaxsl[fr->callno]);
07913                return 1;
07914             }
07915             break;
07916          case IAX_COMMAND_REGACK:
07917             if (iax2_ack_registry(&ies, &sin, fr->callno)) 
07918                ast_log(LOG_WARNING, "Registration failure\n");
07919             /* Send ack immediately, before we destroy */
07920             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07921             iax2_destroy(fr->callno);
07922             break;
07923          case IAX_COMMAND_REGREJ:
07924             if (iaxs[fr->callno]->reg) {
07925                if (authdebug) {
07926                   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));
07927                   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>");
07928                }
07929                iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED;
07930             }
07931             /* Send ack immediately, before we destroy */
07932             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07933             iax2_destroy(fr->callno);
07934             break;
07935          case IAX_COMMAND_REGAUTH:
07936             /* Authentication request */
07937             if (registry_rerequest(&ies, fr->callno, &sin)) {
07938                memset(&ied0, 0, sizeof(ied0));
07939                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found");
07940                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
07941                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07942                if (!iaxs[fr->callno]) {
07943                   ast_mutex_unlock(&iaxsl[fr->callno]);
07944                   return 1;
07945                }
07946             }
07947             break;
07948          case IAX_COMMAND_TXREJ:
07949             iaxs[fr->callno]->transferring = 0;
07950             if (option_verbose > 2) 
07951                ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
07952             memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer));
07953             if (iaxs[fr->callno]->bridgecallno) {
07954                if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) {
07955                   iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0;
07956                   send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
07957                }
07958             }
07959             break;
07960          case IAX_COMMAND_TXREADY:
07961             if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) ||
07962                 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) {
07963                if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)
07964                   iaxs[fr->callno]->transferring = TRANSFER_MREADY;
07965                else
07966                   iaxs[fr->callno]->transferring = TRANSFER_READY;
07967                if (option_verbose > 2) 
07968                   ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
07969                if (iaxs[fr->callno]->bridgecallno) {
07970                   if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) ||
07971                       (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) {
07972                      /* They're both ready, now release them. */
07973                      if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) {
07974                         if (option_verbose > 2) 
07975                            ast_verbose(VERBOSE_PREFIX_3 "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
07976                               iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
07977 
07978                         iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA;
07979                         iaxs[fr->callno]->transferring = TRANSFER_MEDIA;
07980 
07981                         memset(&ied0, 0, sizeof(ied0));
07982                         memset(&ied1, 0, sizeof(ied1));
07983                         iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
07984                         iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
07985                         send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1);
07986                         send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1);
07987                      } else {
07988                         if (option_verbose > 2) 
07989                            ast_verbose(VERBOSE_PREFIX_3 "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
07990                               iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
07991 
07992                         iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED;
07993                         iaxs[fr->callno]->transferring = TRANSFER_RELEASED;
07994                         ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
07995                         ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
07996 
07997                         /* Stop doing lag & ping requests */
07998                         stop_stuff(fr->callno);
07999                         stop_stuff(iaxs[fr->callno]->bridgecallno);
08000 
08001                         memset(&ied0, 0, sizeof(ied0));
08002                         memset(&ied1, 0, sizeof(ied1));
08003                         iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
08004                         iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
08005                         send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1);
08006                         send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1);
08007                      }
08008 
08009                   }
08010                }
08011             }
08012             break;
08013          case IAX_COMMAND_TXREQ:
08014             try_transfer(iaxs[fr->callno], &ies);
08015             break;
08016          case IAX_COMMAND_TXCNT:
08017             if (iaxs[fr->callno]->transferring)
08018                send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0);
08019             break;
08020          case IAX_COMMAND_TXREL:
08021             /* Send ack immediately, rather than waiting until we've changed addresses */
08022             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08023             complete_transfer(fr->callno, &ies);
08024             stop_stuff(fr->callno); /* for attended transfer to work with libiax */
08025             break;   
08026          case IAX_COMMAND_TXMEDIA:
08027             if (iaxs[fr->callno]->transferring == TRANSFER_READY) {
08028                                         AST_LIST_LOCK(&iaxq.queue);
08029                                         AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
08030                                                 /* Cancel any outstanding frames and start anew */
08031                                                 if ((fr->callno == cur->callno) && (cur->transfer)) {
08032                                                         cur->retries = -1;
08033                                                 }
08034                                         }
08035                                         AST_LIST_UNLOCK(&iaxq.queue);
08036                /* Start sending our media to the transfer address, but otherwise leave the call as-is */
08037                iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS;
08038             }
08039             break;   
08040          case IAX_COMMAND_DPREP:
08041             complete_dpreply(iaxs[fr->callno], &ies);
08042             break;
08043          case IAX_COMMAND_UNSUPPORT:
08044             ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown);
08045             break;
08046          case IAX_COMMAND_FWDOWNL:
08047             /* Firmware download */
08048             memset(&ied0, 0, sizeof(ied0));
08049             res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc);
08050             if (res < 0)
08051                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
08052             else if (res > 0)
08053                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1);
08054             else
08055                send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1);
08056             if (!iaxs[fr->callno]) {
08057                ast_mutex_unlock(&iaxsl[fr->callno]);
08058                return 1;
08059             }
08060             break;
08061          default:
08062             ast_log(LOG_DEBUG, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno);
08063             memset(&ied0, 0, sizeof(ied0));
08064             iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass);
08065             send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1);
08066          }
08067          /* Don't actually pass these frames along */
08068          if ((f.subclass != IAX_COMMAND_ACK) && 
08069            (f.subclass != IAX_COMMAND_TXCNT) && 
08070            (f.subclass != IAX_COMMAND_TXACC) && 
08071            (f.subclass != IAX_COMMAND_INVAL) &&
08072            (f.subclass != IAX_COMMAND_VNAK)) { 
08073             if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno)
08074                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08075          }
08076          ast_mutex_unlock(&iaxsl[fr->callno]);
08077          return 1;
08078       }
08079       /* Unless this is an ACK or INVAL frame, ack it */
08080       if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno)
08081          send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08082    } else if (minivid) {
08083       f.frametype = AST_FRAME_VIDEO;
08084       if (iaxs[fr->callno]->videoformat > 0) 
08085          f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0);
08086       else {
08087          ast_log(LOG_WARNING, "Received mini frame before first full video frame\n ");
08088          iax2_vnak(fr->callno);
08089          ast_mutex_unlock(&iaxsl[fr->callno]);
08090          return 1;
08091       }
08092       f.datalen = res - sizeof(*vh);
08093       if (f.datalen)
08094          f.data = thread->buf + sizeof(*vh);
08095       else
08096          f.data = NULL;
08097 #ifdef IAXTESTS
08098       if (test_resync) {
08099          fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff);
08100       } else
08101 #endif /* IAXTESTS */
08102          fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff);
08103    } else {
08104       /* A mini frame */
08105       f.frametype = AST_FRAME_VOICE;
08106       if (iaxs[fr->callno]->voiceformat > 0)
08107          f.subclass = iaxs[fr->callno]->voiceformat;
08108       else {
08109          ast_log(LOG_WARNING, "Received mini frame before first full voice frame\n ");
08110          iax2_vnak(fr->callno);
08111          ast_mutex_unlock(&iaxsl[fr->callno]);
08112          return 1;
08113       }
08114       f.datalen = res - sizeof(struct ast_iax2_mini_hdr);
08115       if (f.datalen < 0) {
08116          ast_log(LOG_WARNING, "Datalen < 0?\n");
08117          ast_mutex_unlock(&iaxsl[fr->callno]);
08118          return 1;
08119       }
08120       if (f.datalen)
08121          f.data = thread->buf + sizeof(*mh);
08122       else
08123          f.data = NULL;
08124 #ifdef IAXTESTS
08125       if (test_resync) {
08126          fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff);
08127       } else
08128 #endif /* IAXTESTS */
08129       fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts);
08130       /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */
08131    }
08132    /* Don't pass any packets until we're started */
08133    if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
08134       ast_mutex_unlock(&iaxsl[fr->callno]);
08135       return 1;
08136    }
08137    /* Common things */
08138    f.src = "IAX2";
08139    f.mallocd = 0;
08140    f.offset = 0;
08141    f.len = 0;
08142    if (f.datalen && (f.frametype == AST_FRAME_VOICE)) {
08143       f.samples = ast_codec_get_samples(&f);
08144       /* We need to byteswap incoming slinear samples from network byte order */
08145       if (f.subclass == AST_FORMAT_SLINEAR)
08146          ast_frame_byteswap_be(&f);
08147    } else
08148       f.samples = 0;
08149    iax_frame_wrap(fr, &f);
08150 
08151    /* If this is our most recent packet, use it as our basis for timestamping */
08152    if (iaxs[fr->callno]->last < fr->ts) {
08153       /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/
08154       fr->outoforder = 0;
08155    } else {
08156       if (option_debug && iaxdebug)
08157          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);
08158       fr->outoforder = -1;
08159    }
08160    duped_fr = iaxfrdup2(fr);
08161    if (duped_fr) {
08162       schedule_delivery(duped_fr, updatehistory, 0, &fr->ts);
08163    }
08164    if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) {
08165       iaxs[fr->callno]->last = fr->ts;
08166 #if 1
08167       if (option_debug && iaxdebug)
08168          ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts);
08169 #endif
08170    }
08171 
08172    /* Always run again */
08173    ast_mutex_unlock(&iaxsl[fr->callno]);
08174    return 1;
08175 }

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

Definition at line 6592 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), ast_iax2_full_hdr::csub, defer_full_frame(), iax2_thread::ffinfo, find_idle_thread(), handle_error(), IAX_FLAG_FULL, IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, inaddrcmp(), len, LOG_NOTICE, LOG_WARNING, 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().

06593 {
06594    struct iax2_thread *thread;
06595    socklen_t len;
06596    time_t t;
06597    static time_t last_errtime = 0;
06598    struct ast_iax2_full_hdr *fh;
06599 
06600    if (!(thread = find_idle_thread())) {
06601       time(&t);
06602       if (t != last_errtime)
06603          ast_log(LOG_NOTICE, "Out of idle IAX2 threads for I/O, pausing!\n");
06604       last_errtime = t;
06605       usleep(1);
06606       return 1;
06607    }
06608 
06609    len = sizeof(thread->iosin);
06610    thread->iofd = fd;
06611    thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
06612    thread->buf_size = sizeof(thread->readbuf);
06613    thread->buf = thread->readbuf;
06614    if (thread->buf_len < 0) {
06615       if (errno != ECONNREFUSED && errno != EAGAIN)
06616          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
06617       handle_error();
06618       thread->iostate = IAX_IOSTATE_IDLE;
06619       signal_condition(&thread->lock, &thread->cond);
06620       return 1;
06621    }
06622    if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
06623       thread->iostate = IAX_IOSTATE_IDLE;
06624       signal_condition(&thread->lock, &thread->cond);
06625       return 1;
06626    }
06627    
06628    /* Determine if this frame is a full frame; if so, and any thread is currently
06629       processing a full frame for the same callno from this peer, then drop this
06630       frame (and the peer will retransmit it) */
06631    fh = (struct ast_iax2_full_hdr *) thread->buf;
06632    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
06633       struct iax2_thread *cur = NULL;
06634       uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
06635       
06636       AST_LIST_LOCK(&active_list);
06637       AST_LIST_TRAVERSE(&active_list, cur, list) {
06638          if ((cur->ffinfo.callno == callno) &&
06639              !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
06640             break;
06641       }
06642       if (cur) {
06643          /* we found another thread processing a full frame for this call,
06644             so queue it up for processing later. */
06645          defer_full_frame(thread, cur);
06646          AST_LIST_UNLOCK(&active_list);
06647          thread->iostate = IAX_IOSTATE_IDLE;
06648          signal_condition(&thread->lock, &thread->cond);
06649          return 1;
06650       } else {
06651          /* this thread is going to process this frame, so mark it */
06652          thread->ffinfo.callno = callno;
06653          memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
06654          thread->ffinfo.type = fh->type;
06655          thread->ffinfo.csub = fh->csub;
06656       }
06657       AST_LIST_UNLOCK(&active_list);
06658    }
06659    
06660    /* Mark as ready and send on its way */
06661    thread->iostate = IAX_IOSTATE_READY;
06662 #ifdef DEBUG_SCHED_MULTITHREAD
06663    ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
06664 #endif
06665    signal_condition(&thread->lock, &thread->cond);
06666 
06667    return 1;
06668 }

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

Definition at line 6379 of file chan_iax2.c.

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

Referenced by socket_process().

06380 {
06381    pthread_t newthread;
06382    struct dpreq_data *dpr;
06383    pthread_attr_t attr;
06384    
06385    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06386       return;
06387 
06388    pthread_attr_init(&attr);
06389    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06390 
06391    dpr->callno = callno;
06392    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06393    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06394    if (callerid)
06395       dpr->callerid = ast_strdup(callerid);
06396    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06397       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06398    }
06399 
06400    pthread_attr_destroy(&attr);
06401 }

static int start_network_thread ( void   )  [static]

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

08753 {
08754    pthread_attr_t attr;
08755    int threadcount = 0;
08756    int x;
08757    for (x = 0; x < iaxthreadcount; x++) {
08758       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
08759       if (thread) {
08760          thread->type = IAX_TYPE_POOL;
08761          thread->threadnum = ++threadcount;
08762          ast_mutex_init(&thread->lock);
08763          ast_cond_init(&thread->cond, NULL);
08764          pthread_attr_init(&attr);
08765          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
08766          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
08767             ast_log(LOG_WARNING, "Failed to create new thread!\n");
08768             free(thread);
08769             thread = NULL;
08770          }
08771          AST_LIST_LOCK(&idle_list);
08772          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
08773          AST_LIST_UNLOCK(&idle_list);
08774       }
08775    }
08776    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
08777    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
08778    if (option_verbose > 1)
08779       ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount);
08780    return 0;
08781 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 6067 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06068 {
06069    iax2_destroy_helper(iaxs[callno]);
06070 }

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

Definition at line 6254 of file chan_iax2.c.

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

Referenced by network_thread().

06255 {
06256    char buf[1024];
06257    int res;
06258    struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL;
06259    int processed = 0;
06260    int totalcalls = 0;
06261 #ifdef ZT_TIMERACK
06262    int x = 1;
06263 #endif
06264    struct timeval now;
06265    if (iaxtrunkdebug)
06266       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA);
06267    gettimeofday(&now, NULL);
06268    if (events & AST_IO_PRI) {
06269 #ifdef ZT_TIMERACK
06270       /* Great, this is a timing interface, just call the ioctl */
06271       if (ioctl(fd, ZT_TIMERACK, &x)) 
06272          ast_log(LOG_WARNING, "Unable to acknowledge zap timer\n");
06273       res = 0;
06274 #endif      
06275    } else {
06276       /* Read and ignore from the pseudo channel for timing */
06277       res = read(fd, buf, sizeof(buf));
06278       if (res < 1) {
06279          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
06280          return 1;
06281       }
06282    }
06283    /* For each peer that supports trunking... */
06284    ast_mutex_lock(&tpeerlock);
06285    tpeer = tpeers;
06286    while(tpeer) {
06287       processed++;
06288       res = 0;
06289       ast_mutex_lock(&tpeer->lock);
06290       /* We can drop a single tpeer per pass.  That makes all this logic
06291          substantially easier */
06292       if (!drop && iax2_trunk_expired(tpeer, &now)) {
06293          /* Take it out of the list, but don't free it yet, because it
06294             could be in use */
06295          if (prev)
06296             prev->next = tpeer->next;
06297          else
06298             tpeers = tpeer->next;
06299          drop = tpeer;
06300       } else {
06301          res = send_trunk(tpeer, &now);
06302          if (iaxtrunkdebug)
06303             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);
06304       }     
06305       totalcalls += res;   
06306       res = 0;
06307       ast_mutex_unlock(&tpeer->lock);
06308       prev = tpeer;
06309       tpeer = tpeer->next;
06310    }
06311    ast_mutex_unlock(&tpeerlock);
06312    if (drop) {
06313       ast_mutex_lock(&drop->lock);
06314       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
06315          because by the time they could get tpeerlock, we've already grabbed it */
06316       ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
06317       free(drop->trunkdata);
06318       ast_mutex_unlock(&drop->lock);
06319       ast_mutex_destroy(&drop->lock);
06320       free(drop);
06321       
06322    }
06323    if (iaxtrunkdebug)
06324       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
06325    iaxtrunkdebug =0;
06326    return 1;
06327 }

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

Definition at line 1832 of file chan_iax2.c.

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

Referenced by send_trunk().

01833 {
01834    int res;
01835    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
01836                sizeof(*sin));
01837    if (res < 0) {
01838       if (option_debug)
01839          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
01840       handle_error();
01841    } else
01842       res = 0;
01843    return res;
01844 }

static int try_firmware ( char *  s  )  [static]

Definition at line 1523 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, iax_firmware::fd, iax_firmware::fwh, IAX_FIRMWARE_MAGIC, last, len, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), iax_firmware::mmaplen, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.

Referenced by reload_firmware().

01524 {
01525    struct stat stbuf;
01526    struct iax_firmware *cur;
01527    int ifd;
01528    int fd;
01529    int res;
01530    
01531    struct ast_iax2_firmware_header *fwh, fwh2;
01532    struct MD5Context md5;
01533    unsigned char sum[16];
01534    unsigned char buf[1024];
01535    int len, chunk;
01536    char *s2;
01537    char *last;
01538    s2 = alloca(strlen(s) + 100);
01539    if (!s2) {
01540       ast_log(LOG_WARNING, "Alloca failed!\n");
01541       return -1;
01542    }
01543    last = strrchr(s, '/');
01544    if (last)
01545       last++;
01546    else
01547       last = s;
01548    snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random());
01549    res = stat(s, &stbuf);
01550    if (res < 0) {
01551       ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno));
01552       return -1;
01553    }
01554    /* Make sure it's not a directory */
01555    if (S_ISDIR(stbuf.st_mode))
01556       return -1;
01557    ifd = open(s, O_RDONLY);
01558    if (ifd < 0) {
01559       ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno));
01560       return -1;
01561    }
01562    fd = open(s2, O_RDWR | O_CREAT | O_EXCL);
01563    if (fd < 0) {
01564       ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno));
01565       close(ifd);
01566       return -1;
01567    }
01568    /* Unlink our newly created file */
01569    unlink(s2);
01570    
01571    /* Now copy the firmware into it */
01572    len = stbuf.st_size;
01573    while(len) {
01574       chunk = len;
01575       if (chunk > sizeof(buf))
01576          chunk = sizeof(buf);
01577       res = read(ifd, buf, chunk);
01578       if (res != chunk) {
01579          ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01580          close(ifd);
01581          close(fd);
01582          return -1;
01583       }
01584       res = write(fd, buf, chunk);
01585       if (res != chunk) {
01586          ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01587          close(ifd);
01588          close(fd);
01589          return -1;
01590       }
01591       len -= chunk;
01592    }
01593    close(ifd);
01594    /* Return to the beginning */
01595    lseek(fd, 0, SEEK_SET);
01596    if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) {
01597       ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s);
01598       close(fd);
01599       return -1;
01600    }
01601    if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) {
01602       ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s);
01603       close(fd);
01604       return -1;
01605    }
01606    if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) {
01607       ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s);
01608       close(fd);
01609       return -1;
01610    }
01611    if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) {
01612       ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s);
01613       close(fd);
01614       return -1;
01615    }
01616    fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 
01617    if (fwh == (void *) -1) {
01618       ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno));
01619       close(fd);
01620       return -1;
01621    }
01622    MD5Init(&md5);
01623    MD5Update(&md5, fwh->data, ntohl(fwh->datalen));
01624    MD5Final(sum, &md5);
01625    if (memcmp(sum, fwh->chksum, sizeof(sum))) {
01626       ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s);
01627       munmap((void*)fwh, stbuf.st_size);
01628       close(fd);
01629       return -1;
01630    }
01631    cur = waresl.wares;
01632    while(cur) {
01633       if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) {
01634          /* Found a candidate */
01635          if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version)))
01636             /* The version we have on loaded is older, load this one instead */
01637             break;
01638          /* This version is no newer than what we have.  Don't worry about it.
01639             We'll consider it a proper load anyhow though */
01640          munmap((void*)fwh, stbuf.st_size);
01641          close(fd);
01642          return 0;
01643       }
01644       cur = cur->next;
01645    }
01646    if (!cur) {
01647       /* Allocate a new one and link it */
01648       if ((cur = ast_calloc(1, sizeof(*cur)))) {
01649          cur->fd = -1;
01650          cur->next = waresl.wares;
01651          waresl.wares = cur;
01652       }
01653    }
01654    if (cur) {
01655       if (cur->fwh) {
01656          munmap((void*)cur->fwh, cur->mmaplen);
01657       }
01658       if (cur->fd > -1)
01659          close(cur->fd);
01660       cur->fwh = fwh;
01661       cur->fd = fd;
01662       cur->mmaplen = stbuf.st_size;
01663       cur->dead = 0;
01664    }
01665    return 0;
01666 }

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

Definition at line 5502 of file chan_iax2.c.

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

Referenced by socket_process().

05503 {
05504    int newcall = 0;
05505    char newip[256];
05506    struct iax_ie_data ied;
05507    struct sockaddr_in new;
05508    
05509    
05510    memset(&ied, 0, sizeof(ied));
05511    if (ies->apparent_addr)
05512       bcopy(ies->apparent_addr, &new, sizeof(new));
05513    if (ies->callno)
05514       newcall = ies->callno;
05515    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05516       ast_log(LOG_WARNING, "Invalid transfer request\n");
05517       return -1;
05518    }
05519    pvt->transfercallno = newcall;
05520    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05521    inet_aton(newip, &pvt->transfer.sin_addr);
05522    pvt->transfer.sin_family = AF_INET;
05523    pvt->transferring = TRANSFER_BEGIN;
05524    pvt->transferid = ies->transferid;
05525    if (ies->transferid)
05526       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05527    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05528    return 0; 
05529 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1043 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

01044 {
01045    /* If the SC_LOG flag is set, return 2^csub otherwise csub */
01046    if (csub & IAX_FLAG_SC_LOG) {
01047       /* special case for 'compressed' -1 */
01048       if (csub == 0xff)
01049          return -1;
01050       else
01051          return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT);
01052    }
01053    else
01054       return csub;
01055 }

static int unload_module ( void   )  [static]

Definition at line 10653 of file chan_iax2.c.

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

10654 {
10655    ast_custom_function_unregister(&iaxpeer_function);
10656    return __unload_module();
10657 }

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

Definition at line 3274 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03275 {
03276    ast_mutex_unlock(&iaxsl[callno1]);
03277    ast_mutex_unlock(&iaxsl[callno0]);
03278 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

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

02383 {
02384    int x;
02385 
02386    if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) {
02387       x = fr->ts - iaxs[fr->callno]->last;
02388       if (x < -50000) {
02389          /* Sudden big jump backwards in timestamp:
02390             What likely happened here is that miniframe timestamp has circled but we haven't
02391             gotten the update from the main packet.  We'll just pretend that we did, and
02392             update the timestamp appropriately. */
02393          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
02394          if (option_debug && iaxdebug)
02395             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02396       }
02397       if (x > 50000) {
02398          /* Sudden apparent big jump forwards in timestamp:
02399             What's likely happened is this is an old miniframe belonging to the previous
02400             top-16-bit timestamp that has turned up out of order.
02401             Adjust the timestamp appropriately. */
02402          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
02403          if (option_debug && iaxdebug)
02404             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02405       }
02406    }
02407 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 2411 of file chan_iax2.c.

References ast_sched_add(), ast_sched_del(), chan_iax2_pvt::callno, CALLNO_TO_PTR, get_from_jb(), chan_iax2_pvt::jb, jb_next(), chan_iax2_pvt::jbid, chan_iax2_pvt::rxcore, sched, and signal_condition().

Referenced by __get_from_jb(), and schedule_delivery().

02412 {
02413    int when;
02414    
02415    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02416    
02417    when = jb_next(pvt->jb) - when;
02418    
02419    if(pvt->jbid > -1) ast_sched_del(sched, pvt->jbid);
02420    
02421    if(when <= 0) {
02422       /* XXX should really just empty until when > 0.. */
02423       when = 1;
02424    }
02425    
02426    pvt->jbid = ast_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02427    
02428    /* Signal scheduler thread */
02429    signal_condition(&sched_lock, &sched_cond);
02430 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1263 of file chan_iax2.c.

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

Referenced by find_callno().

01264 {
01265    int max = 1;
01266    int x;
01267    /* XXX Prolly don't need locks here XXX */
01268    for (x=1;x<TRUNK_CALL_START - 1; x++) {
01269       if (iaxs[x])
01270          max = x + 1;
01271    }
01272    maxnontrunkcall = max;
01273    if (option_debug && iaxdebug)
01274       ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max);
01275 }

static void update_max_trunk ( void   )  [static]

Definition at line 1249 of file chan_iax2.c.

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

Referenced by iax2_destroy().

01250 {
01251    int max = TRUNK_CALL_START;
01252    int x;
01253    /* XXX Prolly don't need locks here XXX */
01254    for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) {
01255       if (iaxs[x])
01256          max = x + 1;
01257    }
01258    maxtrunkcall = max;
01259    if (option_debug && iaxdebug)
01260       ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max);
01261 }

static int update_packet ( struct iax_frame f  )  [static]

Definition at line 2019 of file chan_iax2.c.

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

Referenced by __attempt_transmit().

02020 {
02021    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02022    struct ast_iax2_full_hdr *fh = f->data;
02023    /* Mark this as a retransmission */
02024    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02025    /* Update iseqno */
02026    f->iseqno = iaxs[f->callno]->iseqno;
02027    fh->iseqno = f->iseqno;
02028    return 0;
02029 }

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 5859 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_add(), ast_sched_del(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verbose(), EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), globalflags, iax2_datetime(), iax2_poke_peer(), iax2_regfunk, 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_unref(), realtime_update_peer(), register_peer_exten(), sched, send_command_final(), iax2_peer::sockfd, and VERBOSE_PREFIX_3.

Referenced by socket_process().

05860 {
05861    /* Called from IAX thread only, with proper iaxsl lock */
05862    struct iax_ie_data ied;
05863    struct iax2_peer *p;
05864    int msgcount;
05865    char data[80];
05866    int version;
05867    const char *peer_name;
05868    int res = -1;
05869 
05870    memset(&ied, 0, sizeof(ied));
05871 
05872    peer_name = ast_strdupa(iaxs[callno]->peer);
05873 
05874    /* SLD: Another find_peer call during registration - this time when we are really updating our registration */
05875    ast_mutex_unlock(&iaxsl[callno]);
05876    if (!(p = find_peer(peer_name, 1))) {
05877       ast_mutex_lock(&iaxsl[callno]);
05878       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
05879       return -1;
05880    }
05881    ast_mutex_lock(&iaxsl[callno]);
05882    if (!iaxs[callno])
05883       goto return_unref;
05884 
05885    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) {
05886       if (sin->sin_addr.s_addr) {
05887          time_t nowtime;
05888          time(&nowtime);
05889          realtime_update_peer(peer_name, sin, nowtime);
05890       } else {
05891          realtime_update_peer(peer_name, sin, 0);
05892       }
05893    }
05894    if (inaddrcmp(&p->addr, sin)) {
05895       if (iax2_regfunk)
05896          iax2_regfunk(p->name, 1);
05897       /* Stash the IP address from which they registered */
05898       memcpy(&p->addr, sin, sizeof(p->addr));
05899       snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry);
05900       if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) {
05901          ast_db_put("IAX/Registry", p->name, data);
05902          if  (option_verbose > 2)
05903             ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 
05904                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
05905          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name);
05906          register_peer_exten(p, 1);
05907          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05908       } else if (!ast_test_flag(p, IAX_TEMPONLY)) {
05909          if  (option_verbose > 2)
05910             ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 
05911                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED");
05912          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name);
05913          register_peer_exten(p, 0);
05914          ast_db_del("IAX/Registry", p->name);
05915          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05916       }
05917       /* Update the host */
05918       /* Verify that the host is really there */
05919       iax2_poke_peer(p, callno);
05920    }     
05921 
05922    /* Make sure our call still exists, an INVAL at the right point may make it go away */
05923    if (!iaxs[callno]) {
05924       res = 0;
05925       goto return_unref;
05926    }
05927 
05928    /* Store socket fd */
05929    p->sockfd = fd;
05930    /* Setup the expiry */
05931    if (p->expire > -1)
05932       ast_sched_del(sched, p->expire);
05933    /* treat an unspecified refresh interval as the minimum */
05934    if (!refresh)
05935       refresh = min_reg_expire;
05936    if (refresh > max_reg_expire) {
05937       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
05938          p->name, max_reg_expire, refresh);
05939       p->expiry = max_reg_expire;
05940    } else if (refresh < min_reg_expire) {
05941       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
05942          p->name, min_reg_expire, refresh);
05943       p->expiry = min_reg_expire;
05944    } else {
05945       p->expiry = refresh;
05946    }
05947    if (p->expiry && sin->sin_addr.s_addr)
05948       p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name);
05949    iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
05950    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag));
05951    if (sin->sin_addr.s_addr) {
05952       iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry);
05953       iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
05954       if (!ast_strlen_zero(p->mailbox)) {
05955          int new, old;
05956          ast_app_inboxcount(p->mailbox, &new, &old);
05957          if (new > 255)
05958             new = 255;
05959          if (old > 255)
05960             old = 255;
05961          msgcount = (old << 8) | new;
05962          iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
05963       }
05964       if (ast_test_flag(p, IAX_HASCALLERID)) {
05965          iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num);
05966          iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name);
05967       }
05968    }
05969    version = iax_check_version(devtype);
05970    if (version) 
05971       iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version);
05972 
05973    res = 0;
05974 
05975 return_unref:
05976    peer_unref(p);
05977 
05978    return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
05979 }

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

Referenced by load_module().

01091 {
01092    struct iax2_user *user = obj, *user2 = arg;
01093 
01094    return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0;
01095 }

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

Definition at line 9401 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09402 {
09403    struct iax2_user *user = obj;
09404 
09405    ast_set_flag(user, IAX_DELME);
09406 
09407    return 0;
09408 }

static void user_destructor ( void *  obj  )  [static]

Definition at line 9165 of file chan_iax2.c.

References ast_free_ha(), ast_string_field_free_pools, ast_variables_destroy(), iax2_user::contexts, free_context(), iax2_user::ha, and iax2_user::vars.

Referenced by build_user().

09166 {
09167    struct iax2_user *user = obj;
09168 
09169    ast_free_ha(user->ha);
09170    free_context(user->contexts);
09171    if(user->vars) {
09172       ast_variables_destroy(user->vars);
09173       user->vars = NULL;
09174    }
09175    ast_string_field_free_pools(user);
09176 }

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

References ast_str_hash().

Referenced by load_module().

01081 {
01082    const struct iax2_user *user = obj;
01083 
01084    return ast_str_hash(user->name);
01085 }

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

Definition at line 1129 of file chan_iax2.c.

References ao2_ref().

Referenced by realtime_user().

01130 {
01131    ao2_ref(user, +1);
01132    return user;
01133 }

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

Definition at line 1135 of file chan_iax2.c.

References ao2_ref().

Referenced by authenticate_request(), authenticate_verify(), build_user(), check_access(), iax2_destroy_helper(), iax2_show_users(), and prune_users().

01136 {
01137    ao2_ref(user, -1);
01138    return NULL;
01139 }

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

Definition at line 6170 of file chan_iax2.c.

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

Referenced by socket_process().

06171 {
06172    struct iax_frame *f;
06173 
06174    AST_LIST_LOCK(&iaxq.queue);
06175    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06176       /* Send a copy immediately */
06177       if ((f->callno == callno) && iaxs[f->callno] &&
06178          ((unsigned char ) (f->oseqno - last) < 128) &&
06179          (f->retries >= 0)) {
06180          send_packet(f);
06181       }
06182    }
06183    AST_LIST_UNLOCK(&iaxq.queue);
06184 }


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

Definition at line 219 of file chan_iax2.c.

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

int adsi = 0 [static]

Definition at line 223 of file chan_iax2.c.

Referenced by build_gateway().

int amaflags = 0 [static]

Definition at line 222 of file chan_iax2.c.

Referenced by build_device(), build_gateway(), and pgsql_log().

int authdebug = 1 [static]

Definition at line 159 of file chan_iax2.c.

Referenced by set_config().

int autokill = 0 [static]

Definition at line 160 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 10474 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry cli_iax2_jb_debug_deprecated [static]

Initial value:

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

Definition at line 10454 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_no_debug_deprecated [static]

Initial value:

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

Definition at line 10459 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_no_jb_debug_deprecated [static]

Initial value:

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

Definition at line 10469 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_no_trunk_debug_deprecated [static]

Initial value:

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

Definition at line 10464 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_trunk_debug_deprecated [static]

Initial value:

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

Definition at line 10449 of file chan_iax2.c.

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

Definition at line 144 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 10423 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 10415 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 10407 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]

Definition at line 227 of file chan_iax2.c.

Referenced by __expire_registry(), aji_create_client(), aji_load_config(), build_peer(), build_user(), find_callno(), find_or_create(), find_user(), find_user_realtime(), forward_message(), iax2_request(), iax2_trunk_queue(), load_config(), make_email_file(), notify_new_message(), populate_defaults(), realtime_peer(), realtime_user(), reload_config(), send_trunk(), sendmail(), set_config(), update_registry(), and vm_execmain().

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

Definition at line 178 of file chan_iax2.c.

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

char iax2_reload_usage[] [static]

Initial value:

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

Definition at line 10365 of file chan_iax2.c.

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10339 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

Definition at line 846 of file chan_iax2.c.

Referenced by __unload_module(), ast_iax2_new(), function_iaxpeer(), iax2_bridge(), iax2_prov_app(), and load_module().

char iax2_test_losspct_usage[] [static]

Initial value:

"Usage: iax2 test losspct <percentage>\n"
"       For testing, throws away <percentage> percent of incoming packets\n"

Definition at line 10431 of file chan_iax2.c.

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

struct ast_custom_function iaxpeer_function

Definition at line 10278 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

struct ast_iax2_queue iaxq [static]

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

struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static]

Definition at line 810 of file chan_iax2.c.

Referenced by __attempt_transmit(), __auth_reject(), __auto_congest(), __auto_hangup(), __do_deliver(), __get_from_jb(), __send_lagrq(), __send_ping(), __unload_module(), ast_cli_netstats(), ast_iax2_new(), auth_fail(), auth_reject(), authenticate_reply(), authenticate_request(), auto_hangup(), cache_get_callno_locked(), calc_timestamp(), check_access(), complete_transfer(), decrypt_frame(), delete_users(), dp_lookup(), find_cache(), find_callno(), fix_peerts(), function_iaxpeer(), iax2_ack_registry(), iax2_bridge(), iax2_call(), iax2_destroy(), iax2_do_register(), iax2_dprequest(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_poke_peer(), iax2_predestroy(), iax2_prov_app(), iax2_provision(), iax2_queue_control_data(), iax2_queue_frame(), iax2_queue_hangup(), iax2_request(), iax2_show_channels(), iax2_start_transfer(), iax2_vnak(), iax2_write(), iax_showframe(), load_module(), make_trunk(), network_thread(), register_verify(), registry_authrequest(), registry_rerequest(), save_rr(), schedule_delivery(), send_command_final(), send_command_locked(), send_packet(), socket_process(), stop_stuff(), unwrap_timestamp(), update_max_nontrunk(), update_max_trunk(), update_packet(), update_registry(), and vnak_retransmit().

ast_mutex_t iaxsl[IAX_MAX_CALLS] [static]

Definition at line 811 of file chan_iax2.c.

Referenced by __attempt_transmit(), __auth_reject(), __auto_congest(), __auto_hangup(), __get_from_jb(), __iax2_poke_noanswer(), __send_lagrq(), __send_ping(), __unload_module(), ast_cli_netstats(), ast_iax2_new(), auth_reject(), authenticate_reply(), auto_hangup(), cache_get_callno_locked(), delete_users(), dp_lookup(), find_cache(), find_callno(), iax2_bridge(), iax2_call(), iax2_destroy(), iax2_do_register(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_poke_peer(), iax2_provision(), iax2_queue_control_data(), iax2_queue_frame(), iax2_queue_hangup(), iax2_request(), iax2_show_channels(), iax2_write(), load_module(), lock_both(), make_trunk(), network_thread(), peer_destructor(), register_verify(), registry_authrequest(), send_command_locked(), socket_process(), unlock_both(), and update_registry().

int iaxthreadcount = DEFAULT_THREAD_COUNT [static]

Definition at line 450 of file chan_iax2.c.

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

int iaxtrunkdebug = 0 [static]

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

char language[MAX_LANGUAGE] = "" [static]

Definition at line 146 of file chan_iax2.c.

struct timeval lastused[IAX_MAX_CALLS] [static]

Definition at line 812 of file chan_iax2.c.

Referenced by iax2_destroy().

int max_reg_expire [static]

Definition at line 170 of file chan_iax2.c.

int max_retries = 4 [static]

Definition at line 150 of file chan_iax2.c.

int maxauthreq = 3 [static]

Definition at line 149 of file chan_iax2.c.

int maxjitterbuffer = 1000 [static]

Definition at line 155 of file chan_iax2.c.

int maxjitterinterps = 10 [static]

Definition at line 157 of file chan_iax2.c.

int maxnontrunkcall = 1 [static]

Definition at line 154 of file chan_iax2.c.

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 153 of file chan_iax2.c.

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

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

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 229 of file chan_iax2.c.

Referenced by network_thread(), start_network_thread(), and unload_module().

char no_debug_jb_usage[] [static]

Initial value:

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

Definition at line 10427 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 10419 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 10411 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.

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

char* papp = "IAX2Provision" [static]

Definition at line 8414 of file chan_iax2.c.

char* pdescrip [static]

Initial value:

 
"  IAX2Provision([template]): Provisions the calling IAXy (assuming\n"
"the calling entity is in fact an IAXy) with the given template or\n"
"default if one is not specified.  Returns -1 on error or 0 on success.\n"

Definition at line 8416 of file chan_iax2.c.

ao2_container* peers [static]

Definition at line 648 of file chan_iax2.c.

Referenced by __expire_registry(), __iax2_show_peers(), __unload_module(), abort_request(), authenticate_reply(), build_peer(), build_transactions(), cancel_request(), chanavail_exec(), check_request(), complete_iax2_show_peer(), complete_peer_helper(), delete_users(), destroy_trans(), discover_transactions(), dundi_flush(), dundi_ie_append_eid_appropriately(), dundi_lookup_thread(), dundi_precache_internal(), dundi_precache_thread(), dundi_query_thread(), dundi_rexmit(), dundi_show_entityid(), dundi_show_mappings(), dundi_show_peer(), dundi_show_peers(), dundi_show_requests(), dundi_show_trans(), find_peer(), iax2_getpeername(), iax2_getpeertrunk(), load_module(), mark_mappings(), mark_peers(), network_thread(), optimize_transactions(), precache_transactions(), prune_mappings(), prune_peers(), query_transactions(), register_request(), reload_config(), set_config(), socket_read(), and unregister_request().

int ping_time = 21 [static]

Definition at line 151 of file chan_iax2.c.

struct ast_codec_pref prefs [static]

Definition at line 140 of file chan_iax2.c.

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

char prune_realtime_usage[] [static]

Initial value:

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

Definition at line 10361 of file chan_iax2.c.

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

Definition at line 8415 of file chan_iax2.c.

char regcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 147 of file chan_iax2.c.

int resyncthreshold = 1000 [static]

Definition at line 156 of file chan_iax2.c.

struct sched_context* sched [static]

Definition at line 203 of file chan_iax2.c.

ast_cond_t sched_cond [static]

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 10353 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 10381 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 10399 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 10385 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 10357 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 10393 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10369 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 10403 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 10349 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 10389 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 10376 of file chan_iax2.c.

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

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

ao2_container* users [static]

Definition at line 651 of file chan_iax2.c.

Referenced by __unload_module(), ast_get_manager_by_name_locked(), authenticate_request(), authenticate_verify(), build_user(), check_access(), complete_voicemail_show_users(), delete_users(), find_or_create(), find_user(), handle_showmanager(), handle_showmanagers(), handle_voicemail_show_users(), iax2_destroy_helper(), iax2_show_users(), init_manager(), load_config(), load_module(), prune_users(), realtime_user(), reset_user_pw(), and set_config().

struct ast_firmware_list waresl [static]

Referenced by __unload_module(), iax2_show_firmware(), iax_check_version(), iax_firmware_append(), load_module(), reload_firmware(), and try_firmware().


Generated on Fri Aug 24 02:23:57 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1