Wed Aug 15 01:24:50 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 "iax2.h"
#include "iax2-parser.h"
#include "iax2-provision.h"
#include "jitterbuf.h"

Go to the source code of this file.

Data Structures

struct  ast_firmware_list
struct  ast_iax2_queue
struct  chan_iax2_pvt
struct  create_addr_info
struct  dpreq_data
struct  iax2_context
struct  iax2_dpcache
struct  iax2_peer
struct  iax2_pkt_buf
struct  iax2_registry
struct  iax2_thread
struct  iax2_trunk_peer
struct  iax2_user
struct  iax_dual
struct  iax_firmware
struct  iax_rr
struct  parsed_dial_string

Defines

#define CACHE_FLAG_CANEXIST   (1 << 2)
#define CACHE_FLAG_EXISTS   (1 << 0)
#define CACHE_FLAG_MATCHMORE   (1 << 7)
#define CACHE_FLAG_NONEXISTENT   (1 << 1)
#define CACHE_FLAG_PENDING   (1 << 3)
#define CACHE_FLAG_TIMEOUT   (1 << 4)
#define CACHE_FLAG_TRANSMITTED   (1 << 5)
#define CACHE_FLAG_UNKNOWN   (1 << 6)
#define CALLNO_TO_PTR(a)   ((void *)(unsigned long)(a))
#define DEBUG_SCHED_MULTITHREAD
#define DEBUG_SUPPORT
#define DEFAULT_DROP   3
#define DEFAULT_FREQ_NOTOK   10 * 1000
#define DEFAULT_FREQ_OK   60 * 1000
#define DEFAULT_MAX_THREAD_COUNT   100
#define DEFAULT_MAXMS   2000
#define DEFAULT_RETRY_TIME   1000
#define DEFAULT_THREAD_COUNT   10
#define DEFAULT_TRUNKDATA   640 * 10
#define FORMAT   "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n"
#define FORMAT   "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n"
#define FORMAT   "%-15.15s %-15d %-15d\n"
#define FORMAT   "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s"
#define FORMAT   "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n"
#define FORMAT2   "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n"
#define FORMAT2   "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n"
#define FORMAT2   "%-15.15s %-15.15s %-15.15s\n"
#define FORMAT2   "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s"
#define FORMAT2   "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n"
#define FORMATB   "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n"
#define GAMMA   (0.01)
#define IAX2_TRUNK_PREFACE   (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr))
#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF
#define IAX_CAPABILITY_LOWBANDWIDTH
#define IAX_CAPABILITY_LOWFREE
#define IAX_CAPABILITY_MEDBANDWIDTH
#define IAX_IOSTATE_IDLE   0
#define IAX_IOSTATE_PROCESSING   2
#define IAX_IOSTATE_READY   1
#define IAX_IOSTATE_SCHEDREADY   3
#define IAX_TYPE_DYNAMIC   2
#define IAX_TYPE_POOL   1
#define IPTOS_MINCOST   0x02
#define MAX_JITTER_BUFFER   50
#define MAX_RETRY_TIME   10000
#define MAX_TIMESTAMP_SKEW   160
#define MAX_TRUNKDATA   640 * 200
#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_channel
ast_iax2_new (int callno, int state, int capability)
 Create new call, interface with the PBX core.
static AST_LIST_HEAD_STATIC (dynamic_list, iax2_thread)
static AST_LIST_HEAD_STATIC (active_list, iax2_thread)
static AST_LIST_HEAD_STATIC (idle_list, iax2_thread)
static AST_LIST_HEAD_STATIC (peers, iax2_peer)
static AST_LIST_HEAD_STATIC (users, iax2_user)
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 (struct chan_iax2_pvt *p)
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_context
build_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 destroy_peer (struct iax2_peer *peer)
static void destroy_user (struct iax2_user *user)
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_dpcache
find_cache (struct ast_channel *chan, const char *data, const char *context, const char *exten, int priority)
static int find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int lockpeer, int sockfd)
static struct
iax2_thread
find_idle_thread (void)
static struct iax2_peerfind_peer (const char *name, int realtime)
static struct
iax2_trunk_peer
find_tpeer (struct sockaddr_in *sin, int fd)
static unsigned int fix_peerts (struct timeval *tv, int callno, unsigned int ts)
static void free_context (struct iax2_context *con)
static int function_iaxpeer (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
static int get_auth_methods (char *value)
static int get_encrypt_methods (const char *s)
static int get_from_jb (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, int lockpeer)
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_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_frame (int callno, struct ast_frame *f)
 Queue a frame to a call's owning asterisk channel.
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_channel
iax2_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_pvt
new_iax (struct sockaddr_in *sin, int lockpeer, 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_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 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 (const char *name, 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 (const char *name, struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh)
static void vnak_retransmit (int callno, int last)

Variables

static char accountcode [AST_MAX_ACCOUNT_CODE]
static int adsi = 0
static int amaflags = 0
static int authdebug = 1
static int autokill = 0
static struct
ast_cli_entry 
cli_iax2 []
static struct
ast_cli_entry 
cli_iax2_jb_debug_deprecated
static struct
ast_cli_entry 
cli_iax2_no_debug_deprecated
static struct
ast_cli_entry 
cli_iax2_no_jb_debug_deprecated
static struct
ast_cli_entry 
cli_iax2_no_trunk_debug_deprecated
static struct
ast_cli_entry 
cli_iax2_trunk_debug_deprecated
static char context [80] = "default"
static char debug_jb_usage []
static char debug_trunk_usage []
static char debug_usage []
static int defaultsockfd = -1
static int delayreject = 0
static struct
iax2_dpcache
dpcache
static int global_rtautoclear = 120
static struct ast_flags globalflags = { 0 }
static int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH
static int iax2_encryption = 0
enum { ... }  iax2_flags
int(* iax2_regfunk )(const char *username, int onoff) = NULL
static char iax2_reload_usage []
enum { ... }  iax2_state
static struct ast_switch iax2_switch
static struct
ast_channel_tech 
iax2_tech
static char iax2_test_losspct_usage []
static int iaxactivethreadcount = 0
static int iaxcompat = 0
static int iaxdebug = 0
static int iaxdefaultdpcache = 10 * 60
static int iaxdefaulttimeout = 5
static int iaxdynamicthreadcount = 0
static int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT
struct
ast_custom_function 
iaxpeer_function
static struct
ast_iax2_queue 
iaxq
static struct
chan_iax2_pvt
iaxs [IAX_MAX_CALLS]
static ast_mutex_t iaxsl [IAX_MAX_CALLS]
static int iaxthreadcount = DEFAULT_THREAD_COUNT
static int iaxtrunkdebug = 0
static struct
io_context
io
static int lagrq_time = 10
static char language [MAX_LANGUAGE] = ""
static struct timeval lastused [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_list
netsock
static pthread_t netthreadid = AST_PTHREADT_NULL
static char no_debug_jb_usage []
static char no_debug_trunk_usage []
static char no_debug_usage []
static struct
ast_netsock_list
outsock
static char * papp = "IAX2Provision"
static char * pdescrip
static int ping_time = 21
static struct
ast_codec_pref 
prefs
static char prune_realtime_usage []
static char * psyn = "Provision a calling IAXy with a given template"
static char regcontext [AST_MAX_CONTEXT] = ""
static int resyncthreshold = 1000
static struct
sched_context
sched
static ast_cond_t sched_cond
static pthread_t schedthreadid = AST_PTHREADT_NULL
static char show_cache_usage []
static char show_channels_usage []
static char show_firmware_usage []
static char show_netstats_usage []
static char show_peer_usage []
static char show_peers_usage []
static char show_prov_usage []
static char show_reg_usage []
static char show_stats_usage []
static char show_threads_usage []
static char show_users_usage []
static const char tdesc [] = "Inter Asterisk eXchange Driver (Ver 2)"
static int test_losspct = 0
static int timingfd = -1
static unsigned int tos = 0
static struct
iax2_trunk_peer
tpeers
static int trunkfreq = 20
static struct
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 649 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 645 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 659 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 647 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 651 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 653 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

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

Referenced by complete_dpreply(), and iax2_show_cache().

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

Definition at line 121 of file chan_iax2.c.

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

#define DEBUG_SCHED_MULTITHREAD

Definition at line 109 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 132 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 127 of file chan_iax2.c.

#define DEFAULT_FREQ_NOTOK   10 * 1000

Definition at line 199 of file chan_iax2.c.

Referenced by build_peer(), handle_response_peerpoke(), and sip_poke_noanswer().

#define DEFAULT_FREQ_OK   60 * 1000

Definition at line 198 of file chan_iax2.c.

Referenced by build_peer(), and handle_response_peerpoke().

#define DEFAULT_MAX_THREAD_COUNT   100

Definition at line 124 of file chan_iax2.c.

#define DEFAULT_MAXMS   2000

Definition at line 197 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

Definition at line 125 of file chan_iax2.c.

Referenced by complete_transfer(), and find_callno().

#define DEFAULT_THREAD_COUNT   10

Definition at line 123 of file chan_iax2.c.

#define DEFAULT_TRUNKDATA   640 * 10

40ms, uncompressed linear * 10 channels

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

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF

Definition at line 180 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 188 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 193 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 182 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 681 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 683 of file chan_iax2.c.

Referenced by iax2_process_thread().

#define IAX_IOSTATE_READY   1

Definition at line 682 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 684 of file chan_iax2.c.

Referenced by __schedule_action(), and iax2_process_thread().

#define IAX_TYPE_DYNAMIC   2

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

Referenced by start_network_thread().

#define IPTOS_MINCOST   0x02

Definition at line 112 of file chan_iax2.c.

#define MAX_JITTER_BUFFER   50

Definition at line 440 of file chan_iax2.c.

#define MAX_RETRY_TIME   10000

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

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 444 of file chan_iax2.c.

Referenced by iax2_trunk_queue(), and timing_read().

#define MEMORY_SIZE   100

Definition at line 126 of file chan_iax2.c.

#define MIN_JITTER_BUFFER   10

Definition at line 441 of file chan_iax2.c.

#define MIN_RETRY_TIME   100

Definition at line 437 of file chan_iax2.c.

Referenced by iax2_send().

#define MIN_REUSE_TIME   60

Definition at line 134 of file chan_iax2.c.

Referenced by find_callno(), and make_trunk().

#define NEW_ALLOW   1

Definition at line 1149 of file chan_iax2.c.

Referenced by find_callno(), and socket_process().

#define NEW_FORCE   2

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

Referenced by socket_process().

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

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

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

Definition at line 951 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 130 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 449 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 233 of file chan_iax2.c.

00233      {
00234    IAX_STATE_STARTED =     (1 << 0),
00235    IAX_STATE_AUTHENTICATED =  (1 << 1),
00236    IAX_STATE_TBD =      (1 << 2),
00237    IAX_STATE_UNCHANGED =      (1 << 3),
00238 } iax2_state;

anonymous enum

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

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


Function Documentation

static void __attempt_transmit ( void *  data  )  [static]

Definition at line 1874 of file chan_iax2.c.

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

Referenced by attempt_transmit().

01875 {
01876    /* Attempt to transmit the frame to the remote peer...
01877       Called without iaxsl held. */
01878    struct iax_frame *f = data;
01879    int freeme=0;
01880    int callno = f->callno;
01881    /* Make sure this call is still active */
01882    if (callno) 
01883       ast_mutex_lock(&iaxsl[callno]);
01884    if (callno && iaxs[callno]) {
01885       if ((f->retries < 0) /* Already ACK'd */ ||
01886           (f->retries >= max_retries) /* Too many attempts */) {
01887             /* Record an error if we've transmitted too many times */
01888             if (f->retries >= max_retries) {
01889                if (f->transfer) {
01890                   /* Transfer timeout */
01891                   send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
01892                } else if (f->final) {
01893                   if (f->final) 
01894                      iax2_destroy(callno);
01895                } else {
01896                   if (iaxs[callno]->owner)
01897                      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);
01898                   iaxs[callno]->error = ETIMEDOUT;
01899                   if (iaxs[callno]->owner) {
01900                      struct ast_frame fr = { 0, };
01901                      /* Hangup the fd */
01902                      fr.frametype = AST_FRAME_CONTROL;
01903                      fr.subclass = AST_CONTROL_HANGUP;
01904                      iax2_queue_frame(callno, &fr); // XXX
01905                      /* Remember, owner could disappear */
01906                      if (iaxs[callno] && iaxs[callno]->owner)
01907                         iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01908                   } else {
01909                      if (iaxs[callno]->reg) {
01910                         memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us));
01911                         iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT;
01912                         iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE;
01913                      }
01914                      iax2_destroy(callno);
01915                   }
01916                }
01917 
01918             }
01919             freeme++;
01920       } else {
01921          /* Update it if it needs it */
01922          update_packet(f);
01923          /* Attempt transmission */
01924          send_packet(f);
01925          f->retries++;
01926          /* Try again later after 10 times as long */
01927          f->retrytime *= 10;
01928          if (f->retrytime > MAX_RETRY_TIME)
01929             f->retrytime = MAX_RETRY_TIME;
01930          /* Transfer messages max out at one second */
01931          if (f->transfer && (f->retrytime > 1000))
01932             f->retrytime = 1000;
01933          f->retrans = ast_sched_add(sched, f->retrytime, attempt_transmit, f);
01934       }
01935    } else {
01936       /* Make sure it gets freed */
01937       f->retries = -1;
01938       freeme++;
01939    }
01940    if (callno)
01941       ast_mutex_unlock(&iaxsl[callno]);
01942    /* Do not try again */
01943    if (freeme) {
01944       /* Don't attempt delivery, just remove it from the queue */
01945       AST_LIST_LOCK(&iaxq.queue);
01946       AST_LIST_REMOVE(&iaxq.queue, f, list);
01947       iaxq.count--;
01948       AST_LIST_UNLOCK(&iaxq.queue);
01949       f->retrans = -1;
01950       /* Free the IAX frame */
01951       iax2_frame_free(f);
01952    }
01953 }

static void __auth_reject ( void *  nothing  )  [static]

Definition at line 5842 of file chan_iax2.c.

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

Referenced by auth_reject().

05843 {
05844    /* Called from IAX thread only, without iaxs lock */
05845    int callno = (int)(long)(nothing);
05846    struct iax_ie_data ied;
05847    ast_mutex_lock(&iaxsl[callno]);
05848    if (iaxs[callno]) {
05849       memset(&ied, 0, sizeof(ied));
05850       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
05851          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
05852          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
05853       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
05854          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
05855          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
05856       }
05857       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
05858    }
05859    ast_mutex_unlock(&iaxsl[callno]);
05860 }

static void __auto_congest ( void *  nothing  )  [static]

Definition at line 2760 of file chan_iax2.c.

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

Referenced by auto_congest().

02761 {
02762    int callno = PTR_TO_CALLNO(nothing);
02763    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
02764    ast_mutex_lock(&iaxsl[callno]);
02765    if (iaxs[callno]) {
02766       iaxs[callno]->initid = -1;
02767       iax2_queue_frame(callno, &f);
02768       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
02769    }
02770    ast_mutex_unlock(&iaxsl[callno]);
02771 }

static void __auto_hangup ( void *  nothing  )  [static]

Definition at line 5894 of file chan_iax2.c.

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

Referenced by auto_hangup().

05895 {
05896    /* Called from IAX thread only, without iaxs lock */
05897    int callno = (int)(long)(nothing);
05898    struct iax_ie_data ied;
05899    ast_mutex_lock(&iaxsl[callno]);
05900    if (iaxs[callno]) {
05901       memset(&ied, 0, sizeof(ied));
05902       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
05903       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
05904       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
05905    }
05906    ast_mutex_unlock(&iaxsl[callno]);
05907 }

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

01639 {
01640    /* Just deliver the packet by using queueing.  This is called by
01641      the IAX thread with the iaxsl lock held. */
01642    struct iax_frame *fr = data;
01643    fr->retrans = -1;
01644    fr->af.has_timing_info = 0;
01645    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
01646       iax2_queue_frame(fr->callno, &fr->af);
01647    /* Free our iax frame */
01648    iax2_frame_free(fr);
01649    /* And don't run again */
01650    return 0;
01651 }

static void __expire_registry ( void *  data  )  [static]

Definition at line 5567 of file chan_iax2.c.

References iax2_peer::addr, ast_db_del(), ast_device_state_changed(), AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_set_flag, ast_test_flag, EVENT_FLAG_SYSTEM, iax2_peer::expire, iax2_peer::expiry, iax2_regfunk, IAX_DELME, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, LOG_DEBUG, manager_event(), name, prune_peers(), realtime_update_peer(), and register_peer_exten().

Referenced by expire_registry().

05568 {
05569    char *name = data;
05570    struct iax2_peer *p = NULL;
05571 
05572    /* Go through and grab this peer... and if it needs to be removed... then do it */
05573    AST_LIST_LOCK(&peers);
05574    AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, p, entry) {
05575       if (!strcasecmp(p->name, name)) {
05576          p->expire = -1;
05577          break;
05578       }
05579    }
05580    AST_LIST_TRAVERSE_SAFE_END
05581    AST_LIST_UNLOCK(&peers);
05582 
05583    /* Peer is already gone for whatever reason */
05584    if (!p)
05585       return;
05586 
05587    ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", p->name);
05588    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
05589       realtime_update_peer(p->name, &p->addr, 0);
05590    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", p->name);
05591    /* Reset the address */
05592    memset(&p->addr, 0, sizeof(p->addr));
05593    /* Reset expiry value */
05594    p->expiry = min_reg_expire;
05595    if (!ast_test_flag(p, IAX_TEMPONLY))
05596       ast_db_del("IAX/Registry", p->name);
05597    register_peer_exten(p, 0);
05598    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05599    if (iax2_regfunk)
05600       iax2_regfunk(p->name, 0);
05601 
05602    if (ast_test_flag(p, IAX_RTAUTOCLEAR)) {
05603       ast_set_flag(p, IAX_DELME);
05604       prune_peers();
05605    }
05606 }

static void __get_from_jb ( void *  p  )  [static]

Definition at line 2271 of file chan_iax2.c.

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

Referenced by get_from_jb().

02272 {
02273    int callno = PTR_TO_CALLNO(p);
02274    struct chan_iax2_pvt *pvt = NULL;
02275    struct iax_frame *fr;
02276    jb_frame frame;
02277    int ret;
02278    long now;
02279    long next;
02280    struct timeval tv;
02281    
02282    /* Make sure we have a valid private structure before going on */
02283    ast_mutex_lock(&iaxsl[callno]);
02284    pvt = iaxs[callno];
02285    if (!pvt) {
02286       /* No go! */
02287       ast_mutex_unlock(&iaxsl[callno]);
02288       return;
02289    }
02290 
02291    pvt->jbid = -1;
02292    
02293    gettimeofday(&tv,NULL);
02294    /* round up a millisecond since ast_sched_runq does; */
02295    /* prevents us from spinning while waiting for our now */
02296    /* to catch up with runq's now */
02297    tv.tv_usec += 1000;
02298    
02299    now = ast_tvdiff_ms(tv, pvt->rxcore);
02300    
02301    if(now >= (next = jb_next(pvt->jb))) {
02302       ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
02303       switch(ret) {
02304       case JB_OK:
02305          fr = frame.data;
02306          __do_deliver(fr);
02307          /* __do_deliver() can cause the call to disappear */
02308          pvt = iaxs[callno];
02309          break;
02310       case JB_INTERP:
02311       {
02312          struct ast_frame af = { 0, };
02313          
02314          /* create an interpolation frame */
02315          af.frametype = AST_FRAME_VOICE;
02316          af.subclass = pvt->voiceformat;
02317          af.samples  = frame.ms * 8;
02318          af.src  = "IAX2 JB interpolation";
02319          af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
02320          af.offset = AST_FRIENDLY_OFFSET;
02321          
02322          /* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
02323           * which we'd need to malloc, and then it would free it.  That seems like a drag */
02324          if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
02325             iax2_queue_frame(callno, &af);
02326             /* iax2_queue_frame() could cause the call to disappear */
02327             pvt = iaxs[callno];
02328          }
02329       }
02330          break;
02331       case JB_DROP:
02332          iax2_frame_free(frame.data);
02333          break;
02334       case JB_NOFRAME:
02335       case JB_EMPTY:
02336          /* do nothing */
02337          break;
02338       default:
02339          /* shouldn't happen */
02340          break;
02341       }
02342    }
02343    if (pvt)
02344       update_jbsched(pvt);
02345    ast_mutex_unlock(&iaxsl[callno]);
02346 }

static void __iax2_do_register_s ( void *  data  )  [static]

Definition at line 5284 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05285 {
05286    struct iax2_registry *reg = data;
05287    reg->expire = -1;
05288    iax2_do_register(reg);
05289 }

static void __iax2_poke_noanswer ( void *  data  )  [static]

Definition at line 8147 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, and iax2_peer::pokefreqnotok.

Referenced by iax2_poke_noanswer().

08148 {
08149    struct iax2_peer *peer = data;
08150    if (peer->lastms > -1) {
08151       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08152       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08153       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08154    }
08155    if (peer->callno > 0) {
08156       ast_mutex_lock(&iaxsl[peer->callno]);
08157       iax2_destroy(peer->callno);
08158       ast_mutex_unlock(&iaxsl[peer->callno]);
08159    }
08160    peer->callno = 0;
08161    peer->lastms = -1;
08162    /* Try again quickly */
08163    peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer);
08164 }

static void __iax2_poke_peer_s ( void *  data  )  [static]

Definition at line 5958 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by iax2_poke_peer_s().

05959 {
05960    struct iax2_peer *peer = data;
05961    iax2_poke_peer(peer, 0);
05962 }

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

Definition at line 4109 of file chan_iax2.c.

References iax2_peer::addr, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_test_flag, astman_append(), iax2_peer::encmethods, FORMAT, FORMAT2, IAX_DYNAMIC, IAX_TRUNK, iax2_peer::mask, name, peer_status(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

Referenced by iax2_show_peers(), and manager_iax2_show_peers().

04110 {
04111    regex_t regexbuf;
04112    int havepattern = 0;
04113    int total_peers = 0;
04114    int online_peers = 0;
04115    int offline_peers = 0;
04116    int unmonitored_peers = 0;
04117 
04118 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
04119 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
04120 
04121    struct iax2_peer *peer = NULL;
04122    char name[256];
04123    int registeredonly=0;
04124    char *term = manager ? "\r\n" : "\n";
04125 
04126    switch (argc) {
04127    case 6:
04128       if (!strcasecmp(argv[3], "registered"))
04129          registeredonly = 1;
04130       else
04131          return RESULT_SHOWUSAGE;
04132       if (!strcasecmp(argv[4], "like")) {
04133          if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
04134             return RESULT_SHOWUSAGE;
04135          havepattern = 1;
04136       } else
04137          return RESULT_SHOWUSAGE;
04138       break;
04139    case 5:
04140       if (!strcasecmp(argv[3], "like")) {
04141          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04142             return RESULT_SHOWUSAGE;
04143          havepattern = 1;
04144       } else
04145          return RESULT_SHOWUSAGE;
04146       break;
04147    case 4:
04148       if (!strcasecmp(argv[3], "registered"))
04149          registeredonly = 1;
04150       else
04151          return RESULT_SHOWUSAGE;
04152       break;
04153    case 3:
04154       break;
04155    default:
04156       return RESULT_SHOWUSAGE;
04157    }
04158 
04159 
04160    if (s)
04161       astman_append(s, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04162    else
04163       ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04164 
04165    AST_LIST_LOCK(&peers);
04166    AST_LIST_TRAVERSE(&peers, peer, entry) {
04167       char nm[20];
04168       char status[20];
04169       char srch[2000];
04170       int retstatus;
04171 
04172       if (registeredonly && !peer->addr.sin_addr.s_addr)
04173          continue;
04174       if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0))
04175          continue;
04176 
04177       if (!ast_strlen_zero(peer->username))
04178          snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
04179       else
04180          ast_copy_string(name, peer->name, sizeof(name));
04181       
04182       retstatus = peer_status(peer, status, sizeof(status));
04183       if (retstatus > 0)
04184          online_peers++;
04185       else if (!retstatus)
04186          offline_peers++;
04187       else
04188          unmonitored_peers++;
04189       
04190       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
04191       
04192       snprintf(srch, sizeof(srch), FORMAT, name, 
04193           peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04194           ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04195           nm,
04196           ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04197           peer->encmethods ? "(E)" : "   ", status, term);
04198       
04199       if (s)
04200          astman_append(s, FORMAT, name, 
04201                   peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)",
04202                   ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04203                   nm,
04204                   ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04205                   peer->encmethods ? "(E)" : "   ", status, term);
04206       else
04207          ast_cli(fd, FORMAT, name, 
04208             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04209             ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04210             nm,
04211             ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04212             peer->encmethods ? "(E)" : "   ", status, term);
04213       total_peers++;
04214    }
04215    AST_LIST_UNLOCK(&peers);
04216 
04217    if (s)
04218       astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04219    else
04220       ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04221 
04222    if (havepattern)
04223       regfree(&regexbuf);
04224 
04225    return RESULT_SUCCESS;
04226 #undef FORMAT
04227 #undef FORMAT2
04228 }

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

Definition at line 926 of file chan_iax2.c.

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

00927 {
00928    struct iax2_thread *thread = NULL;
00929    static time_t lasterror;
00930    static time_t t;
00931 
00932    thread = find_idle_thread();
00933 
00934    if (thread != NULL) {
00935       thread->schedfunc = func;
00936       thread->scheddata = data;
00937       thread->iostate = IAX_IOSTATE_SCHEDREADY;
00938 #ifdef DEBUG_SCHED_MULTITHREAD
00939       ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc));
00940 #endif
00941       signal_condition(&thread->lock, &thread->cond);
00942       return 0;
00943    }
00944    time(&t);
00945    if (t != lasterror) 
00946       ast_log(LOG_NOTICE, "Out of idle IAX2 threads for scheduling!\n");
00947    lasterror = t;
00948 
00949    return -1;
00950 }

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

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

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

04610 {
04611    struct ast_frame f = { 0, };
04612 
04613    f.frametype = type;
04614    f.subclass = command;
04615    f.datalen = datalen;
04616    f.src = __FUNCTION__;
04617    f.data = (void *) data;
04618 
04619    return iax2_send(i, &f, ts, seqno, now, transfer, final);
04620 }

static void __send_lagrq ( void *  data  )  [static]

Definition at line 990 of file chan_iax2.c.

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

Referenced by send_lagrq().

00991 {
00992    int callno = (long)data;
00993    /* Ping only if it's real not if it's bridged */
00994    ast_mutex_lock(&iaxsl[callno]);
00995    if (iaxs[callno] && iaxs[callno]->lagid != -1) {
00996       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
00997       iaxs[callno]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
00998    }
00999    ast_mutex_unlock(&iaxsl[callno]);
01000 }

static void __send_ping ( void *  data  )  [static]

Definition at line 956 of file chan_iax2.c.

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

Referenced by send_ping().

00957 {
00958    int callno = (long)data;
00959    ast_mutex_lock(&iaxsl[callno]);
00960    if (iaxs[callno] && iaxs[callno]->pingid != -1) {
00961       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
00962       iaxs[callno]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, data);
00963    }
00964    ast_mutex_unlock(&iaxsl[callno]);
00965 }

static int __unload_module ( void   )  [static]

Definition at line 10246 of file chan_iax2.c.

References 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, papp, sched_context_destroy(), thread, and waresl.

Referenced by load_module(), and unload_module().

10247 {
10248    struct iax2_thread *thread = NULL;
10249    int x;
10250 
10251    /* Make sure threads do not hold shared resources when they are canceled */
10252    
10253    /* Grab the sched lock resource to keep it away from threads about to die */
10254    /* Cancel the network thread, close the net socket */
10255    if (netthreadid != AST_PTHREADT_NULL) {
10256       AST_LIST_LOCK(&iaxq.queue);
10257       ast_mutex_lock(&sched_lock);
10258       pthread_cancel(netthreadid);
10259       ast_cond_signal(&sched_cond);
10260       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
10261       AST_LIST_UNLOCK(&iaxq.queue);
10262       pthread_join(netthreadid, NULL);
10263    }
10264    if (schedthreadid != AST_PTHREADT_NULL) {
10265       ast_mutex_lock(&sched_lock);  
10266       pthread_cancel(schedthreadid);
10267       ast_cond_signal(&sched_cond);
10268       ast_mutex_unlock(&sched_lock);   
10269       pthread_join(schedthreadid, NULL);
10270    }
10271    
10272    /* Call for all threads to halt */
10273    AST_LIST_LOCK(&idle_list);
10274    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
10275       AST_LIST_REMOVE_CURRENT(&idle_list, list);
10276       pthread_cancel(thread->threadid);
10277    }
10278    AST_LIST_TRAVERSE_SAFE_END
10279    AST_LIST_UNLOCK(&idle_list);
10280 
10281    AST_LIST_LOCK(&active_list);
10282    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
10283       AST_LIST_REMOVE_CURRENT(&active_list, list);
10284       pthread_cancel(thread->threadid);
10285    }
10286    AST_LIST_TRAVERSE_SAFE_END
10287    AST_LIST_UNLOCK(&active_list);
10288 
10289    AST_LIST_LOCK(&dynamic_list);
10290         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
10291       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
10292       pthread_cancel(thread->threadid);
10293         }
10294    AST_LIST_TRAVERSE_SAFE_END
10295         AST_LIST_UNLOCK(&dynamic_list);
10296 
10297    AST_LIST_HEAD_DESTROY(&iaxq.queue);
10298 
10299    /* Wait for threads to exit */
10300    while(0 < iaxactivethreadcount)
10301       usleep(10000);
10302    
10303    ast_netsock_release(netsock);
10304    ast_netsock_release(outsock);
10305    for (x=0;x<IAX_MAX_CALLS;x++)
10306       if (iaxs[x])
10307          iax2_destroy(x);
10308    ast_manager_unregister( "IAXpeers" );
10309    ast_manager_unregister( "IAXnetstats" );
10310    ast_unregister_application(papp);
10311    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10312    ast_unregister_switch(&iax2_switch);
10313    ast_channel_unregister(&iax2_tech);
10314    delete_users();
10315    iax_provision_unload();
10316    sched_context_destroy(sched);
10317 
10318    ast_mutex_destroy(&waresl.lock);
10319 
10320    for (x = 0; x < IAX_MAX_CALLS; x++)
10321       ast_mutex_destroy(&iaxsl[x]);
10322 
10323    return 0;
10324 }

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

Definition at line 4653 of file chan_iax2.c.

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

Referenced by check_access().

04654 {
04655    while(con) {
04656       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
04657          return -1;
04658       con = con->next;
04659    }
04660    return 0;
04661 }

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

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

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

04437 {
04438    int x;
04439    int numchans = 0;
04440    for (x=0;x<IAX_MAX_CALLS;x++) {
04441       ast_mutex_lock(&iaxsl[x]);
04442       if (iaxs[x]) {
04443          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04444          char *fmt;
04445          jb_info jbinfo;
04446          
04447          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04448             jb_getinfo(iaxs[x]->jb, &jbinfo);
04449             localjitter = jbinfo.jitter;
04450             localdelay = jbinfo.current - jbinfo.min;
04451             locallost = jbinfo.frames_lost;
04452             locallosspct = jbinfo.losspct/1000;
04453             localdropped = jbinfo.frames_dropped;
04454             localooo = jbinfo.frames_ooo;
04455          } else {
04456             localjitter = -1;
04457             localdelay = 0;
04458             locallost = -1;
04459             locallosspct = -1;
04460             localdropped = 0;
04461             localooo = -1;
04462          }
04463          if (limit_fmt)
04464             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04465          else
04466             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04467          if (s)
04468             
04469             astman_append(s, fmt,
04470                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04471                      iaxs[x]->pingtime,
04472                      localjitter, 
04473                      localdelay,
04474                      locallost,
04475                      locallosspct,
04476                      localdropped,
04477                      localooo,
04478                      iaxs[x]->frames_received/1000,
04479                      iaxs[x]->remote_rr.jitter,
04480                      iaxs[x]->remote_rr.delay,
04481                      iaxs[x]->remote_rr.losscnt,
04482                      iaxs[x]->remote_rr.losspct,
04483                      iaxs[x]->remote_rr.dropped,
04484                      iaxs[x]->remote_rr.ooo,
04485                      iaxs[x]->remote_rr.packets/1000);
04486          else
04487             ast_cli(fd, fmt,
04488                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04489                iaxs[x]->pingtime,
04490                localjitter, 
04491                localdelay,
04492                locallost,
04493                locallosspct,
04494                localdropped,
04495                localooo,
04496                iaxs[x]->frames_received/1000,
04497                iaxs[x]->remote_rr.jitter,
04498                iaxs[x]->remote_rr.delay,
04499                iaxs[x]->remote_rr.losscnt,
04500                iaxs[x]->remote_rr.losspct,
04501                iaxs[x]->remote_rr.dropped,
04502                iaxs[x]->remote_rr.ooo,
04503                iaxs[x]->remote_rr.packets/1000
04504                );
04505          numchans++;
04506       }
04507       ast_mutex_unlock(&iaxsl[x]);
04508    }
04509    return numchans;
04510 }

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

Create new call, interface with the PBX core.

Definition at line 3345 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_name, ast_callerid::cid_num, 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().

03346 {
03347    struct ast_channel *tmp;
03348    struct chan_iax2_pvt *i;
03349    struct ast_variable *v = NULL;
03350 
03351    if (!(i = iaxs[callno])) {
03352       ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
03353       return NULL;
03354    }
03355 
03356    /* Don't hold call lock */
03357    ast_mutex_unlock(&iaxsl[callno]);
03358    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);
03359    ast_mutex_lock(&iaxsl[callno]);
03360    if (!tmp)
03361       return NULL;
03362    tmp->tech = &iax2_tech;
03363    /* We can support any format by default, until we get restricted */
03364    tmp->nativeformats = capability;
03365    tmp->readformat = ast_best_codec(capability);
03366    tmp->writeformat = ast_best_codec(capability);
03367    tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
03368 
03369    /* Don't use ast_set_callerid() here because it will
03370     * generate a NewCallerID event before the NewChannel event */
03371    tmp->cid.cid_num = ast_strdup(i->cid_num);
03372    tmp->cid.cid_name = ast_strdup(i->cid_name);
03373    if (!ast_strlen_zero(i->ani))
03374       tmp->cid.cid_ani = ast_strdup(i->ani);
03375    else
03376       tmp->cid.cid_ani = ast_strdup(i->cid_num);
03377    tmp->cid.cid_dnid = ast_strdup(i->dnid);
03378    tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
03379    tmp->cid.cid_pres = i->calling_pres;
03380    tmp->cid.cid_ton = i->calling_ton;
03381    tmp->cid.cid_tns = i->calling_tns;
03382    if (!ast_strlen_zero(i->language))
03383       ast_string_field_set(tmp, language, i->language);
03384    if (!ast_strlen_zero(i->accountcode))
03385       ast_string_field_set(tmp, accountcode, i->accountcode);
03386    if (i->amaflags)
03387       tmp->amaflags = i->amaflags;
03388    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
03389    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
03390    if (i->adsi)
03391       tmp->adsicpe = i->peeradsicpe;
03392    else
03393       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
03394    i->owner = tmp;
03395    i->capability = capability;
03396 
03397    for (v = i->vars ; v ; v = v->next)
03398       pbx_builtin_setvar_helper(tmp, v->name, v->value);
03399 
03400    if (state != AST_STATE_DOWN) {
03401       if (ast_pbx_start(tmp)) {
03402          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
03403          ast_hangup(tmp);
03404          i->owner = NULL;
03405          return NULL;
03406       }
03407    }
03408 
03409    ast_module_ref(ast_module_info->self);
03410    
03411    return tmp;
03412 }

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 ( peers  ,
iax2_peer   
) [static]

static AST_LIST_HEAD_STATIC ( users  ,
iax2_user   
) [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 1955 of file chan_iax2.c.

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

01956 {
01957 #ifdef SCHED_MULTITHREADED
01958    if (schedule_action(__attempt_transmit, data))
01959 #endif      
01960       __attempt_transmit(data);
01961    return 0;
01962 }

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

Definition at line 5876 of file chan_iax2.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), auth_reject(), chan_iax2_pvt::authfail, chan_iax2_pvt::authid, iaxs, and iaxsl.

Referenced by socket_process().

05877 {
05878    /* Schedule sending the authentication failure in one second, to prevent
05879       guessing */
05880    ast_mutex_lock(&iaxsl[callno]);
05881    if (iaxs[callno]) {
05882       iaxs[callno]->authfail = failcode;
05883       if (delayreject) {
05884          if (iaxs[callno]->authid > -1)
05885             ast_sched_del(sched, iaxs[callno]->authid);
05886          iaxs[callno]->authid = ast_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
05887       } else
05888          auth_reject((void *)(long)callno);
05889    }
05890    ast_mutex_unlock(&iaxsl[callno]);
05891    return 0;
05892 }

static int auth_reject ( void *  data  )  [static]

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

05863 {
05864    int callno = (int)(long)(data);
05865    ast_mutex_lock(&iaxsl[callno]);
05866    if (iaxs[callno])
05867       iaxs[callno]->authid = -1;
05868    ast_mutex_unlock(&iaxsl[callno]);
05869 #ifdef SCHED_MULTITHREADED
05870    if (schedule_action(__auth_reject, data))
05871 #endif      
05872       __auth_reject(data);
05873    return 0;
05874 }

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 5171 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, MD5Final(), MD5Init(), and MD5Update().

05172 {
05173    int res = -1;
05174    int x;
05175    if (!ast_strlen_zero(keyn)) {
05176       if (!(authmethods & IAX_AUTH_RSA)) {
05177          if (ast_strlen_zero(secret)) 
05178             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));
05179       } else if (ast_strlen_zero(challenge)) {
05180          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
05181       } else {
05182          char sig[256];
05183          struct ast_key *key;
05184          key = ast_key_get(keyn, AST_KEY_PRIVATE);
05185          if (!key) {
05186             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
05187          } else {
05188             if (ast_sign(key, (char*)challenge, sig)) {
05189                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
05190                res = -1;
05191             } else {
05192                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
05193                res = 0;
05194             }
05195          }
05196       }
05197    } 
05198    /* Fall back */
05199    if (res && !ast_strlen_zero(secret)) {
05200       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
05201          struct MD5Context md5;
05202          unsigned char digest[16];
05203          char digres[128];
05204          MD5Init(&md5);
05205          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
05206          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
05207          MD5Final(digest, &md5);
05208          /* If they support md5, authenticate with it.  */
05209          for (x=0;x<16;x++)
05210             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
05211          if (ecx && dcx)
05212             build_enc_keys(digest, ecx, dcx);
05213          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
05214          res = 0;
05215       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
05216          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
05217          res = 0;
05218       } else
05219          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
05220    }
05221    return res;
05222 }

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

Definition at line 5224 of file chan_iax2.c.

References iax2_peer::addr, AST_FRAME_IAX, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_set_flag, ast_string_field_set, ast_strlen_zero(), ast_test_flag, authenticate(), iax_ies::authmethods, iax_ie_data::buf, iax_ies::challenge, chan_iax2_pvt::dcx, destroy_peer(), chan_iax2_pvt::ecx, chan_iax2_pvt::encmethods, iax_ies::encmethods, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, IAX_TEMPONLY, iax2_peer::mask, merge_encryption(), iax_ie_data::pos, realtime_peer(), send_command(), and iax_ies::username.

Referenced by socket_process().

05225 {
05226    struct iax2_peer *peer = NULL;
05227    /* Start pessimistic */
05228    int res = -1;
05229    int authmethods = 0;
05230    struct iax_ie_data ied;
05231    
05232    memset(&ied, 0, sizeof(ied));
05233    
05234    if (ies->username)
05235       ast_string_field_set(p, username, ies->username);
05236    if (ies->challenge)
05237       ast_string_field_set(p, challenge, ies->challenge);
05238    if (ies->authmethods)
05239       authmethods = ies->authmethods;
05240    if (authmethods & IAX_AUTH_MD5)
05241       merge_encryption(p, ies->encmethods);
05242    else
05243       p->encmethods = 0;
05244 
05245    /* Check for override RSA authentication first */
05246    if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) {
05247       /* Normal password authentication */
05248       res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05249    } else {
05250       AST_LIST_LOCK(&peers);
05251       AST_LIST_TRAVERSE(&peers, peer, entry) {
05252          if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
05253              /* No peer specified at our end, or this is the peer */
05254              && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
05255              /* No username specified in peer rule, or this is the right username */
05256              && (!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)))
05257              /* No specified host, or this is our host */
05258             ) {
05259             res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05260             if (!res)
05261                break;   
05262          }
05263       }
05264       AST_LIST_UNLOCK(&peers);
05265       if (!peer) {
05266          /* We checked our list and didn't find one.  It's unlikely, but possible, 
05267             that we're trying to authenticate *to* a realtime peer */
05268          if ((peer = realtime_peer(p->peer, NULL))) {
05269             res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05270             if (ast_test_flag(peer, IAX_TEMPONLY))
05271                destroy_peer(peer);
05272          }
05273       }
05274    }
05275    if (ies->encmethods)
05276       ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
05277    if (!res)
05278       res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);
05279    return res;
05280 }

static int authenticate_request ( struct chan_iax2_pvt p  )  [static]

Definition at line 4896 of file chan_iax2.c.

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

Referenced by socket_process().

04897 {
04898    struct iax2_user *user = NULL;
04899    struct iax_ie_data ied;
04900    int res = -1, authreq_restrict = 0;
04901    char challenge[10];
04902 
04903    memset(&ied, 0, sizeof(ied));
04904 
04905    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
04906    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
04907       AST_LIST_LOCK(&users);
04908       AST_LIST_TRAVERSE(&users, user, entry) {
04909          if (!strcmp(user->name, p->username)) {
04910             if (user->curauthreq == user->maxauthreq)
04911                authreq_restrict = 1;
04912             else
04913                user->curauthreq++;
04914             break;
04915          }
04916       }
04917       AST_LIST_UNLOCK(&users);
04918    }
04919 
04920    /* If the AUTHREQ limit test failed, send back an error */
04921    if (authreq_restrict) {
04922       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
04923       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
04924       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
04925       return 0;
04926    }
04927 
04928    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
04929    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
04930       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
04931       ast_string_field_set(p, challenge, challenge);
04932       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
04933       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
04934    }
04935    if (p->encmethods)
04936       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
04937 
04938    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
04939 
04940    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
04941 
04942    if (p->encmethods)
04943       ast_set_flag(p, IAX_ENCRYPTED);
04944 
04945    return res;
04946 }

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

Definition at line 4948 of file chan_iax2.c.

References ast_check_signature, ast_clear_flag, ast_key_get, AST_KEY_PUBLIC, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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, key(), LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, iax_ies::rsa_result, secret, chan_iax2_pvt::state, and strsep().

Referenced by socket_process().

04949 {
04950    char requeststr[256];
04951    char md5secret[256] = "";
04952    char secret[256] = "";
04953    char rsasecret[256] = "";
04954    int res = -1; 
04955    int x;
04956    struct iax2_user *user = NULL;
04957 
04958    AST_LIST_LOCK(&users);
04959    AST_LIST_TRAVERSE(&users, user, entry) {
04960       if (!strcmp(user->name, p->username))
04961          break;
04962    }
04963    if (user) {
04964       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
04965          user->curauthreq--;
04966          ast_clear_flag(p, IAX_MAXAUTHREQ);
04967       }
04968       ast_string_field_set(p, host, user->name);
04969    }
04970    AST_LIST_UNLOCK(&users);
04971 
04972    if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
04973       return res;
04974    if (ies->password)
04975       ast_copy_string(secret, ies->password, sizeof(secret));
04976    if (ies->md5_result)
04977       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
04978    if (ies->rsa_result)
04979       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
04980    if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) {
04981       struct ast_key *key;
04982       char *keyn;
04983       char tmpkey[256];
04984       char *stringp=NULL;
04985       ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey));
04986       stringp=tmpkey;
04987       keyn = strsep(&stringp, ":");
04988       while(keyn) {
04989          key = ast_key_get(keyn, AST_KEY_PUBLIC);
04990          if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
04991             res = 0;
04992             break;
04993          } else if (!key)
04994             ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
04995          keyn = strsep(&stringp, ":");
04996       }
04997    } else if (p->authmethods & IAX_AUTH_MD5) {
04998       struct MD5Context md5;
04999       unsigned char digest[16];
05000       char *tmppw, *stringp;
05001       
05002       tmppw = ast_strdupa(p->secret);
05003       stringp = tmppw;
05004       while((tmppw = strsep(&stringp, ";"))) {
05005          MD5Init(&md5);
05006          MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge));
05007          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05008          MD5Final(digest, &md5);
05009          /* If they support md5, authenticate with it.  */
05010          for (x=0;x<16;x++)
05011             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05012          if (!strcasecmp(requeststr, md5secret)) {
05013             res = 0;
05014             break;
05015          }
05016       }
05017    } else if (p->authmethods & IAX_AUTH_PLAINTEXT) {
05018       if (!strcmp(secret, p->secret))
05019          res = 0;
05020    }
05021    return res;
05022 }

static int auto_congest ( void *  data  )  [static]

Definition at line 2773 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

02774 {
02775 #ifdef SCHED_MULTITHREADED
02776    if (schedule_action(__auto_congest, data))
02777 #endif      
02778       __auto_congest(data);
02779    return 0;
02780 }

static int auto_hangup ( void *  data  )  [static]

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

05910 {
05911    int callno = (int)(long)(data);
05912    ast_mutex_lock(&iaxsl[callno]);
05913    if (iaxs[callno]) {
05914       iaxs[callno]->autoid = -1;
05915    }
05916    ast_mutex_unlock(&iaxsl[callno]);
05917 #ifdef SCHED_MULTITHREADED
05918    if (schedule_action(__auto_hangup, data))
05919 #endif      
05920       __auto_hangup(data);
05921    return 0;
05922 }

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

Definition at line 8444 of file chan_iax2.c.

References ast_calloc, and iax2_context::context.

Referenced by build_user().

08445 {
08446    struct iax2_context *con;
08447 
08448    if ((con = ast_calloc(1, sizeof(*con))))
08449       ast_copy_string(con->context, context, sizeof(con->context));
08450    
08451    return con;
08452 }

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

Definition at line 3706 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

03707 {
03708    aes_encrypt_key128(digest, ecx);
03709    aes_decrypt_key128(digest, dcx);
03710 }

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

Create peer structure based on configuration.

Definition at line 8569 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_clear_flag, ast_copy_flags, ast_dnsmgr_lookup(), ast_free_ha(), ast_get_ip(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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(), iax2_peer::authmethods, iax2_peer::capability, cid_name, cid_num, iax2_peer::defaddr, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, iax2_peer::dnsmgr, iax2_peer::encmethods, iax2_peer::expire, iax2_peer::expiry, free, get_auth_methods(), get_encrypt_methods(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mask, iax2_peer::maxms, ast_variable::name, ast_variable::next, peer_set_srcaddr(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax2_user::prefs, iax2_peer::prefs, secret, iax2_peer::smoothing, iax2_peer::sockfd, and ast_variable::value.

08570 {
08571    struct iax2_peer *peer = NULL;
08572    struct ast_ha *oldha = NULL;
08573    int maskfound=0;
08574    int found=0;
08575    int firstpass=1;
08576 
08577    AST_LIST_LOCK(&peers);
08578    if (!temponly) {
08579       AST_LIST_TRAVERSE(&peers, peer, entry) {
08580          if (!strcmp(peer->name, name)) { 
08581             if (!ast_test_flag(peer, IAX_DELME))
08582                firstpass = 0;
08583             break;
08584          }
08585       }
08586    } else
08587       peer = NULL;   
08588    if (peer) {
08589       found++;
08590       if (firstpass) {
08591          oldha = peer->ha;
08592          peer->ha = NULL;
08593       }
08594       AST_LIST_REMOVE(&peers, peer, entry);
08595       AST_LIST_UNLOCK(&peers);
08596    } else {
08597       AST_LIST_UNLOCK(&peers);
08598       if ((peer = ast_calloc(1, sizeof(*peer)))) {
08599          peer->expire = -1;
08600          peer->pokeexpire = -1;
08601          peer->sockfd = defaultsockfd;
08602          if (ast_string_field_init(peer, 32)) {
08603             free(peer);
08604             peer = NULL;
08605          }
08606       }
08607    }
08608    if (peer) {
08609       if (firstpass) {
08610          ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08611          peer->encmethods = iax2_encryption;
08612          peer->adsi = adsi;
08613          ast_string_field_set(peer,secret,"");
08614          if (!found) {
08615             ast_string_field_set(peer, name, name);
08616             peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
08617             peer->expiry = min_reg_expire;
08618          }
08619          peer->prefs = prefs;
08620          peer->capability = iax2_capability;
08621          peer->smoothing = 0;
08622          peer->pokefreqok = DEFAULT_FREQ_OK;
08623          peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
08624          ast_string_field_set(peer,context,"");
08625          ast_string_field_set(peer,peercontext,"");
08626          ast_clear_flag(peer, IAX_HASCALLERID);
08627          ast_string_field_set(peer, cid_name, "");
08628          ast_string_field_set(peer, cid_num, "");
08629       }
08630 
08631       if (!v) {
08632          v = alt;
08633          alt = NULL;
08634       }
08635       while(v) {
08636          if (!strcasecmp(v->name, "secret")) {
08637             ast_string_field_set(peer, secret, v->value);
08638          } else if (!strcasecmp(v->name, "mailbox")) {
08639             ast_string_field_set(peer, mailbox, v->value);
08640          } else if (!strcasecmp(v->name, "mohinterpret")) {
08641             ast_string_field_set(peer, mohinterpret, v->value);
08642          } else if (!strcasecmp(v->name, "mohsuggest")) {
08643             ast_string_field_set(peer, mohsuggest, v->value);
08644          } else if (!strcasecmp(v->name, "dbsecret")) {
08645             ast_string_field_set(peer, dbsecret, v->value);
08646          } else if (!strcasecmp(v->name, "trunk")) {
08647             ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK);   
08648             if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) {
08649                ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without zaptel timing\n", peer->name);
08650                ast_clear_flag(peer, IAX_TRUNK);
08651             }
08652          } else if (!strcasecmp(v->name, "auth")) {
08653             peer->authmethods = get_auth_methods(v->value);
08654          } else if (!strcasecmp(v->name, "encryption")) {
08655             peer->encmethods = get_encrypt_methods(v->value);
08656          } else if (!strcasecmp(v->name, "notransfer")) {
08657             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
08658             ast_clear_flag(peer, IAX_TRANSFERMEDIA);  
08659             ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 
08660          } else if (!strcasecmp(v->name, "transfer")) {
08661             if (!strcasecmp(v->value, "mediaonly")) {
08662                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
08663             } else if (ast_true(v->value)) {
08664                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
08665             } else 
08666                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
08667          } else if (!strcasecmp(v->name, "jitterbuffer")) {
08668             ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF);  
08669          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
08670             ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF);   
08671          } else if (!strcasecmp(v->name, "host")) {
08672             if (!strcasecmp(v->value, "dynamic")) {
08673                /* They'll register with us */
08674                ast_set_flag(peer, IAX_DYNAMIC); 
08675                if (!found) {
08676                   /* Initialize stuff iff we're not found, otherwise
08677                      we keep going with what we had */
08678                   memset(&peer->addr.sin_addr, 0, 4);
08679                   if (peer->addr.sin_port) {
08680                      /* If we've already got a port, make it the default rather than absolute */
08681                      peer->defaddr.sin_port = peer->addr.sin_port;
08682                      peer->addr.sin_port = 0;
08683                   }
08684                }
08685             } else {
08686                /* Non-dynamic.  Make sure we become that way if we're not */
08687                if (peer->expire > -1)
08688                   ast_sched_del(sched, peer->expire);
08689                peer->expire = -1;
08690                ast_clear_flag(peer, IAX_DYNAMIC);
08691                if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr)) {
08692                   ast_string_field_free_pools(peer);
08693                   free(peer);
08694                   return NULL;
08695                }
08696                if (!peer->addr.sin_port)
08697                   peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
08698             }
08699             if (!maskfound)
08700                inet_aton("255.255.255.255", &peer->mask);
08701          } else if (!strcasecmp(v->name, "defaultip")) {
08702             if (ast_get_ip(&peer->defaddr, v->value)) {
08703                ast_string_field_free_pools(peer);
08704                free(peer);
08705                return NULL;
08706             }
08707          } else if (!strcasecmp(v->name, "sourceaddress")) {
08708             peer_set_srcaddr(peer, v->value);
08709          } else if (!strcasecmp(v->name, "permit") ||
08710                   !strcasecmp(v->name, "deny")) {
08711             peer->ha = ast_append_ha(v->name, v->value, peer->ha);
08712          } else if (!strcasecmp(v->name, "mask")) {
08713             maskfound++;
08714             inet_aton(v->value, &peer->mask);
08715          } else if (!strcasecmp(v->name, "context")) {
08716             ast_string_field_set(peer, context, v->value);
08717          } else if (!strcasecmp(v->name, "regexten")) {
08718             ast_string_field_set(peer, regexten, v->value);
08719          } else if (!strcasecmp(v->name, "peercontext")) {
08720             ast_string_field_set(peer, peercontext, v->value);
08721          } else if (!strcasecmp(v->name, "port")) {
08722             if (ast_test_flag(peer, IAX_DYNAMIC))
08723                peer->defaddr.sin_port = htons(atoi(v->value));
08724             else
08725                peer->addr.sin_port = htons(atoi(v->value));
08726          } else if (!strcasecmp(v->name, "username")) {
08727             ast_string_field_set(peer, username, v->value);
08728          } else if (!strcasecmp(v->name, "allow")) {
08729             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1);
08730          } else if (!strcasecmp(v->name, "disallow")) {
08731             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0);
08732          } else if (!strcasecmp(v->name, "callerid")) {
08733             if (!ast_strlen_zero(v->value)) {
08734                char name2[80];
08735                char num2[80];
08736                ast_callerid_split(v->value, name2, 80, num2, 80);
08737                ast_string_field_set(peer, cid_name, name2);
08738                ast_string_field_set(peer, cid_num, num2);
08739                ast_set_flag(peer, IAX_HASCALLERID);
08740             } else {
08741                ast_clear_flag(peer, IAX_HASCALLERID);
08742                ast_string_field_set(peer, cid_name, "");
08743                ast_string_field_set(peer, cid_num, "");
08744             }
08745          } else if (!strcasecmp(v->name, "fullname")) {
08746             if (!ast_strlen_zero(v->value)) {
08747                ast_string_field_set(peer, cid_name, v->value);
08748                ast_set_flag(peer, IAX_HASCALLERID);
08749             } else {
08750                ast_string_field_set(peer, cid_name, "");
08751                if (ast_strlen_zero(peer->cid_num))
08752                   ast_clear_flag(peer, IAX_HASCALLERID);
08753             }
08754          } else if (!strcasecmp(v->name, "cid_number")) {
08755             if (!ast_strlen_zero(v->value)) {
08756                ast_string_field_set(peer, cid_num, v->value);
08757                ast_set_flag(peer, IAX_HASCALLERID);
08758             } else {
08759                ast_string_field_set(peer, cid_num, "");
08760                if (ast_strlen_zero(peer->cid_name))
08761                   ast_clear_flag(peer, IAX_HASCALLERID);
08762             }
08763          } else if (!strcasecmp(v->name, "sendani")) {
08764             ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 
08765          } else if (!strcasecmp(v->name, "inkeys")) {
08766             ast_string_field_set(peer, inkeys, v->value);
08767          } else if (!strcasecmp(v->name, "outkey")) {
08768             ast_string_field_set(peer, outkey, v->value);
08769          } else if (!strcasecmp(v->name, "qualify")) {
08770             if (!strcasecmp(v->value, "no")) {
08771                peer->maxms = 0;
08772             } else if (!strcasecmp(v->value, "yes")) {
08773                peer->maxms = DEFAULT_MAXMS;
08774             } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
08775                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);
08776                peer->maxms = 0;
08777             }
08778          } else if (!strcasecmp(v->name, "qualifysmoothing")) {
08779             peer->smoothing = ast_true(v->value);
08780          } else if (!strcasecmp(v->name, "qualifyfreqok")) {
08781             if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) {
08782                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);
08783             }
08784          } else if (!strcasecmp(v->name, "qualifyfreqnotok")) {
08785             if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) {
08786                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);
08787             } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok);
08788          } else if (!strcasecmp(v->name, "timezone")) {
08789             ast_string_field_set(peer, zonetag, v->value);
08790          } else if (!strcasecmp(v->name, "adsi")) {
08791             peer->adsi = ast_true(v->value);
08792          }/* else if (strcasecmp(v->name,"type")) */
08793          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
08794          v = v->next;
08795          if (!v) {
08796             v = alt;
08797             alt = NULL;
08798          }
08799       }
08800       if (!peer->authmethods)
08801          peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
08802       ast_clear_flag(peer, IAX_DELME); 
08803       /* Make sure these are IPv4 addresses */
08804       peer->addr.sin_family = AF_INET;
08805    }
08806    if (oldha)
08807       ast_free_ha(oldha);
08808    return peer;
08809 }

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

Create in-memory user structure from configuration.

Definition at line 8812 of file chan_iax2.c.

References iax2_user::adsi, iax2_user::amaflags, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_clear_flag, ast_copy_flags, ast_free_ha(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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, iax2_user::contexts, iax2_user::curauthreq, iax2_user::encmethods, format, free, free_context(), get_auth_methods(), get_encrypt_methods(), iax2_user::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, iax2_context::next, iax2_user::prefs, secret, ast_variable::value, and iax2_user::vars.

08813 {
08814    struct iax2_user *user = NULL;
08815    struct iax2_context *con, *conl = NULL;
08816    struct ast_ha *oldha = NULL;
08817    struct iax2_context *oldcon = NULL;
08818    int format;
08819    int firstpass=1;
08820    int oldcurauthreq = 0;
08821    char *varname = NULL, *varval = NULL;
08822    struct ast_variable *tmpvar = NULL;
08823    
08824    AST_LIST_LOCK(&users);
08825    if (!temponly) {
08826       AST_LIST_TRAVERSE(&users, user, entry) {
08827          if (!strcmp(user->name, name)) { 
08828             if (!ast_test_flag(user, IAX_DELME))
08829                firstpass = 0;
08830             break;
08831          }
08832       }
08833    } else
08834       user = NULL;
08835 
08836    if (user) {
08837       if (firstpass) {
08838          oldcurauthreq = user->curauthreq;
08839          oldha = user->ha;
08840          oldcon = user->contexts;
08841          user->ha = NULL;
08842          user->contexts = NULL;
08843       }
08844       /* Already in the list, remove it and it will be added back (or FREE'd) */
08845       AST_LIST_REMOVE(&users, user, entry);
08846       AST_LIST_UNLOCK(&users);
08847    } else {
08848       AST_LIST_UNLOCK(&users);
08849       /* This is going to memset'd to 0 in the next block */
08850       user = ast_calloc(sizeof(*user),1);
08851    }
08852    
08853    if (user) {
08854       if (firstpass) {
08855          ast_string_field_free_pools(user);
08856          memset(user, 0, sizeof(struct iax2_user));
08857          if (ast_string_field_init(user, 32)) {
08858             free(user);
08859             user = NULL;
08860          }
08861          user->maxauthreq = maxauthreq;
08862          user->curauthreq = oldcurauthreq;
08863          user->prefs = prefs;
08864          user->capability = iax2_capability;
08865          user->encmethods = iax2_encryption;
08866          user->adsi = adsi;
08867          ast_string_field_set(user, name, name);
08868          ast_string_field_set(user, language, language);
08869          ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP);   
08870          ast_clear_flag(user, IAX_HASCALLERID);
08871          ast_string_field_set(user, cid_name, "");
08872          ast_string_field_set(user, cid_num, "");
08873       }
08874       if (!v) {
08875          v = alt;
08876          alt = NULL;
08877       }
08878       while(v) {
08879          if (!strcasecmp(v->name, "context")) {
08880             con = build_context(v->value);
08881             if (con) {
08882                if (conl)
08883                   conl->next = con;
08884                else
08885                   user->contexts = con;
08886                conl = con;
08887             }
08888          } else if (!strcasecmp(v->name, "permit") ||
08889                   !strcasecmp(v->name, "deny")) {
08890             user->ha = ast_append_ha(v->name, v->value, user->ha);
08891          } else if (!strcasecmp(v->name, "setvar")) {
08892             varname = ast_strdupa(v->value);
08893             if (varname && (varval = strchr(varname,'='))) {
08894                *varval = '\0';
08895                varval++;
08896                if((tmpvar = ast_variable_new(varname, varval))) {
08897                   tmpvar->next = user->vars; 
08898                   user->vars = tmpvar;
08899                }
08900             }
08901          } else if (!strcasecmp(v->name, "allow")) {
08902             ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
08903          } else if (!strcasecmp(v->name, "disallow")) {
08904             ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0);
08905          } else if (!strcasecmp(v->name, "trunk")) {
08906             ast_set2_flag(user, ast_true(v->value), IAX_TRUNK);   
08907             if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) {
08908                ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without zaptel timing\n", user->name);
08909                ast_clear_flag(user, IAX_TRUNK);
08910             }
08911          } else if (!strcasecmp(v->name, "auth")) {
08912             user->authmethods = get_auth_methods(v->value);
08913          } else if (!strcasecmp(v->name, "encryption")) {
08914             user->encmethods = get_encrypt_methods(v->value);
08915          } else if (!strcasecmp(v->name, "notransfer")) {
08916             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
08917             ast_clear_flag(user, IAX_TRANSFERMEDIA);  
08918             ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 
08919          } else if (!strcasecmp(v->name, "transfer")) {
08920             if (!strcasecmp(v->value, "mediaonly")) {
08921                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
08922             } else if (ast_true(v->value)) {
08923                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
08924             } else 
08925                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
08926          } else if (!strcasecmp(v->name, "codecpriority")) {
08927             if(!strcasecmp(v->value, "caller"))
08928                ast_set_flag(user, IAX_CODEC_USER_FIRST);
08929             else if(!strcasecmp(v->value, "disabled"))
08930                ast_set_flag(user, IAX_CODEC_NOPREFS);
08931             else if(!strcasecmp(v->value, "reqonly")) {
08932                ast_set_flag(user, IAX_CODEC_NOCAP);
08933                ast_set_flag(user, IAX_CODEC_NOPREFS);
08934             }
08935          } else if (!strcasecmp(v->name, "jitterbuffer")) {
08936             ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF);
08937          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
08938             ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF);
08939          } else if (!strcasecmp(v->name, "dbsecret")) {
08940             ast_string_field_set(user, dbsecret, v->value);
08941          } else if (!strcasecmp(v->name, "secret")) {
08942             if (!ast_strlen_zero(user->secret)) {
08943                char *old = ast_strdupa(user->secret);
08944 
08945                ast_string_field_build(user, secret, "%s;%s", old, v->value);
08946             } else
08947                ast_string_field_set(user, secret, v->value);
08948          } else if (!strcasecmp(v->name, "callerid")) {
08949             if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) {
08950                char name2[80];
08951                char num2[80];
08952                ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
08953                ast_string_field_set(user, cid_name, name2);
08954                ast_string_field_set(user, cid_num, num2);
08955                ast_set_flag(user, IAX_HASCALLERID);
08956             } else {
08957                ast_clear_flag(user, IAX_HASCALLERID);
08958                ast_string_field_set(user, cid_name, "");
08959                ast_string_field_set(user, cid_num, "");
08960             }
08961          } else if (!strcasecmp(v->name, "fullname")) {
08962             if (!ast_strlen_zero(v->value)) {
08963                ast_string_field_set(user, cid_name, v->value);
08964                ast_set_flag(user, IAX_HASCALLERID);
08965             } else {
08966                ast_string_field_set(user, cid_name, "");
08967                if (ast_strlen_zero(user->cid_num))
08968                   ast_clear_flag(user, IAX_HASCALLERID);
08969             }
08970          } else if (!strcasecmp(v->name, "cid_number")) {
08971             if (!ast_strlen_zero(v->value)) {
08972                ast_string_field_set(user, cid_num, v->value);
08973                ast_set_flag(user, IAX_HASCALLERID);
08974             } else {
08975                ast_string_field_set(user, cid_num, "");
08976                if (ast_strlen_zero(user->cid_name))
08977                   ast_clear_flag(user, IAX_HASCALLERID);
08978             }
08979          } else if (!strcasecmp(v->name, "accountcode")) {
08980             ast_string_field_set(user, accountcode, v->value);
08981          } else if (!strcasecmp(v->name, "mohinterpret")) {
08982             ast_string_field_set(user, mohinterpret, v->value);
08983          } else if (!strcasecmp(v->name, "mohsuggest")) {
08984             ast_string_field_set(user, mohsuggest, v->value);
08985          } else if (!strcasecmp(v->name, "language")) {
08986             ast_string_field_set(user, language, v->value);
08987          } else if (!strcasecmp(v->name, "amaflags")) {
08988             format = ast_cdr_amaflags2int(v->value);
08989             if (format < 0) {
08990                ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
08991             } else {
08992                user->amaflags = format;
08993             }
08994          } else if (!strcasecmp(v->name, "inkeys")) {
08995             ast_string_field_set(user, inkeys, v->value);
08996          } else if (!strcasecmp(v->name, "maxauthreq")) {
08997             user->maxauthreq = atoi(v->value);
08998             if (user->maxauthreq < 0)
08999                user->maxauthreq = 0;
09000          } else if (!strcasecmp(v->name, "adsi")) {
09001             user->adsi = ast_true(v->value);
09002          }/* else if (strcasecmp(v->name,"type")) */
09003          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09004          v = v->next;
09005          if (!v) {
09006             v = alt;
09007             alt = NULL;
09008          }
09009       }
09010       if (!user->authmethods) {
09011          if (!ast_strlen_zero(user->secret)) {
09012             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09013             if (!ast_strlen_zero(user->inkeys))
09014                user->authmethods |= IAX_AUTH_RSA;
09015          } else if (!ast_strlen_zero(user->inkeys)) {
09016             user->authmethods = IAX_AUTH_RSA;
09017          } else {
09018             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09019          }
09020       }
09021       ast_clear_flag(user, IAX_DELME);
09022    }
09023    if (oldha)
09024       ast_free_ha(oldha);
09025    if (oldcon)
09026       free_context(oldcon);
09027    return user;
09028 }

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

Definition at line 9552 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, iax_ie_data::buf, chan_iax2_pvt::capability, parsed_dial_string::context, create_addr(), parsed_dial_string::exten, 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, parsed_dial_string::key, LOG_DEBUG, LOG_WARNING, NEW_FORCE, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, iax_ie_data::pos, secret, send_command(), create_addr_info::sockfd, and parsed_dial_string::username.

Referenced by find_cache().

09553 {
09554    struct sockaddr_in sin;
09555    int x;
09556    int callno;
09557    struct iax_ie_data ied;
09558    struct create_addr_info cai;
09559    struct parsed_dial_string pds;
09560    char *tmpstr;
09561 
09562    for (x=0; x<IAX_MAX_CALLS; x++) {
09563       /* Look for an *exact match* call.  Once a call is negotiated, it can only
09564          look up entries for a single context */
09565       if (!ast_mutex_trylock(&iaxsl[x])) {
09566          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
09567             return x;
09568          ast_mutex_unlock(&iaxsl[x]);
09569       }
09570    }
09571 
09572    /* No match found, we need to create a new one */
09573 
09574    memset(&cai, 0, sizeof(cai));
09575    memset(&ied, 0, sizeof(ied));
09576    memset(&pds, 0, sizeof(pds));
09577 
09578    tmpstr = ast_strdupa(data);
09579    parse_dial_string(tmpstr, &pds);
09580 
09581    /* Populate our address from the given */
09582    if (create_addr(pds.peer, &sin, &cai))
09583       return -1;
09584 
09585    ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
09586       pds.peer, pds.username, pds.password, pds.context);
09587 
09588    callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd);
09589    if (callno < 1) {
09590       ast_log(LOG_WARNING, "Unable to create call\n");
09591       return -1;
09592    }
09593 
09594    ast_mutex_lock(&iaxsl[callno]);
09595    ast_string_field_set(iaxs[callno], dproot, data);
09596    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
09597 
09598    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
09599    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
09600    /* the string format is slightly different from a standard dial string,
09601       because the context appears in the 'exten' position
09602    */
09603    if (pds.exten)
09604       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
09605    if (pds.username)
09606       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
09607    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
09608    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
09609    /* Keep password handy */
09610    if (pds.password)
09611       ast_string_field_set(iaxs[callno], secret, pds.password);
09612    if (pds.key)
09613       ast_string_field_set(iaxs[callno], outkey, pds.key);
09614    /* Start the call going */
09615    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
09616 
09617    return callno;
09618 }

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

Definition at line 3576 of file chan_iax2.c.

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

03577 {
03578    /* Returns where in "receive time" we are.  That is, how many ms
03579       since we received (or would have received) the frame with timestamp 0 */
03580    int ms;
03581 #ifdef IAXTESTS
03582    int jit;
03583 #endif /* IAXTESTS */
03584    /* Setup rxcore if necessary */
03585    if (ast_tvzero(p->rxcore)) {
03586       p->rxcore = ast_tvnow();
03587       if (option_debug && iaxdebug)
03588          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
03589                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
03590       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
03591 #if 1
03592       if (option_debug && iaxdebug)
03593          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
03594                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
03595 #endif
03596    }
03597 
03598    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
03599 #ifdef IAXTESTS
03600    if (test_jit) {
03601       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
03602          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
03603          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
03604             jit = -jit;
03605          ms += jit;
03606       }
03607    }
03608    if (test_late) {
03609       ms += test_late;
03610       test_late = 0;
03611    }
03612 #endif /* IAXTESTS */
03613    return ms;
03614 }

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

Definition at line 3458 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, ast_frame::delivery, ast_frame::frametype, iaxs, chan_iax2_pvt::lastsent, LOG_DEBUG, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, chan_iax2_pvt::offset, option_debug, chan_iax2_pvt::peercallno, and ast_frame::samples.

Referenced by iax2_send(), and socket_process().

03459 {
03460    int ms;
03461    int voice = 0;
03462    int genuine = 0;
03463    int adjust;
03464    struct timeval *delivery = NULL;
03465 
03466 
03467    /* What sort of frame do we have?: voice is self-explanatory
03468       "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK
03469       non-genuine frames are CONTROL frames [ringing etc], DTMF
03470       The "genuine" distinction is needed because genuine frames must get a clock-based timestamp,
03471       the others need a timestamp slaved to the voice frames so that they go in sequence
03472    */
03473    if (f) {
03474       if (f->frametype == AST_FRAME_VOICE) {
03475          voice = 1;
03476          delivery = &f->delivery;
03477       } else if (f->frametype == AST_FRAME_IAX) {
03478          genuine = 1;
03479       } else if (f->frametype == AST_FRAME_CNG) {
03480          p->notsilenttx = 0;  
03481       }
03482    }
03483    if (ast_tvzero(p->offset)) {
03484       gettimeofday(&p->offset, NULL);
03485       /* Round to nearest 20ms for nice looking traces */
03486       p->offset.tv_usec -= p->offset.tv_usec % 20000;
03487    }
03488    /* If the timestamp is specified, just send it as is */
03489    if (ts)
03490       return ts;
03491    /* If we have a time that the frame arrived, always use it to make our timestamp */
03492    if (delivery && !ast_tvzero(*delivery)) {
03493       ms = ast_tvdiff_ms(*delivery, p->offset);
03494       if (option_debug > 2 && iaxdebug)
03495          ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno);
03496    } else {
03497       ms = ast_tvdiff_ms(ast_tvnow(), p->offset);
03498       if (ms < 0)
03499          ms = 0;
03500       if (voice) {
03501          /* On a voice frame, use predicted values if appropriate */
03502          if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
03503             /* Adjust our txcore, keeping voice and non-voice synchronized */
03504             /* AN EXPLANATION:
03505                When we send voice, we usually send "calculated" timestamps worked out
03506                on the basis of the number of samples sent. When we send other frames,
03507                we usually send timestamps worked out from the real clock.
03508                The problem is that they can tend to drift out of step because the 
03509                   source channel's clock and our clock may not be exactly at the same rate.
03510                We fix this by continuously "tweaking" p->offset.  p->offset is "time zero"
03511                for this call.  Moving it adjusts timestamps for non-voice frames.
03512                We make the adjustment in the style of a moving average.  Each time we
03513                adjust p->offset by 10% of the difference between our clock-derived
03514                timestamp and the predicted timestamp.  That's why you see "10000"
03515                below even though IAX2 timestamps are in milliseconds.
03516                The use of a moving average avoids offset moving too radically.
03517                Generally, "adjust" roams back and forth around 0, with offset hardly
03518                changing at all.  But if a consistent different starts to develop it
03519                will be eliminated over the course of 10 frames (200-300msecs) 
03520             */
03521             adjust = (ms - p->nextpred);
03522             if (adjust < 0)
03523                p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000));
03524             else if (adjust > 0)
03525                p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000));
03526 
03527             if (!p->nextpred) {
03528                p->nextpred = ms; /*f->samples / 8;*/
03529                if (p->nextpred <= p->lastsent)
03530                   p->nextpred = p->lastsent + 3;
03531             }
03532             ms = p->nextpred;
03533          } else {
03534                 /* in this case, just use the actual
03535             * time, since we're either way off
03536             * (shouldn't happen), or we're  ending a
03537             * silent period -- and seed the next
03538             * predicted time.  Also, round ms to the
03539             * next multiple of frame size (so our
03540             * silent periods are multiples of
03541             * frame size too) */
03542 
03543             if (iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW )
03544                ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n",
03545                   abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW);
03546 
03547             if (f->samples >= 8) /* check to make sure we dont core dump */
03548             {
03549                int diff = ms % (f->samples / 8);
03550                if (diff)
03551                    ms += f->samples/8 - diff;
03552             }
03553 
03554             p->nextpred = ms;
03555             p->notsilenttx = 1;
03556          }
03557       } else {
03558          /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless
03559             it's a genuine frame */
03560          if (genuine) {
03561             /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */
03562             if (ms <= p->lastsent)
03563                ms = p->lastsent + 3;
03564          } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) {
03565             /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */
03566             ms = p->lastsent + 3;
03567          }
03568       }
03569    }
03570    p->lastsent = ms;
03571    if (voice)
03572       p->nextpred = p->nextpred + f->samples / 8;
03573    return ms;
03574 }

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

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

03415 {
03416    unsigned long int mssincetx; /* unsigned to handle overflows */
03417    long int ms, pred;
03418 
03419    tpeer->trunkact = *tv;
03420    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03421    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03422       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03423       tpeer->txtrunktime = *tv;
03424       tpeer->lastsent = 999999;
03425    }
03426    /* Update last transmit time now */
03427    tpeer->lasttxtime = *tv;
03428    
03429    /* Calculate ms offset */
03430    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03431    /* Predict from last value */
03432    pred = tpeer->lastsent + sampms;
03433    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03434       ms = pred;
03435    
03436    /* We never send the same timestamp twice, so fudge a little if we must */
03437    if (ms == tpeer->lastsent)
03438       ms = tpeer->lastsent + 1;
03439    tpeer->lastsent = ms;
03440    return ms;
03441 }

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

Definition at line 4664 of file chan_iax2.c.

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

Referenced by socket_process().

04665 {
04666    /* Start pessimistic */
04667    int res = -1;
04668    int version = 2;
04669    struct iax2_user *user = NULL, *best = NULL;
04670    int bestscore = 0;
04671    int gotcapability = 0;
04672    struct ast_variable *v = NULL, *tmpvar = NULL;
04673 
04674    if (!iaxs[callno])
04675       return res;
04676    if (ies->called_number)
04677       ast_string_field_set(iaxs[callno], exten, ies->called_number);
04678    if (ies->calling_number) {
04679       ast_shrink_phone_number(ies->calling_number);
04680       ast_string_field_set(iaxs[callno], cid_num, ies->calling_number);
04681    }
04682    if (ies->calling_name)
04683       ast_string_field_set(iaxs[callno], cid_name, ies->calling_name);
04684    if (ies->calling_ani)
04685       ast_string_field_set(iaxs[callno], ani, ies->calling_ani);
04686    if (ies->dnid)
04687       ast_string_field_set(iaxs[callno], dnid, ies->dnid);
04688    if (ies->rdnis)
04689       ast_string_field_set(iaxs[callno], rdnis, ies->rdnis);
04690    if (ies->called_context)
04691       ast_string_field_set(iaxs[callno], context, ies->called_context);
04692    if (ies->language)
04693       ast_string_field_set(iaxs[callno], language, ies->language);
04694    if (ies->username)
04695       ast_string_field_set(iaxs[callno], username, ies->username);
04696    if (ies->calling_ton > -1)
04697       iaxs[callno]->calling_ton = ies->calling_ton;
04698    if (ies->calling_tns > -1)
04699       iaxs[callno]->calling_tns = ies->calling_tns;
04700    if (ies->calling_pres > -1)
04701       iaxs[callno]->calling_pres = ies->calling_pres;
04702    if (ies->format)
04703       iaxs[callno]->peerformat = ies->format;
04704    if (ies->adsicpe)
04705       iaxs[callno]->peeradsicpe = ies->adsicpe;
04706    if (ies->capability) {
04707       gotcapability = 1;
04708       iaxs[callno]->peercapability = ies->capability;
04709    } 
04710    if (ies->version)
04711       version = ies->version;
04712 
04713    /* Use provided preferences until told otherwise for actual preferences */
04714    if(ies->codec_prefs) {
04715       ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
04716       ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
04717    }
04718 
04719    if (!gotcapability) 
04720       iaxs[callno]->peercapability = iaxs[callno]->peerformat;
04721    if (version > IAX_PROTO_VERSION) {
04722       ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 
04723          ast_inet_ntoa(sin->sin_addr), version);
04724       return res;
04725    }
04726    /* Search the userlist for a compatible entry, and fill in the rest */
04727    AST_LIST_LOCK(&users);
04728    AST_LIST_TRAVERSE(&users, user, entry) {
04729       if ((ast_strlen_zero(iaxs[callno]->username) ||          /* No username specified */
04730          !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */
04731          && ast_apply_ha(user->ha, sin)   /* Access is permitted from this IP */
04732          && (ast_strlen_zero(iaxs[callno]->context) ||         /* No context specified */
04733               apply_context(user->contexts, iaxs[callno]->context))) {        /* Context is permitted */
04734          if (!ast_strlen_zero(iaxs[callno]->username)) {
04735             /* Exact match, stop right now. */
04736             best = user;
04737             break;
04738          } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->inkeys)) {
04739             /* No required authentication */
04740             if (user->ha) {
04741                /* There was host authentication and we passed, bonus! */
04742                if (bestscore < 4) {
04743                   bestscore = 4;
04744                   best = user;
04745                }
04746             } else {
04747                /* No host access, but no secret, either, not bad */
04748                if (bestscore < 3) {
04749                   bestscore = 3;
04750                   best = user;
04751                }
04752             }
04753          } else {
04754             if (user->ha) {
04755                /* Authentication, but host access too, eh, it's something.. */
04756                if (bestscore < 2) {
04757                   bestscore = 2;
04758                   best = user;
04759                }
04760             } else {
04761                /* Authentication and no host access...  This is our baseline */
04762                if (bestscore < 1) {
04763                   bestscore = 1;
04764                   best = user;
04765                }
04766             }
04767          }
04768       }
04769    }
04770    AST_LIST_UNLOCK(&users);
04771    user = best;
04772    if (!user && !ast_strlen_zero(iaxs[callno]->username)) {
04773       user = realtime_user(iaxs[callno]->username);
04774       if (user && !ast_strlen_zero(iaxs[callno]->context) &&         /* No context specified */
04775           !apply_context(user->contexts, iaxs[callno]->context)) {      /* Context is permitted */
04776          destroy_user(user);
04777          user = NULL;
04778       }
04779    }
04780    if (user) {
04781       /* We found our match (use the first) */
04782       /* copy vars */
04783       for (v = user->vars ; v ; v = v->next) {
04784          if((tmpvar = ast_variable_new(v->name, v->value))) {
04785             tmpvar->next = iaxs[callno]->vars; 
04786             iaxs[callno]->vars = tmpvar;
04787          }
04788       }
04789       /* If a max AUTHREQ restriction is in place, activate it */
04790       if (user->maxauthreq > 0)
04791          ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ);
04792       iaxs[callno]->prefs = user->prefs;
04793       ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST);
04794       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS);
04795       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP);
04796       iaxs[callno]->encmethods = user->encmethods;
04797       /* Store the requested username if not specified */
04798       if (ast_strlen_zero(iaxs[callno]->username))
04799          ast_string_field_set(iaxs[callno], username, user->name);
04800       /* Store whether this is a trunked call, too, of course, and move if appropriate */
04801       ast_copy_flags(iaxs[callno], user, IAX_TRUNK);
04802       iaxs[callno]->capability = user->capability;
04803       /* And use the default context */
04804       if (ast_strlen_zero(iaxs[callno]->context)) {
04805          if (user->contexts)
04806             ast_string_field_set(iaxs[callno], context, user->contexts->context);
04807          else
04808             ast_string_field_set(iaxs[callno], context, context);
04809       }
04810       /* And any input keys */
04811       ast_string_field_set(iaxs[callno], inkeys, user->inkeys);
04812       /* And the permitted authentication methods */
04813       iaxs[callno]->authmethods = user->authmethods;
04814       iaxs[callno]->adsi = user->adsi;
04815       /* If they have callerid, override the given caller id.  Always store the ANI */
04816       if (!ast_strlen_zero(iaxs[callno]->cid_num) || !ast_strlen_zero(iaxs[callno]->cid_name)) {
04817          if (ast_test_flag(user, IAX_HASCALLERID)) {
04818             iaxs[callno]->calling_tns = 0;
04819             iaxs[callno]->calling_ton = 0;
04820             ast_string_field_set(iaxs[callno], cid_num, user->cid_num);
04821             ast_string_field_set(iaxs[callno], cid_name, user->cid_name);
04822             iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
04823          }
04824          if (ast_strlen_zero(iaxs[callno]->ani))
04825             ast_string_field_set(iaxs[callno], ani, user->cid_num);
04826       } else {
04827          iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE;
04828       }
04829       if (!ast_strlen_zero(user->accountcode))
04830          ast_string_field_set(iaxs[callno], accountcode, user->accountcode);
04831       if (!ast_strlen_zero(user->mohinterpret))
04832          ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret);
04833       if (!ast_strlen_zero(user->mohsuggest))
04834          ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest);
04835       if (user->amaflags)
04836          iaxs[callno]->amaflags = user->amaflags;
04837       if (!ast_strlen_zero(user->language))
04838          ast_string_field_set(iaxs[callno], language, user->language);
04839       ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);   
04840       /* Keep this check last */
04841       if (!ast_strlen_zero(user->dbsecret)) {
04842          char *family, *key=NULL;
04843          char buf[80];
04844          family = ast_strdupa(user->dbsecret);
04845          key = strchr(family, '/');
04846          if (key) {
04847             *key = '\0';
04848             key++;
04849          }
04850          if (!key || ast_db_get(family, key, buf, sizeof(buf)))
04851             ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret);
04852          else
04853             ast_string_field_set(iaxs[callno], secret, buf);
04854       } else
04855          ast_string_field_set(iaxs[callno], secret, user->secret);
04856       if (ast_test_flag(user, IAX_TEMPONLY))
04857          destroy_user(user);
04858       res = 0;
04859    }
04860    ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);  
04861    return res;
04862 }

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

Definition at line 6260 of file chan_iax2.c.

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

Referenced by socket_process().

06261 {
06262    unsigned int ourver;
06263    char rsi[80];
06264    snprintf(rsi, sizeof(rsi), "si-%s", si);
06265    if (iax_provision_version(&ourver, rsi, 1))
06266       return 0;
06267    if (option_debug)
06268       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06269    if (ourver != ver) 
06270       iax2_provision(sin, sockfd, NULL, rsi, 1);
06271    return 0;
06272 }

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

References ast_log(), LOG_DEBUG, and LOG_ERROR.

Referenced by peer_set_srcaddr().

08471 {
08472    int sd;
08473    int res;
08474    
08475    sd = socket(AF_INET, SOCK_DGRAM, 0);
08476    if (sd < 0) {
08477       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
08478       return -1;
08479    }
08480 
08481    res = bind(sd, sa, salen);
08482    if (res < 0) {
08483       ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
08484       close(sd);
08485       return 1;
08486    }
08487 
08488    close(sd);
08489    return 0;
08490 }

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

Definition at line 5329 of file chan_iax2.c.

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

Referenced by socket_process().

05330 {
05331    char exten[256] = "";
05332    int status = CACHE_FLAG_UNKNOWN;
05333    int expiry = iaxdefaultdpcache;
05334    int x;
05335    int matchmore = 0;
05336    struct iax2_dpcache *dp, *prev;
05337    
05338    if (ies->called_number)
05339       ast_copy_string(exten, ies->called_number, sizeof(exten));
05340 
05341    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
05342       status = CACHE_FLAG_EXISTS;
05343    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
05344       status = CACHE_FLAG_CANEXIST;
05345    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
05346       status = CACHE_FLAG_NONEXISTENT;
05347 
05348    if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
05349       /* Don't really do anything with this */
05350    }
05351    if (ies->refresh)
05352       expiry = ies->refresh;
05353    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
05354       matchmore = CACHE_FLAG_MATCHMORE;
05355    ast_mutex_lock(&dpcache_lock);
05356    prev = NULL;
05357    dp = pvt->dpentries;
05358    while(dp) {
05359       if (!strcmp(dp->exten, exten)) {
05360          /* Let them go */
05361          if (prev)
05362             prev->peer = dp->peer;
05363          else
05364             pvt->dpentries = dp->peer;
05365          dp->peer = NULL;
05366          dp->callno = 0;
05367          dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
05368          if (dp->flags & CACHE_FLAG_PENDING) {
05369             dp->flags &= ~CACHE_FLAG_PENDING;
05370             dp->flags |= status;
05371             dp->flags |= matchmore;
05372          }
05373          /* Wake up waiters */
05374          for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
05375             if (dp->waiters[x] > -1)
05376                write(dp->waiters[x], "asdf", 4);
05377       }
05378       prev = dp;
05379       dp = dp->peer;
05380    }
05381    ast_mutex_unlock(&dpcache_lock);
05382    return 0;
05383 }

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

Definition at line 2117 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_strdup.

02118 {
02119    int which = 0;
02120    struct iax2_peer *p = NULL;
02121    char *res = NULL;
02122    int wordlen = strlen(word);
02123 
02124    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02125    if (pos == 3) {
02126       AST_LIST_LOCK(&peers);
02127       AST_LIST_TRAVERSE(&peers, p, entry) {
02128          if (!strncasecmp(p->name, word, wordlen) && ++which > state) {
02129             res = ast_strdup(p->name);
02130             break;
02131          }
02132       }
02133       AST_LIST_UNLOCK(&peers);
02134    }
02135 
02136    return res;
02137 }

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

Definition at line 5385 of file chan_iax2.c.

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

05386 {
05387    int peercallno = 0;
05388    struct chan_iax2_pvt *pvt = iaxs[callno];
05389    struct iax_frame *cur;
05390    jb_frame frame;
05391 
05392    if (ies->callno)
05393       peercallno = ies->callno;
05394 
05395    if (peercallno < 1) {
05396       ast_log(LOG_WARNING, "Invalid transfer request\n");
05397       return -1;
05398    }
05399    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
05400    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
05401    /* Reset sequence numbers */
05402    pvt->oseqno = 0;
05403    pvt->rseqno = 0;
05404    pvt->iseqno = 0;
05405    pvt->aseqno = 0;
05406    pvt->peercallno = peercallno;
05407    pvt->transferring = TRANSFER_NONE;
05408    pvt->svoiceformat = -1;
05409    pvt->voiceformat = 0;
05410    pvt->svideoformat = -1;
05411    pvt->videoformat = 0;
05412    pvt->transfercallno = -1;
05413    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
05414    memset(&pvt->offset, 0, sizeof(pvt->offset));
05415    /* reset jitterbuffer */
05416    while(jb_getall(pvt->jb,&frame) == JB_OK)
05417       iax2_frame_free(frame.data);
05418    jb_reset(pvt->jb);
05419    pvt->lag = 0;
05420    pvt->last = 0;
05421    pvt->lastsent = 0;
05422    pvt->nextpred = 0;
05423    pvt->pingtime = DEFAULT_RETRY_TIME;
05424    AST_LIST_LOCK(&iaxq.queue);
05425    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
05426       /* We must cancel any packets that would have been transmitted
05427          because now we're talking to someone new.  It's okay, they
05428          were transmitted to someone that didn't care anyway. */
05429       if (callno == cur->callno) 
05430          cur->retries = -1;
05431    }
05432    AST_LIST_UNLOCK(&iaxq.queue);
05433    return 0; 
05434 }

static unsigned char compress_subclass ( int  subclass  )  [static]

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

01012 {
01013    int x;
01014    int power=-1;
01015    /* If it's 128 or smaller, just return it */
01016    if (subclass < IAX_FLAG_SC_LOG)
01017       return subclass;
01018    /* Otherwise find its power */
01019    for (x = 0; x < IAX_MAX_SHIFT; x++) {
01020       if (subclass & (1 << x)) {
01021          if (power > -1) {
01022             ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass);
01023             return 0;
01024          } else
01025             power = x;
01026       }
01027    }
01028    return power | IAX_FLAG_SC_LOG;
01029 }

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

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

06275 {
06276    jb_info stats;
06277    jb_getinfo(pvt->jb, &stats);
06278    
06279    memset(iep, 0, sizeof(*iep));
06280 
06281    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06282    if(stats.frames_in == 0) stats.frames_in = 1;
06283    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06284    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06285    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06286    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06287    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06288 }

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

Definition at line 2671 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ast_clear_flag, ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, iax2_peer::capability, create_addr_info::capability, create_addr_info::context, iax2_peer::defaddr, destroy_peer(), iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, hp, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TEMPONLY, 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, create_addr_info::peercontext, iax2_peer::prefs, create_addr_info::prefs, iax2_user::prefs, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, and create_addr_info::username.

02672 {
02673    struct ast_hostent ahp;
02674    struct hostent *hp;
02675    struct iax2_peer *peer;
02676 
02677    ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
02678    cai->sockfd = defaultsockfd;
02679    cai->maxtime = 0;
02680    sin->sin_family = AF_INET;
02681 
02682    if (!(peer = find_peer(peername, 1))) {
02683       cai->found = 0;
02684 
02685       hp = ast_gethostbyname(peername, &ahp);
02686       if (hp) {
02687          memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
02688          sin->sin_port = htons(IAX_DEFAULT_PORTNO);
02689          /* use global iax prefs for unknown peer/user */
02690          ast_codec_pref_convert(&prefs, cai->prefs, sizeof(cai->prefs), 1);
02691          return 0;
02692       } else {
02693          ast_log(LOG_WARNING, "No such host: %s\n", peername);
02694          return -1;
02695       }
02696    }
02697 
02698    cai->found = 1;
02699    
02700    /* if the peer has no address (current or default), return failure */
02701    if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) {
02702       if (ast_test_flag(peer, IAX_TEMPONLY))
02703          destroy_peer(peer);
02704       return -1;
02705    }
02706 
02707    /* if the peer is being monitored and is currently unreachable, return failure */
02708    if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0))) {
02709       if (ast_test_flag(peer, IAX_TEMPONLY))
02710          destroy_peer(peer);
02711       return -1;
02712    }
02713 
02714    ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
02715    cai->maxtime = peer->maxms;
02716    cai->capability = peer->capability;
02717    cai->encmethods = peer->encmethods;
02718    cai->sockfd = peer->sockfd;
02719    cai->adsi = peer->adsi;
02720    ast_codec_pref_convert(&peer->prefs, cai->prefs, sizeof(cai->prefs), 1);
02721    ast_copy_string(cai->context, peer->context, sizeof(cai->context));
02722    ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
02723    ast_copy_string(cai->username, peer->username, sizeof(cai->username));
02724    ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
02725    ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
02726    ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
02727    ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
02728    if (ast_strlen_zero(peer->dbsecret)) {
02729       ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret));
02730    } else {
02731       char *family;
02732       char *key = NULL;
02733 
02734       family = ast_strdupa(peer->dbsecret);
02735       key = strchr(family, '/');
02736       if (key)
02737          *key++ = '\0';
02738       if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) {
02739          ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret);
02740          if (ast_test_flag(peer, IAX_TEMPONLY))
02741             destroy_peer(peer);
02742          return -1;
02743       }
02744    }
02745 
02746    if (peer->addr.sin_addr.s_addr) {
02747       sin->sin_addr = peer->addr.sin_addr;
02748       sin->sin_port = peer->addr.sin_port;
02749    } else {
02750       sin->sin_addr = peer->defaddr.sin_addr;
02751       sin->sin_port = peer->defaddr.sin_port;
02752    }
02753 
02754    if (ast_test_flag(peer, IAX_TEMPONLY))
02755       destroy_peer(peer);
02756 
02757    return 0;
02758 }

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

Definition at line 3760 of file chan_iax2.c.

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

Referenced by decrypt_frame().

03761 {
03762    int padding;
03763    unsigned char *workspace;
03764 
03765    workspace = alloca(*datalen);
03766    memset(f, 0, sizeof(*f));
03767    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
03768       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
03769       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
03770          return -1;
03771       /* Decrypt */
03772       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
03773 
03774       padding = 16 + (workspace[15] & 0xf);
03775       if (option_debug && iaxdebug)
03776          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
03777       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
03778          return -1;
03779 
03780       *datalen -= padding;
03781       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
03782       f->frametype = fh->type;
03783       if (f->frametype == AST_FRAME_VIDEO) {
03784          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
03785       } else {
03786          f->subclass = uncompress_subclass(fh->csub);
03787       }
03788    } else {
03789       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
03790       if (option_debug && iaxdebug)
03791          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
03792       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
03793          return -1;
03794       /* Decrypt */
03795       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
03796       padding = 16 + (workspace[15] & 0x0f);
03797       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
03798          return -1;
03799       *datalen -= padding;
03800       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
03801    }
03802    return 0;
03803 }

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

Definition at line 3846 of file chan_iax2.c.

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

Referenced by socket_process().

03847 {
03848    int res=-1;
03849    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
03850       /* Search for possible keys, given secrets */
03851       struct MD5Context md5;
03852       unsigned char digest[16];
03853       char *tmppw, *stringp;
03854       
03855       tmppw = ast_strdupa(iaxs[callno]->secret);
03856       stringp = tmppw;
03857       while ((tmppw = strsep(&stringp, ";"))) {
03858          MD5Init(&md5);
03859          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
03860          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
03861          MD5Final(digest, &md5);
03862          build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx);
03863          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
03864          if (!res) {
03865             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
03866             break;
03867          }
03868       }
03869    } else 
03870       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
03871    return res;
03872 }

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

06337 {
06338    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06339    struct ast_iax2_full_hdr *fh, *cur_fh;
06340 
06341    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06342       return;
06343 
06344    pkt_buf->len = from_here->buf_len;
06345    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06346 
06347    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06348    ast_mutex_lock(&to_here->lock);
06349    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06350       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06351       if (fh->oseqno < cur_fh->oseqno) {
06352          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06353          break;
06354       }
06355    }
06356    AST_LIST_TRAVERSE_SAFE_END
06357 
06358    if (!cur_pkt_buf)
06359       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06360    
06361    ast_mutex_unlock(&to_here->lock);
06362 }

static void delete_users ( void   )  [static]

Definition at line 9030 of file chan_iax2.c.

References ast_dnsmgr_release(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), ast_set_flag, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, free, iax2_destroy(), IAX_DELME, iaxs, iaxsl, and chan_iax2_pvt::reg.

09031 {
09032    struct iax2_user *user;
09033    struct iax2_peer *peer;
09034    struct iax2_registry *reg;
09035 
09036    AST_LIST_LOCK(&users);
09037    AST_LIST_TRAVERSE(&users, user, entry)
09038       ast_set_flag(user, IAX_DELME);
09039    AST_LIST_UNLOCK(&users);
09040 
09041    AST_LIST_LOCK(&registrations);
09042    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09043       if (reg->expire > -1)
09044          ast_sched_del(sched, reg->expire);
09045       if (reg->callno) {
09046          ast_mutex_lock(&iaxsl[reg->callno]);
09047          if (iaxs[reg->callno]) {
09048             iaxs[reg->callno]->reg = NULL;
09049             iax2_destroy(reg->callno);
09050          }
09051          ast_mutex_unlock(&iaxsl[reg->callno]);
09052       }
09053       if (reg->dnsmgr)
09054          ast_dnsmgr_release(reg->dnsmgr);
09055       free(reg);
09056    }
09057    AST_LIST_UNLOCK(&registrations);
09058 
09059    AST_LIST_LOCK(&peers);
09060    AST_LIST_TRAVERSE(&peers, peer, entry)
09061       ast_set_flag(peer, IAX_DELME);
09062    AST_LIST_UNLOCK(&peers);
09063 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1368 of file chan_iax2.c.

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

Referenced by reload_firmware().

01369 {
01370    /* Close firmware */
01371    if (cur->fwh) {
01372       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01373    }
01374    close(cur->fd);
01375    free(cur);
01376 }

static void destroy_peer ( struct iax2_peer peer  )  [static]

Definition at line 9093 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, free, iax2_peer::ha, iax2_destroy(), iaxsl, iax2_peer::pokeexpire, and register_peer_exten().

Referenced by authenticate_reply(), create_addr(), iax2_devicestate(), iax2_getpeername(), iax2_show_peer(), prune_peers(), realtime_peer(), register_verify(), registry_authrequest(), and update_registry().

09094 {
09095    ast_free_ha(peer->ha);
09096 
09097    /* Delete it, it needs to disappear */
09098    if (peer->expire > -1)
09099       ast_sched_del(sched, peer->expire);
09100    if (peer->pokeexpire > -1)
09101       ast_sched_del(sched, peer->pokeexpire);
09102    if (peer->callno > 0) {
09103       ast_mutex_lock(&iaxsl[peer->callno]);
09104       iax2_destroy(peer->callno);
09105       ast_mutex_unlock(&iaxsl[peer->callno]);
09106    }
09107 
09108    register_peer_exten(peer, 0);
09109 
09110    if (peer->dnsmgr)
09111       ast_dnsmgr_release(peer->dnsmgr);
09112 
09113    ast_string_field_free_pools(peer);
09114 
09115    free(peer);
09116 }

static void destroy_user ( struct iax2_user user  )  [static]

Definition at line 9065 of file chan_iax2.c.

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

Referenced by check_access(), and prune_users().

09066 {
09067    ast_free_ha(user->ha);
09068    free_context(user->contexts);
09069    if(user->vars) {
09070       ast_variables_destroy(user->vars);
09071       user->vars = NULL;
09072    }
09073    ast_string_field_free_pools(user);
09074    free(user);
09075 }

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

Definition at line 6108 of file chan_iax2.c.

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

Referenced by dp_lookup_thread(), and socket_process().

06109 {
06110    unsigned short dpstatus = 0;
06111    struct iax_ie_data ied1;
06112    int mm;
06113 
06114    memset(&ied1, 0, sizeof(ied1));
06115    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06116    /* Must be started */
06117    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06118       dpstatus = IAX_DPSTATUS_EXISTS;
06119    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06120       dpstatus = IAX_DPSTATUS_CANEXIST;
06121    } else {
06122       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06123    }
06124    if (ast_ignore_pattern(context, callednum))
06125       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06126    if (mm)
06127       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06128    if (!skiplock)
06129       ast_mutex_lock(&iaxsl[callno]);
06130    if (iaxs[callno]) {
06131       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06132       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06133       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06134       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06135    }
06136    if (!skiplock)
06137       ast_mutex_unlock(&iaxsl[callno]);
06138 }

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

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

06141 {
06142    /* Look up for dpreq */
06143    struct dpreq_data *dpr = data;
06144    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06145    if (dpr->callerid)
06146       free(dpr->callerid);
06147    free(dpr);
06148    return NULL;
06149 }

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

Definition at line 3805 of file chan_iax2.c.

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

Referenced by iax2_send().

03806 {
03807    int padding;
03808    unsigned char *workspace;
03809    workspace = alloca(*datalen + 32);
03810    if (!workspace)
03811       return -1;
03812    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
03813       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
03814       if (option_debug && iaxdebug)
03815          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
03816       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
03817       padding = 16 + (padding & 0xf);
03818       memcpy(workspace, poo, padding);
03819       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
03820       workspace[15] &= 0xf0;
03821       workspace[15] |= (padding & 0xf);
03822       if (option_debug && iaxdebug)
03823          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]);
03824       *datalen += padding;
03825       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
03826       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
03827          memcpy(poo, workspace + *datalen - 32, 32);
03828    } else {
03829       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
03830       if (option_debug && iaxdebug)
03831          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
03832       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
03833       padding = 16 + (padding & 0xf);
03834       memcpy(workspace, poo, padding);
03835       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
03836       workspace[15] &= 0xf0;
03837       workspace[15] |= (padding & 0x0f);
03838       *datalen += padding;
03839       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
03840       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
03841          memcpy(poo, workspace + *datalen - 32, 32);
03842    }
03843    return 0;
03844 }

static int expire_registry ( void *  data  )  [static]

Definition at line 5608 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

05609 {
05610 #ifdef SCHED_MULTITHREADED
05611    if (schedule_action(__expire_registry, data))
05612 #endif      
05613       __expire_registry(data);
05614    return 0;
05615 }

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

Definition at line 9620 of file chan_iax2.c.

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

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

09621 {
09622    struct iax2_dpcache *dp, *prev = NULL, *next;
09623    struct timeval tv;
09624    int x;
09625    int com[2];
09626    int timeout;
09627    int old=0;
09628    int outfd;
09629    int abort;
09630    int callno;
09631    struct ast_channel *c;
09632    struct ast_frame *f;
09633    gettimeofday(&tv, NULL);
09634    dp = dpcache;
09635    while(dp) {
09636       next = dp->next;
09637       /* Expire old caches */
09638       if (ast_tvcmp(tv, dp->expiry) > 0) {
09639             /* It's expired, let it disappear */
09640             if (prev)
09641                prev->next = dp->next;
09642             else
09643                dpcache = dp->next;
09644             if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) {
09645                /* Free memory and go again */
09646                free(dp);
09647             } else {
09648                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);
09649             }
09650             dp = next;
09651             continue;
09652       }
09653       /* We found an entry that matches us! */
09654       if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 
09655          break;
09656       prev = dp;
09657       dp = next;
09658    }
09659    if (!dp) {
09660       /* No matching entry.  Create a new one. */
09661       /* First, can we make a callno? */
09662       callno = cache_get_callno_locked(data);
09663       if (callno < 0) {
09664          ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data);
09665          return NULL;
09666       }
09667       if (!(dp = ast_calloc(1, sizeof(*dp)))) {
09668          ast_mutex_unlock(&iaxsl[callno]);
09669          return NULL;
09670       }
09671       ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext));
09672       ast_copy_string(dp->exten, exten, sizeof(dp->exten));
09673       gettimeofday(&dp->expiry, NULL);
09674       dp->orig = dp->expiry;
09675       /* Expires in 30 mins by default */
09676       dp->expiry.tv_sec += iaxdefaultdpcache;
09677       dp->next = dpcache;
09678       dp->flags = CACHE_FLAG_PENDING;
09679       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
09680          dp->waiters[x] = -1;
09681       dpcache = dp;
09682       dp->peer = iaxs[callno]->dpentries;
09683       iaxs[callno]->dpentries = dp;
09684       /* Send the request if we're already up */
09685       if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
09686          iax2_dprequest(dp, callno);
09687       ast_mutex_unlock(&iaxsl[callno]);
09688    }
09689    /* By here we must have a dp */
09690    if (dp->flags & CACHE_FLAG_PENDING) {
09691       /* Okay, here it starts to get nasty.  We need a pipe now to wait
09692          for a reply to come back so long as it's pending */
09693       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) {
09694          /* Find an empty slot */
09695          if (dp->waiters[x] < 0)
09696             break;
09697       }
09698       if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) {
09699          ast_log(LOG_WARNING, "No more waiter positions available\n");
09700          return NULL;
09701       }
09702       if (pipe(com)) {
09703          ast_log(LOG_WARNING, "Unable to create pipe for comm\n");
09704          return NULL;
09705       }
09706       dp->waiters[x] = com[1];
09707       /* Okay, now we wait */
09708       timeout = iaxdefaulttimeout * 1000;
09709       /* Temporarily unlock */
09710       ast_mutex_unlock(&dpcache_lock);
09711       /* Defer any dtmf */
09712       if (chan)
09713          old = ast_channel_defer_dtmf(chan);
09714       abort = 0;
09715       while(timeout) {
09716          c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
09717          if (outfd > -1) {
09718             break;
09719          }
09720          if (c) {
09721             f = ast_read(c);
09722             if (f)
09723                ast_frfree(f);
09724             else {
09725                /* Got hung up on, abort! */
09726                break;
09727                abort = 1;
09728             }
09729          }
09730       }
09731       if (!timeout) {
09732          ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
09733       }
09734       ast_mutex_lock(&dpcache_lock);
09735       dp->waiters[x] = -1;
09736       close(com[1]);
09737       close(com[0]);
09738       if (abort) {
09739          /* Don't interpret anything, just abort.  Not sure what th epoint
09740            of undeferring dtmf on a hung up channel is but hey whatever */
09741          if (!old && chan)
09742             ast_channel_undefer_dtmf(chan);
09743          return NULL;
09744       }
09745       if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
09746          /* Now to do non-independent analysis the results of our wait */
09747          if (dp->flags & CACHE_FLAG_PENDING) {
09748             /* Still pending... It's a timeout.  Wake everybody up.  Consider it no longer
09749                pending.  Don't let it take as long to timeout. */
09750             dp->flags &= ~CACHE_FLAG_PENDING;
09751             dp->flags |= CACHE_FLAG_TIMEOUT;
09752             /* Expire after only 60 seconds now.  This is designed to help reduce backlog in heavily loaded
09753                systems without leaving it unavailable once the server comes back online */
09754             dp->expiry.tv_sec = dp->orig.tv_sec + 60;
09755             for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
09756                if (dp->waiters[x] > -1)
09757                   write(dp->waiters[x], "asdf", 4);
09758          }
09759       }
09760       /* Our caller will obtain the rest */
09761       if (!old && chan)
09762          ast_channel_undefer_dtmf(chan);
09763    }
09764    return dp;  
09765 }

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

Definition at line 1247 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, iax2_getpeername(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, 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, 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().

01248 {
01249    int res = 0;
01250    int x;
01251    struct timeval now;
01252    char host[80];
01253 
01254    if (new <= NEW_ALLOW) {
01255       /* Look for an existing connection first */
01256       for (x=1;(res < 1) && (x<maxnontrunkcall);x++) {
01257          ast_mutex_lock(&iaxsl[x]);
01258          if (iaxs[x]) {
01259             /* Look for an exact match */
01260             if (match(sin, callno, dcallno, iaxs[x])) {
01261                res = x;
01262             }
01263          }
01264          ast_mutex_unlock(&iaxsl[x]);
01265       }
01266       for (x=TRUNK_CALL_START;(res < 1) && (x<maxtrunkcall);x++) {
01267          ast_mutex_lock(&iaxsl[x]);
01268          if (iaxs[x]) {
01269             /* Look for an exact match */
01270             if (match(sin, callno, dcallno, iaxs[x])) {
01271                res = x;
01272             }
01273          }
01274          ast_mutex_unlock(&iaxsl[x]);
01275       }
01276    }
01277    if ((res < 1) && (new >= NEW_ALLOW)) {
01278       /* It may seem odd that we look through the peer list for a name for
01279        * this *incoming* call.  Well, it is weird.  However, users don't
01280        * have an IP address/port number that we can match against.  So,
01281        * this is just checking for a peer that has that IP/port and
01282        * assuming that we have a user of the same name.  This isn't always
01283        * correct, but it will be changed if needed after authentication. */
01284       if (!iax2_getpeername(*sin, host, sizeof(host), lockpeer))
01285          snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
01286       gettimeofday(&now, NULL);
01287       for (x=1;x<TRUNK_CALL_START;x++) {
01288          /* Find first unused call number that hasn't been used in a while */
01289          ast_mutex_lock(&iaxsl[x]);
01290          if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) break;
01291          ast_mutex_unlock(&iaxsl[x]);
01292       }
01293       /* We've still got lock held if we found a spot */
01294       if (x >= TRUNK_CALL_START) {
01295          ast_log(LOG_WARNING, "No more space\n");
01296          return 0;
01297       }
01298       iaxs[x] = new_iax(sin, lockpeer, host);
01299       update_max_nontrunk();
01300       if (iaxs[x]) {
01301          if (option_debug && iaxdebug)
01302             ast_log(LOG_DEBUG, "Creating new call structure %d\n", x);
01303          iaxs[x]->sockfd = sockfd;
01304          iaxs[x]->addr.sin_port = sin->sin_port;
01305          iaxs[x]->addr.sin_family = sin->sin_family;
01306          iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr;
01307          iaxs[x]->peercallno = callno;
01308          iaxs[x]->callno = x;
01309          iaxs[x]->pingtime = DEFAULT_RETRY_TIME;
01310          iaxs[x]->expiry = min_reg_expire;
01311          iaxs[x]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01312          iaxs[x]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01313          iaxs[x]->amaflags = amaflags;
01314          ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
01315          
01316          ast_string_field_set(iaxs[x], accountcode, accountcode);
01317          ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
01318          ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
01319       } else {
01320          ast_log(LOG_WARNING, "Out of resources\n");
01321          ast_mutex_unlock(&iaxsl[x]);
01322          return 0;
01323       }
01324       ast_mutex_unlock(&iaxsl[x]);
01325       res = x;
01326    }
01327    return res;
01328 }

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

Definition at line 877 of file chan_iax2.c.

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

Referenced by __schedule_action(), and socket_read().

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

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

Definition at line 1045 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and realtime_peer().

01046 {
01047    struct iax2_peer *peer = NULL;
01048 
01049    /* Grab peer from linked list */
01050    AST_LIST_LOCK(&peers);
01051    AST_LIST_TRAVERSE(&peers, peer, entry) {
01052       if (!strcasecmp(peer->name, name)) {
01053          break;
01054       }
01055    }
01056    AST_LIST_UNLOCK(&peers);
01057 
01058    /* Now go for realtime if applicable */
01059    if(!peer && realtime)
01060       peer = realtime_peer(name, NULL);
01061    return peer;
01062 }

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

Definition at line 3616 of file chan_iax2.c.

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

Referenced by iax2_trunk_queue(), and socket_process().

03617 {
03618    struct iax2_trunk_peer *tpeer;
03619    
03620    /* Finds and locks trunk peer */
03621    ast_mutex_lock(&tpeerlock);
03622    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
03623       /* We don't lock here because tpeer->addr *never* changes */
03624       if (!inaddrcmp(&tpeer->addr, sin)) {
03625          ast_mutex_lock(&tpeer->lock);
03626          break;
03627       }
03628    }
03629    if (!tpeer) {
03630       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
03631          ast_mutex_init(&tpeer->lock);
03632          tpeer->lastsent = 9999;
03633          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
03634          tpeer->trunkact = ast_tvnow();
03635          ast_mutex_lock(&tpeer->lock);
03636          tpeer->next = tpeers;
03637          tpeer->sockfd = fd;
03638          tpeers = tpeer;
03639 #ifdef SO_NO_CHECK
03640          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
03641 #endif
03642          ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
03643       }
03644    }
03645    ast_mutex_unlock(&tpeerlock);
03646    return tpeer;
03647 }

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

Definition at line 3443 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03444 {
03445    long ms; /* NOT unsigned */
03446    if (ast_tvzero(iaxs[callno]->rxcore)) {
03447       /* Initialize rxcore time if appropriate */
03448       gettimeofday(&iaxs[callno]->rxcore, NULL);
03449       /* Round to nearest 20ms so traces look pretty */
03450       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03451    }
03452    /* Calculate difference between trunk and channel */
03453    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03454    /* Return as the sum of trunk time and the difference between trunk and real time */
03455    return ms + ts;
03456 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8225 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and destroy_user().

08226 {
08227    struct iax2_context *conl;
08228    while(con) {
08229       conl = con;
08230       con = con->next;
08231       free(conl);
08232    }
08233 }

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

Todo:
: will be removed after the 1.4 relese

Definition at line 9889 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::capability, iax2_peer::expire, find_peer(), iax2_tech, IAX_DYNAMIC, iaxs, peer_status(), iax2_peer::prefs, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.

09890 {
09891    struct iax2_peer *peer;
09892    char *peername, *colname;
09893 
09894    peername = ast_strdupa(data);
09895 
09896    /* if our channel, return the IP address of the endpoint of current channel */
09897    if (!strcmp(peername,"CURRENTCHANNEL")) {
09898            unsigned short callno;
09899       if (chan->tech != &iax2_tech)
09900          return -1;
09901       callno = PTR_TO_CALLNO(chan->tech_pvt);   
09902       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
09903       return 0;
09904    }
09905 
09906    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
09907       *colname++ = '\0';
09908    else if ((colname = strchr(peername, '|')))
09909       *colname++ = '\0';
09910    else
09911       colname = "ip";
09912 
09913    if (!(peer = find_peer(peername, 1)))
09914       return -1;
09915 
09916    if (!strcasecmp(colname, "ip")) {
09917       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
09918    } else  if (!strcasecmp(colname, "status")) {
09919       peer_status(peer, buf, len); 
09920    } else  if (!strcasecmp(colname, "mailbox")) {
09921       ast_copy_string(buf, peer->mailbox, len);
09922    } else  if (!strcasecmp(colname, "context")) {
09923       ast_copy_string(buf, peer->context, len);
09924    } else  if (!strcasecmp(colname, "expire")) {
09925       snprintf(buf, len, "%d", peer->expire);
09926    } else  if (!strcasecmp(colname, "dynamic")) {
09927       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
09928    } else  if (!strcasecmp(colname, "callerid_name")) {
09929       ast_copy_string(buf, peer->cid_name, len);
09930    } else  if (!strcasecmp(colname, "callerid_num")) {
09931       ast_copy_string(buf, peer->cid_num, len);
09932    } else  if (!strcasecmp(colname, "codecs")) {
09933       ast_getformatname_multiple(buf, len -1, peer->capability);
09934    } else  if (!strncasecmp(colname, "codec[", 6)) {
09935       char *codecnum, *ptr;
09936       int index = 0, codec = 0;
09937       
09938       codecnum = strchr(colname, '[');
09939       *codecnum = '\0';
09940       codecnum++;
09941       if ((ptr = strchr(codecnum, ']'))) {
09942          *ptr = '\0';
09943       }
09944       index = atoi(codecnum);
09945       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
09946          ast_copy_string(buf, ast_getformatname(codec), len);
09947       }
09948    }
09949 
09950    return 0;
09951 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 8454 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

08455 {
08456    int methods = 0;
08457    if (strstr(value, "rsa"))
08458       methods |= IAX_AUTH_RSA;
08459    if (strstr(value, "md5"))
08460       methods |= IAX_AUTH_MD5;
08461    if (strstr(value, "plaintext"))
08462       methods |= IAX_AUTH_PLAINTEXT;
08463    return methods;
08464 }

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

Definition at line 976 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

00977 {
00978    int e;
00979    if (!strcasecmp(s, "aes128"))
00980       e = IAX_ENCRYPT_AES128;
00981    else if (ast_true(s))
00982       e = IAX_ENCRYPT_AES128;
00983    else
00984       e = 0;
00985    return e;
00986 }

static int get_from_jb ( void *  p  )  [static]

Definition at line 2348 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02349 {
02350 #ifdef SCHED_MULTITHREADED
02351    if (schedule_action(__get_from_jb, data))
02352 #endif      
02353       __get_from_jb(data);
02354    return 0;
02355 }

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

Definition at line 6306 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

06307 {
06308    struct iax2_pkt_buf *pkt_buf;
06309 
06310    ast_mutex_lock(&thread->lock);
06311 
06312    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06313       ast_mutex_unlock(&thread->lock);
06314 
06315       thread->buf = pkt_buf->buf;
06316       thread->buf_len = pkt_buf->len;
06317       thread->buf_size = pkt_buf->len + 1;
06318       
06319       socket_process(thread);
06320 
06321       thread->buf = NULL;
06322       ast_free(pkt_buf);
06323 
06324       ast_mutex_lock(&thread->lock);
06325    }
06326 
06327    ast_mutex_unlock(&thread->lock);
06328 }

static int handle_error ( void   )  [static]

Definition at line 1653 of file chan_iax2.c.

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

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

01654 {
01655    /* XXX Ideally we should figure out why an error occured and then abort those
01656       rather than continuing to try.  Unfortunately, the published interface does
01657       not seem to work XXX */
01658 #if 0
01659    struct sockaddr_in *sin;
01660    int res;
01661    struct msghdr m;
01662    struct sock_extended_err e;
01663    m.msg_name = NULL;
01664    m.msg_namelen = 0;
01665    m.msg_iov = NULL;
01666    m.msg_control = &e;
01667    m.msg_controllen = sizeof(e);
01668    m.msg_flags = 0;
01669    res = recvmsg(netsocket, &m, MSG_ERRQUEUE);
01670    if (res < 0)
01671       ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno));
01672    else {
01673       if (m.msg_controllen) {
01674          sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e);
01675          if (sin) 
01676             ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr));
01677          else
01678             ast_log(LOG_WARNING, "No address detected??\n");
01679       } else {
01680          ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno));
01681       }
01682    }
01683 #endif
01684    return 0;
01685 }

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

Acknowledgment received for OUR registration.

Definition at line 5437 of file chan_iax2.c.

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

Referenced by socket_process().

05438 {
05439    struct iax2_registry *reg;
05440    /* Start pessimistic */
05441    char peer[256] = "";
05442    char msgstatus[60];
05443    int refresh = 60;
05444    char ourip[256] = "<Unspecified>";
05445    struct sockaddr_in oldus;
05446    struct sockaddr_in us;
05447    int oldmsgs;
05448 
05449    memset(&us, 0, sizeof(us));
05450    if (ies->apparent_addr)
05451       bcopy(ies->apparent_addr, &us, sizeof(us));
05452    if (ies->username)
05453       ast_copy_string(peer, ies->username, sizeof(peer));
05454    if (ies->refresh)
05455       refresh = ies->refresh;
05456    if (ies->calling_number) {
05457       /* We don't do anything with it really, but maybe we should */
05458    }
05459    reg = iaxs[callno]->reg;
05460    if (!reg) {
05461       ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer);
05462       return -1;
05463    }
05464    memcpy(&oldus, &reg->us, sizeof(oldus));
05465    oldmsgs = reg->messages;
05466    if (inaddrcmp(&reg->addr, sin)) {
05467       ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr));
05468       return -1;
05469    }
05470    memcpy(&reg->us, &us, sizeof(reg->us));
05471    if (ies->msgcount >= 0)
05472       reg->messages = ies->msgcount & 0xffff;      /* only low 16 bits are used in the transmission of the IE */
05473    /* always refresh the registration at the interval requested by the server
05474       we are registering to
05475    */
05476    reg->refresh = refresh;
05477    if (reg->expire > -1)
05478       ast_sched_del(sched, reg->expire);
05479    reg->expire = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
05480    if (inaddrcmp(&oldus, &reg->us) || (reg->messages != oldmsgs)) {
05481       if (option_verbose > 2) {
05482          if (reg->messages > 255)
05483             snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8);
05484          else if (reg->messages > 1)
05485             snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages);
05486          else if (reg->messages > 0)
05487             snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n");
05488          else
05489             snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n");
05490          snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
05491          ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus);
05492       }
05493       manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr));
05494    }
05495    reg->regstate = REG_STATE_REGISTERED;
05496    return 0;
05497 }

static int iax2_answer ( struct ast_channel c  )  [static]

Definition at line 3264 of file chan_iax2.c.

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

03265 {
03266    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03267    if (option_debug)
03268       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03269    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03270 }

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

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

03115 {
03116    struct ast_channel *cs[3];
03117    struct ast_channel *who, *other;
03118    int to = -1;
03119    int res = -1;
03120    int transferstarted=0;
03121    struct ast_frame *f;
03122    unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt);
03123    unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt);
03124    struct timeval waittimer = {0, 0}, tv;
03125 
03126    lock_both(callno0, callno1);
03127    if (!iaxs[callno0] || !iaxs[callno1]) {
03128       unlock_both(callno0, callno1);
03129       return AST_BRIDGE_FAILED;
03130    }
03131    /* Put them in native bridge mode */
03132    if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) {
03133       iaxs[callno0]->bridgecallno = callno1;
03134       iaxs[callno1]->bridgecallno = callno0;
03135    }
03136    unlock_both(callno0, callno1);
03137 
03138    /* If not, try to bridge until we can execute a transfer, if we can */
03139    cs[0] = c0;
03140    cs[1] = c1;
03141    for (/* ever */;;) {
03142       /* Check in case we got masqueraded into */
03143       if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) {
03144          if (option_verbose > 2)
03145             ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n");
03146          /* Remove from native mode */
03147          if (c0->tech == &iax2_tech) {
03148             ast_mutex_lock(&iaxsl[callno0]);
03149             iaxs[callno0]->bridgecallno = 0;
03150             ast_mutex_unlock(&iaxsl[callno0]);
03151          }
03152          if (c1->tech == &iax2_tech) {
03153             ast_mutex_lock(&iaxsl[callno1]);
03154             iaxs[callno1]->bridgecallno = 0;
03155             ast_mutex_unlock(&iaxsl[callno1]);
03156          }
03157          return AST_BRIDGE_FAILED_NOWARN;
03158       }
03159       if (c0->nativeformats != c1->nativeformats) {
03160          if (option_verbose > 2) {
03161             char buf0[255];
03162             char buf1[255];
03163             ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats);
03164             ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats);
03165             ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1);
03166          }
03167          /* Remove from native mode */
03168          lock_both(callno0, callno1);
03169          if (iaxs[callno0])
03170             iaxs[callno0]->bridgecallno = 0;
03171          if (iaxs[callno1])
03172             iaxs[callno1]->bridgecallno = 0;
03173          unlock_both(callno0, callno1);
03174          return AST_BRIDGE_FAILED_NOWARN;
03175       }
03176       /* check if transfered and if we really want native bridging */
03177       if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) {
03178          /* Try the transfer */
03179          if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) ||
03180                      ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA)))
03181             ast_log(LOG_WARNING, "Unable to start the transfer\n");
03182          transferstarted = 1;
03183       }
03184       if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) {
03185          /* Call has been transferred.  We're no longer involved */
03186          gettimeofday(&tv, NULL);
03187          if (ast_tvzero(waittimer)) {
03188             waittimer = tv;
03189          } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) {
03190             c0->_softhangup |= AST_SOFTHANGUP_DEV;
03191             c1->_softhangup |= AST_SOFTHANGUP_DEV;
03192             *fo = NULL;
03193             *rc = c0;
03194             res = AST_BRIDGE_COMPLETE;
03195             break;
03196          }
03197       }
03198       to = 1000;
03199       who = ast_waitfor_n(cs, 2, &to);
03200       if (timeoutms > -1) {
03201          timeoutms -= (1000 - to);
03202          if (timeoutms < 0)
03203             timeoutms = 0;
03204       }
03205       if (!who) {
03206          if (!timeoutms) {
03207             res = AST_BRIDGE_RETRY;
03208             break;
03209          }
03210          if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03211             res = AST_BRIDGE_FAILED;
03212             break;
03213          }
03214          continue;
03215       }
03216       f = ast_read(who);
03217       if (!f) {
03218          *fo = NULL;
03219          *rc = who;
03220          res = AST_BRIDGE_COMPLETE;
03221          break;
03222       }
03223       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03224          *fo = f;
03225          *rc = who;
03226          res =  AST_BRIDGE_COMPLETE;
03227          break;
03228       }
03229       other = (who == c0) ? c1 : c0;  /* the 'other' channel */
03230       if ((f->frametype == AST_FRAME_VOICE) ||
03231           (f->frametype == AST_FRAME_TEXT) ||
03232           (f->frametype == AST_FRAME_VIDEO) || 
03233           (f->frametype == AST_FRAME_IMAGE) ||
03234           (f->frametype == AST_FRAME_DTMF)) {
03235          /* monitored dtmf take out of the bridge.
03236           * check if we monitor the specific source.
03237           */
03238          int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1;
03239          if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) {
03240             *rc = who;
03241             *fo = f;
03242             res = AST_BRIDGE_COMPLETE;
03243             /* Remove from native mode */
03244             break;
03245          }
03246          /* everything else goes to the other side */
03247          ast_write(other, f);
03248       }
03249       ast_frfree(f);
03250       /* Swap who gets priority */
03251       cs[2] = cs[0];
03252       cs[0] = cs[1];
03253       cs[1] = cs[2];
03254    }
03255    lock_both(callno0, callno1);
03256    if(iaxs[callno0])
03257       iaxs[callno0]->bridgecallno = 0;
03258    if(iaxs[callno1])
03259       iaxs[callno1]->bridgecallno = 0;
03260    unlock_both(callno0, callno1);
03261    return res;
03262 }

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

Definition at line 2870 of file chan_iax2.c.

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

02871 {
02872    struct sockaddr_in sin;
02873    char *l=NULL, *n=NULL, *tmpstr;
02874    struct iax_ie_data ied;
02875    char *defaultrdest = "s";
02876    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
02877    struct parsed_dial_string pds;
02878    struct create_addr_info cai;
02879 
02880    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
02881       ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name);
02882       return -1;
02883    }
02884 
02885    memset(&cai, 0, sizeof(cai));
02886    cai.encmethods = iax2_encryption;
02887 
02888    memset(&pds, 0, sizeof(pds));
02889    tmpstr = ast_strdupa(dest);
02890    parse_dial_string(tmpstr, &pds);
02891 
02892    if (!pds.exten)
02893       pds.exten = defaultrdest;
02894 
02895    if (create_addr(pds.peer, &sin, &cai)) {
02896       ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
02897       return -1;
02898    }
02899 
02900    if (!pds.username && !ast_strlen_zero(cai.username))
02901       pds.username = cai.username;
02902    if (!pds.password && !ast_strlen_zero(cai.secret))
02903       pds.password = cai.secret;
02904    if (!pds.key && !ast_strlen_zero(cai.outkey))
02905       pds.key = cai.outkey;
02906    if (!pds.context && !ast_strlen_zero(cai.peercontext))
02907       pds.context = cai.peercontext;
02908 
02909    /* Keep track of the context for outgoing calls too */
02910    ast_copy_string(c->context, cai.context, sizeof(c->context));
02911 
02912    if (pds.port)
02913       sin.sin_port = htons(atoi(pds.port));
02914 
02915    l = c->cid.cid_num;
02916    n = c->cid.cid_name;
02917 
02918    /* Now build request */ 
02919    memset(&ied, 0, sizeof(ied));
02920 
02921    /* On new call, first IE MUST be IAX version of caller */
02922    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
02923    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten);
02924    if (pds.options && strchr(pds.options, 'a')) {
02925       /* Request auto answer */
02926       iax_ie_append(&ied, IAX_IE_AUTOANSWER);
02927    }
02928 
02929    iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs);
02930 
02931    if (l) {
02932       iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
02933       iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
02934    } else {
02935       if (n)
02936          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
02937       else
02938          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
02939    }
02940 
02941    iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
02942    iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
02943 
02944    if (n)
02945       iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
02946    if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
02947       iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
02948 
02949    if (!ast_strlen_zero(c->language))
02950       iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
02951    if (!ast_strlen_zero(c->cid.cid_dnid))
02952       iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid);
02953    if (!ast_strlen_zero(c->cid.cid_rdnis))
02954       iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis);
02955 
02956    if (pds.context)
02957       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context);
02958 
02959    if (pds.username)
02960       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
02961 
02962    if (cai.encmethods)
02963       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods);
02964 
02965    ast_mutex_lock(&iaxsl[callno]);
02966 
02967    if (!ast_strlen_zero(c->context))
02968       ast_string_field_set(iaxs[callno], context, c->context);
02969 
02970    if (pds.username)
02971       ast_string_field_set(iaxs[callno], username, pds.username);
02972 
02973    iaxs[callno]->encmethods = cai.encmethods;
02974 
02975    iaxs[callno]->adsi = cai.adsi;
02976    
02977    ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret);
02978    ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest);
02979 
02980    if (pds.key)
02981       ast_string_field_set(iaxs[callno], outkey, pds.key);
02982    if (pds.password)
02983       ast_string_field_set(iaxs[callno], secret, pds.password);
02984 
02985    iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats);
02986    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability);
02987    iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe);
02988    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone));
02989 
02990    if (iaxs[callno]->maxtime) {
02991       /* Initialize pingtime and auto-congest time */
02992       iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2;
02993       iaxs[callno]->initid = ast_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno));
02994    } else if (autokill) {
02995       iaxs[callno]->pingtime = autokill / 2;
02996       iaxs[callno]->initid = ast_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno));
02997    }
02998 
02999    /* send the command using the appropriate socket for this peer */
03000    iaxs[callno]->sockfd = cai.sockfd;
03001 
03002    /* Transmit the string in a "NEW" request */
03003    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
03004 
03005    ast_mutex_unlock(&iaxsl[callno]);
03006    ast_setstate(c, AST_STATE_RINGING);
03007    
03008    return 0;
03009 }

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

09792 {
09793    int res = 0;
09794    struct iax2_dpcache *dp;
09795 #if 0
09796    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
09797 #endif
09798    if ((priority != 1) && (priority != 2))
09799       return 0;
09800    ast_mutex_lock(&dpcache_lock);
09801    dp = find_cache(chan, data, context, exten, priority);
09802    if (dp) {
09803       if (dp->flags & CACHE_FLAG_CANEXIST)
09804          res= 1;
09805    }
09806    ast_mutex_unlock(&dpcache_lock);
09807    if (!dp) {
09808       ast_log(LOG_WARNING, "Unable to make DP cache\n");
09809    }
09810    return res;
09811 }

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

Definition at line 2782 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

02783 {
02784    time_t t;
02785    struct tm tm;
02786    unsigned int tmp;
02787    time(&t);
02788    if (!ast_strlen_zero(tz))
02789       ast_localtime(&t, &tm, tz);
02790    else
02791       ast_localtime(&t, &tm, NULL);
02792    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
02793    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
02794    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
02795    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
02796    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
02797    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
02798    return tmp;
02799 }

static void iax2_destroy ( int  callno  )  [static]

Definition at line 1792 of file chan_iax2.c.

References ast_channel::_softhangup, 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_SOFTHANGUP_DEV, 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(), destroy_peer(), iax2_do_register(), iax2_hangup(), iax2_poke_peer(), and socket_process().

01793 {
01794    struct chan_iax2_pvt *pvt;
01795    struct iax_frame *cur;
01796    struct ast_channel *owner;
01797 
01798 retry:
01799    pvt = iaxs[callno];
01800    gettimeofday(&lastused[callno], NULL);
01801    
01802    owner = pvt ? pvt->owner : NULL;
01803 
01804    if (owner) {
01805       if (ast_mutex_trylock(&owner->lock)) {
01806          ast_log(LOG_NOTICE, "Avoiding IAX destroy deadlock\n");
01807          ast_mutex_unlock(&iaxsl[callno]);
01808          usleep(1);
01809          ast_mutex_lock(&iaxsl[callno]);
01810          goto retry;
01811       }
01812    }
01813    if (!owner)
01814       iaxs[callno] = NULL;
01815    if (pvt) {
01816       if (!owner)
01817          pvt->owner = NULL;
01818       iax2_destroy_helper(pvt);
01819 
01820       /* Already gone */
01821       ast_set_flag(pvt, IAX_ALREADYGONE); 
01822 
01823       if (owner) {
01824          /* If there's an owner, prod it to give up */
01825          owner->_softhangup |= AST_SOFTHANGUP_DEV;
01826          ast_queue_hangup(owner);
01827       }
01828 
01829       AST_LIST_LOCK(&iaxq.queue);
01830       AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
01831          /* Cancel any pending transmissions */
01832          if (cur->callno == pvt->callno) 
01833             cur->retries = -1;
01834       }
01835       AST_LIST_UNLOCK(&iaxq.queue);
01836 
01837       if (pvt->reg)
01838          pvt->reg->callno = 0;
01839       if (!owner) {
01840          jb_frame frame;
01841          if (pvt->vars) {
01842              ast_variables_destroy(pvt->vars);
01843              pvt->vars = NULL;
01844          }
01845 
01846          while (jb_getall(pvt->jb, &frame) == JB_OK)
01847             iax2_frame_free(frame.data);
01848          jb_destroy(pvt->jb);
01849          /* gotta free up the stringfields */
01850          ast_string_field_free_pools(pvt);
01851          free(pvt);
01852       }
01853    }
01854    if (owner) {
01855       ast_mutex_unlock(&owner->lock);
01856    }
01857    if (callno & 0x4000)
01858       update_max_trunk();
01859 }

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1733 of file chan_iax2.c.

References ast_clear_flag, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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, and chan_iax2_pvt::pingid.

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

01734 {
01735    struct iax2_user *user = NULL;
01736 
01737    /* Decrement AUTHREQ count if needed */
01738    if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
01739       AST_LIST_LOCK(&users);
01740       AST_LIST_TRAVERSE(&users, user, entry) {
01741          if (!strcmp(user->name, pvt->username)) {
01742             user->curauthreq--;
01743             break;
01744          }
01745       }
01746       AST_LIST_UNLOCK(&users);
01747       ast_clear_flag(pvt, IAX_MAXAUTHREQ);
01748    }
01749    /* No more pings or lagrq's */
01750    if (pvt->pingid > -1)
01751       ast_sched_del(sched, pvt->pingid);
01752    pvt->pingid = -1;
01753    if (pvt->lagid > -1)
01754       ast_sched_del(sched, pvt->lagid);
01755    pvt->lagid = -1;
01756    if (pvt->autoid > -1)
01757       ast_sched_del(sched, pvt->autoid);
01758    pvt->autoid = -1;
01759    if (pvt->authid > -1)
01760       ast_sched_del(sched, pvt->authid);
01761    pvt->authid = -1;
01762    if (pvt->initid > -1)
01763       ast_sched_del(sched, pvt->initid);
01764    pvt->initid = -1;
01765    if (pvt->jbid > -1)
01766       ast_sched_del(sched, pvt->jbid);
01767    pvt->jbid = -1;
01768 }

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

Definition at line 9976 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(), ast_test_flag, iax2_peer::defaddr, destroy_peer(), find_peer(), iax2_peer::historicms, IAX_TEMPONLY, iax2_peer::lastms, LOG_DEBUG, iax2_peer::maxms, option_debug, parse_dial_string(), and parsed_dial_string::peer.

09977 {
09978    struct parsed_dial_string pds;
09979    char *tmp = ast_strdupa(data);
09980    struct iax2_peer *p;
09981    int res = AST_DEVICE_INVALID;
09982 
09983    memset(&pds, 0, sizeof(pds));
09984    parse_dial_string(tmp, &pds);
09985    if (ast_strlen_zero(pds.peer))
09986       return res;
09987    
09988    if (option_debug > 2)
09989       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
09990 
09991    /* SLD: FIXME: second call to find_peer during registration */
09992    if (!(p = find_peer(pds.peer, 1)))
09993       return res;
09994 
09995    res = AST_DEVICE_UNAVAILABLE;
09996    if (option_debug > 2) 
09997       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
09998          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
09999    
10000    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
10001        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
10002       /* Peer is registered, or have default IP address
10003          and a valid registration */
10004       if (p->historicms == 0 || p->historicms <= p->maxms)
10005          /* let the core figure out whether it is in use or not */
10006          res = AST_DEVICE_UNKNOWN;  
10007    }
10008 
10009    if (ast_test_flag(p, IAX_TEMPONLY))
10010       destroy_peer(p);
10011 
10012    return res;
10013 }

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

Definition at line 2466 of file chan_iax2.c.

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

02467 {
02468    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02469 }

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

Definition at line 2471 of file chan_iax2.c.

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

02472 {
02473    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02474 }

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

Definition at line 4524 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04525 {
04526    if (argc < 2 || argc > 3)
04527       return RESULT_SHOWUSAGE;
04528    iaxdebug = 1;
04529    ast_cli(fd, "IAX2 Debugging Enabled\n");
04530    return RESULT_SUCCESS;
04531 }

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

Definition at line 4542 of file chan_iax2.c.

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

04543 {
04544    if (argc < 3 || argc > 4)
04545       return RESULT_SHOWUSAGE;
04546    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04547    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04548    return RESULT_SUCCESS;
04549 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 7970 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(), iax_ie_data::buf, 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_DEBUG, LOG_WARNING, NEW_FORCE, option_debug, iax_ie_data::pos, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, send_command(), and iax2_registry::username.

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

07971 {
07972    struct iax_ie_data ied;
07973    if (option_debug && iaxdebug)
07974       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
07975 
07976    if (reg->dnsmgr && 
07977        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
07978       /* Maybe the IP has changed, force DNS refresh */
07979       ast_dnsmgr_refresh(reg->dnsmgr);
07980    }
07981    
07982    /*
07983     * if IP has Changed, free allocated call to create a new one with new IP
07984     * call has the pointer to IP and must be updated to the new one
07985     */
07986    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
07987       ast_mutex_lock(&iaxsl[reg->callno]);
07988       iax2_destroy(reg->callno);
07989       ast_mutex_unlock(&iaxsl[reg->callno]);
07990       reg->callno = 0;
07991    }
07992    if (!reg->addr.sin_addr.s_addr) {
07993       if (option_debug && iaxdebug)
07994          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
07995       /* Setup the next registration attempt */
07996       if (reg->expire > -1)
07997          ast_sched_del(sched, reg->expire);
07998       reg->expire  = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
07999       return -1;
08000    }
08001 
08002    if (!reg->callno) {
08003       if (option_debug)
08004          ast_log(LOG_DEBUG, "Allocate call number\n");
08005       reg->callno = find_callno(0, 0, &reg->addr, NEW_FORCE, 1, defaultsockfd);
08006       if (reg->callno < 1) {
08007          ast_log(LOG_WARNING, "Unable to create call for registration\n");
08008          return -1;
08009       } else if (option_debug)
08010          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
08011       iaxs[reg->callno]->reg = reg;
08012    }
08013    /* Schedule the next registration attempt */
08014    if (reg->expire > -1)
08015       ast_sched_del(sched, reg->expire);
08016    /* Setup the next registration a little early */
08017    reg->expire  = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08018    /* Send the request */
08019    memset(&ied, 0, sizeof(ied));
08020    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
08021    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
08022    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
08023    reg->regstate = REG_STATE_REGSENT;
08024    return 0;
08025 }

static int iax2_do_register_s ( void *  data  )  [static]

Definition at line 5291 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05292 {
05293 #ifdef SCHED_MULTITHREADED
05294    if (schedule_action(__iax2_do_register_s, data))
05295 #endif      
05296       __iax2_do_register_s(data);
05297    return 0;
05298 }

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

Definition at line 4533 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04534 {
04535    if (argc < 3 || argc > 4)
04536       return RESULT_SHOWUSAGE;
04537    iaxtrunkdebug = 1;
04538    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04539    return RESULT_SUCCESS;
04540 }

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

Definition at line 5924 of file chan_iax2.c.

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

Referenced by find_cache(), and socket_process().

05925 {
05926    struct iax_ie_data ied;
05927    /* Auto-hangup with 30 seconds of inactivity */
05928    if (iaxs[callno]->autoid > -1)
05929       ast_sched_del(sched, iaxs[callno]->autoid);
05930    iaxs[callno]->autoid = ast_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
05931    memset(&ied, 0, sizeof(ied));
05932    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
05933    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
05934    dp->flags |= CACHE_FLAG_TRANSMITTED;
05935 }

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

09838 {
09839    char odata[256];
09840    char req[256];
09841    char *ncontext;
09842    struct iax2_dpcache *dp;
09843    struct ast_app *dial;
09844 #if 0
09845    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);
09846 #endif
09847    if (priority == 2) {
09848       /* Indicate status, can be overridden in dialplan */
09849       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
09850       if (dialstatus) {
09851          dial = pbx_findapp(dialstatus);
09852          if (dial) 
09853             pbx_exec(chan, dial, "");
09854       }
09855       return -1;
09856    } else if (priority != 1)
09857       return -1;
09858    ast_mutex_lock(&dpcache_lock);
09859    dp = find_cache(chan, data, context, exten, priority);
09860    if (dp) {
09861       if (dp->flags & CACHE_FLAG_EXISTS) {
09862          ast_copy_string(odata, data, sizeof(odata));
09863          ncontext = strchr(odata, '/');
09864          if (ncontext) {
09865             *ncontext = '\0';
09866             ncontext++;
09867             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
09868          } else {
09869             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
09870          }
09871          if (option_verbose > 2)
09872             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
09873       } else {
09874          ast_mutex_unlock(&dpcache_lock);
09875          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
09876          return -1;
09877       }
09878    }
09879    ast_mutex_unlock(&dpcache_lock);
09880    dial = pbx_findapp("Dial");
09881    if (dial) {
09882       return pbx_exec(chan, dial, req);
09883    } else {
09884       ast_log(LOG_WARNING, "No dial application registered\n");
09885    }
09886    return -1;
09887 }

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

09769 {
09770    struct iax2_dpcache *dp;
09771    int res = 0;
09772 #if 0
09773    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
09774 #endif
09775    if ((priority != 1) && (priority != 2))
09776       return 0;
09777    ast_mutex_lock(&dpcache_lock);
09778    dp = find_cache(chan, data, context, exten, priority);
09779    if (dp) {
09780       if (dp->flags & CACHE_FLAG_EXISTS)
09781          res= 1;
09782    }
09783    ast_mutex_unlock(&dpcache_lock);
09784    if (!dp) {
09785       ast_log(LOG_WARNING, "Unable to make DP cache\n");
09786    }
09787    return res;
09788 }

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

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

02494 {
02495    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02496    ast_mutex_lock(&iaxsl[callno]);
02497    if (iaxs[callno])
02498       iaxs[callno]->owner = newchan;
02499    else
02500       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02501    ast_mutex_unlock(&iaxsl[callno]);
02502    return 0;
02503 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

Definition at line 1330 of file chan_iax2.c.

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

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

01331 {
01332    if (fr->retrans > -1)
01333       ast_sched_del(sched, fr->retrans);
01334    iax_frame_free(fr);
01335 }

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

Definition at line 1064 of file chan_iax2.c.

References iax2_peer::addr, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_test_flag, destroy_peer(), IAX_TEMPONLY, and realtime_peer().

Referenced by find_callno().

01065 {
01066    struct iax2_peer *peer = NULL;
01067    int res = 0;
01068 
01069    if (lockpeer)
01070       AST_LIST_LOCK(&peers);
01071    AST_LIST_TRAVERSE(&peers, peer, entry) {
01072       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
01073           (peer->addr.sin_port == sin.sin_port)) {
01074          ast_copy_string(host, peer->name, len);
01075          res = 1;
01076          break;
01077       }
01078    }
01079    if (lockpeer)
01080       AST_LIST_UNLOCK(&peers);
01081    if (!peer) {
01082       peer = realtime_peer(NULL, &sin);
01083       if (peer) {
01084          ast_copy_string(host, peer->name, len);
01085          if (ast_test_flag(peer, IAX_TEMPONLY))
01086             destroy_peer(peer);
01087          res = 1;
01088       }
01089    }
01090 
01091    return res;
01092 }

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

Definition at line 3326 of file chan_iax2.c.

References iax2_peer::addr, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_test_flag, and IAX_TRUNK.

Referenced by check_access().

03327 {
03328    struct iax2_peer *peer = NULL;
03329    int res = 0;
03330 
03331    AST_LIST_LOCK(&peers);
03332    AST_LIST_TRAVERSE(&peers, peer, entry) {
03333       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03334           (peer->addr.sin_port == sin.sin_port)) {
03335          res = ast_test_flag(peer, IAX_TRUNK);
03336          break;
03337       }
03338    }
03339    AST_LIST_UNLOCK(&peers);
03340 
03341    return res;
03342 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 3011 of file chan_iax2.c.

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

03012 {
03013    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03014    int alreadygone;
03015    struct iax_ie_data ied;
03016    memset(&ied, 0, sizeof(ied));
03017    ast_mutex_lock(&iaxsl[callno]);
03018    if (callno && iaxs[callno]) {
03019       ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
03020       alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
03021       /* Send the hangup unless we have had a transmission error or are already gone */
03022       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
03023       if (!iaxs[callno]->error && !alreadygone) 
03024          send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
03025       /* Explicitly predestroy it */
03026       iax2_predestroy(callno);
03027       /* If we were already gone to begin with, destroy us now */
03028       if (alreadygone) {
03029          ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
03030          iax2_destroy(callno);
03031       }
03032    }
03033    ast_mutex_unlock(&iaxsl[callno]);
03034    if (option_verbose > 2) 
03035       ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
03036    return 0;
03037 }

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

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

03273 {
03274    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03275    struct chan_iax2_pvt *pvt;
03276    int res = 0;
03277 
03278    if (option_debug && iaxdebug)
03279       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03280 
03281    ast_mutex_lock(&iaxsl[callno]);
03282    pvt = iaxs[callno];
03283 
03284    switch (condition) {
03285    case AST_CONTROL_HOLD:
03286       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03287          ast_moh_start(c, data, pvt->mohinterpret);
03288          goto done;
03289       }
03290       break;
03291    case AST_CONTROL_UNHOLD:
03292       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03293          ast_moh_stop(c);
03294          goto done;
03295       }
03296    }
03297 
03298    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03299 
03300 done:
03301    ast_mutex_unlock(&iaxsl[callno]);
03302 
03303    return res;
03304 }

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

09815 {
09816    int res = 0;
09817    struct iax2_dpcache *dp;
09818 #if 0
09819    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
09820 #endif
09821    if ((priority != 1) && (priority != 2))
09822       return 0;
09823    ast_mutex_lock(&dpcache_lock);
09824    dp = find_cache(chan, data, context, exten, priority);
09825    if (dp) {
09826       if (dp->flags & CACHE_FLAG_MATCHMORE)
09827          res= 1;
09828    }
09829    ast_mutex_unlock(&dpcache_lock);
09830    if (!dp) {
09831       ast_log(LOG_WARNING, "Unable to make DP cache\n");
09832    }
09833    return res;
09834 }

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

Definition at line 4551 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04552 {
04553    if (argc < 3 || argc > 4)
04554       return RESULT_SHOWUSAGE;
04555    iaxdebug = 0;
04556    ast_cli(fd, "IAX2 Debugging Disabled\n");
04557    return RESULT_SUCCESS;
04558 }

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

Definition at line 4569 of file chan_iax2.c.

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

04570 {
04571    if (argc < 4 || argc > 5)
04572       return RESULT_SHOWUSAGE;
04573    jb_setoutput(jb_error_output, jb_warning_output, NULL);
04574    jb_debug_output("\n");
04575    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
04576    return RESULT_SUCCESS;
04577 }

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

Definition at line 4560 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04561 {
04562    if (argc < 4 || argc > 5)
04563       return RESULT_SHOWUSAGE;
04564    iaxtrunkdebug = 0;
04565    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
04566    return RESULT_SUCCESS;
04567 }

static int iax2_poke_noanswer ( void *  data  )  [static]

Definition at line 8166 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08167 {
08168    struct iax2_peer *peer = data;
08169    peer->pokeexpire = -1;
08170 #ifdef SCHED_MULTITHREADED
08171    if (schedule_action(__iax2_poke_noanswer, data))
08172 #endif      
08173       __iax2_poke_noanswer(data);
08174    return 0;
08175 }

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

Definition at line 8177 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, send_command(), and iax2_peer::sockfd.

Referenced by __iax2_poke_peer_s(), load_module(), reg_source_db(), reload_config(), and update_registry().

08178 {
08179    if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
08180       /* IF we have no IP, or this isn't to be monitored, return
08181         immediately after clearing things out */
08182       peer->lastms = 0;
08183       peer->historicms = 0;
08184       peer->pokeexpire = -1;
08185       peer->callno = 0;
08186       return 0;
08187    }
08188    if (peer->callno > 0) {
08189       ast_log(LOG_NOTICE, "Still have a callno...\n");
08190       ast_mutex_lock(&iaxsl[peer->callno]);
08191       iax2_destroy(peer->callno);
08192       ast_mutex_unlock(&iaxsl[peer->callno]);
08193    }
08194    if (heldcall)
08195       ast_mutex_unlock(&iaxsl[heldcall]);
08196    peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, 0, peer->sockfd);
08197    if (heldcall)
08198       ast_mutex_lock(&iaxsl[heldcall]);
08199    if (peer->callno < 1) {
08200       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
08201       return -1;
08202    }
08203 
08204    /* Speed up retransmission times for this qualify call */
08205    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
08206    iaxs[peer->callno]->peerpoke = peer;
08207    
08208    /* Remove any pending pokeexpire task */
08209    if (peer->pokeexpire > -1)
08210       ast_sched_del(sched, peer->pokeexpire);
08211 
08212    /* Queue up a new task to handle no reply */
08213    /* If the host is already unreachable then use the unreachable interval instead */
08214    if (peer->lastms < 0) {
08215       peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer);
08216    } else
08217       peer->pokeexpire = ast_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer);
08218 
08219    /* And send the poke */
08220    send_command(iaxs[peer->callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
08221 
08222    return 0;
08223 }

static int iax2_poke_peer_s ( void *  data  )  [static]

Definition at line 5964 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

05965 {
05966    struct iax2_peer *peer = data;
05967    peer->pokeexpire = -1;
05968 #ifdef SCHED_MULTITHREADED
05969    if (schedule_action(__iax2_poke_peer_s, data))
05970 #endif      
05971       __iax2_poke_peer_s(data);
05972    return 0;
05973 }

static int iax2_predestroy ( int  callno  )  [static]

Definition at line 1770 of file chan_iax2.c.

References ast_channel::_softhangup, ast_module_unref(), ast_queue_hangup(), ast_set_flag, AST_SOFTHANGUP_DEV, ast_test_flag, iax2_destroy_helper(), IAX_ALREADYGONE, iaxs, chan_iax2_pvt::owner, and ast_channel::tech_pvt.

Referenced by iax2_hangup(), and send_command_final().

01771 {
01772    struct ast_channel *c;
01773    struct chan_iax2_pvt *pvt = iaxs[callno];
01774 
01775    if (!pvt)
01776       return -1;
01777    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
01778       iax2_destroy_helper(pvt);
01779       ast_set_flag(pvt, IAX_ALREADYGONE); 
01780    }
01781    c = pvt->owner;
01782    if (c) {
01783       c->_softhangup |= AST_SOFTHANGUP_DEV;
01784       c->tech_pvt = NULL;
01785       ast_queue_hangup(c);
01786       pvt->owner = NULL;
01787       ast_module_unref(ast_module_info->self);
01788    }
01789    return 0;
01790 }

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

Definition at line 7857 of file chan_iax2.c.

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

Referenced by find_idle_thread(), and start_network_thread().

07858 {
07859    struct iax2_thread *thread = data;
07860    struct timeval tv;
07861    struct timespec ts;
07862    int put_into_idle = 0;
07863 
07864    ast_atomic_fetchadd_int(&iaxactivethreadcount,1);
07865    pthread_cleanup_push(iax2_process_thread_cleanup, data);
07866    for(;;) {
07867       /* Wait for something to signal us to be awake */
07868       ast_mutex_lock(&thread->lock);
07869 
07870       /* Flag that we're ready to accept signals */
07871       thread->ready_for_signal = 1;
07872       
07873       /* Put into idle list if applicable */
07874       if (put_into_idle)
07875          insert_idle_thread(thread);
07876 
07877       if (thread->type == IAX_TYPE_DYNAMIC) {
07878          struct iax2_thread *t = NULL;
07879          /* Wait to be signalled or time out */
07880          tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
07881          ts.tv_sec = tv.tv_sec;
07882          ts.tv_nsec = tv.tv_usec * 1000;
07883          if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
07884             /* This thread was never put back into the available dynamic
07885              * thread list, so just go away. */
07886             if (!put_into_idle) {
07887                ast_mutex_unlock(&thread->lock);
07888                break;
07889             }
07890             AST_LIST_LOCK(&dynamic_list);
07891             /* Account for the case where this thread is acquired *right* after a timeout */
07892             if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list)))
07893                iaxdynamicthreadcount--;
07894             AST_LIST_UNLOCK(&dynamic_list);
07895             if (t) {
07896                /* This dynamic thread timed out waiting for a task and was
07897                 * not acquired immediately after the timeout, 
07898                 * so it's time to go away. */
07899                ast_mutex_unlock(&thread->lock);
07900                break;
07901             }
07902             /* Someone grabbed our thread *right* after we timed out.
07903              * Wait for them to set us up with something to do and signal
07904              * us to continue. */
07905             tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
07906             ts.tv_sec = tv.tv_sec;
07907             ts.tv_nsec = tv.tv_usec * 1000;
07908             if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT)
07909             {
07910                ast_mutex_unlock(&thread->lock);
07911                break;
07912             }
07913          }
07914       } else {
07915          ast_cond_wait(&thread->cond, &thread->lock);
07916       }
07917 
07918       /* Go back into our respective list */
07919       put_into_idle = 1;
07920 
07921       ast_mutex_unlock(&thread->lock);
07922 
07923       if (thread->iostate == IAX_IOSTATE_IDLE)
07924          continue;
07925 
07926       /* Add ourselves to the active list now */
07927       AST_LIST_LOCK(&active_list);
07928       AST_LIST_INSERT_HEAD(&active_list, thread, list);
07929       AST_LIST_UNLOCK(&active_list);
07930 
07931       /* See what we need to do */
07932       switch(thread->iostate) {
07933       case IAX_IOSTATE_READY:
07934          thread->actions++;
07935          thread->iostate = IAX_IOSTATE_PROCESSING;
07936          socket_process(thread);
07937          handle_deferred_full_frames(thread);
07938          break;
07939       case IAX_IOSTATE_SCHEDREADY:
07940          thread->actions++;
07941          thread->iostate = IAX_IOSTATE_PROCESSING;
07942 #ifdef SCHED_MULTITHREADED
07943          thread->schedfunc(thread->scheddata);
07944 #endif      
07945          break;
07946       }
07947       time(&thread->checktime);
07948       thread->iostate = IAX_IOSTATE_IDLE;
07949 #ifdef DEBUG_SCHED_MULTITHREAD
07950       thread->curfunc[0]='\0';
07951 #endif      
07952 
07953       /* Now... remove ourselves from the active list, and return to the idle list */
07954       AST_LIST_LOCK(&active_list);
07955       AST_LIST_REMOVE(&active_list, thread, list);
07956       AST_LIST_UNLOCK(&active_list);
07957 
07958       /* Make sure another frame didn't sneak in there after we thought we were done. */
07959       handle_deferred_full_frames(thread);
07960    }
07961 
07962    /* I am exiting here on my own volition, I need to clean up my own data structures
07963    * Assume that I am no longer in any of the lists (idle, active, or dynamic)
07964    */
07965    pthread_cleanup_pop(1);
07966 
07967    return NULL;
07968 }

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 7848 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

07849 {
07850    struct iax2_thread *thread = data;
07851    ast_mutex_destroy(&thread->lock);
07852    ast_cond_destroy(&thread->cond);
07853    free(thread);
07854    ast_atomic_dec_and_test(&iaxactivethreadcount);
07855 }

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

Definition at line 8125 of file chan_iax2.c.

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

08126 {
08127    int force = 0;
08128    int res;
08129    if (argc < 4)
08130       return RESULT_SHOWUSAGE;
08131    if ((argc > 4)) {
08132       if (!strcasecmp(argv[4], "forced"))
08133          force = 1;
08134       else
08135          return RESULT_SHOWUSAGE;
08136    }
08137    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08138    if (res < 0)
08139       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08140    else if (res < 1)
08141       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08142    else
08143       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08144    return RESULT_SUCCESS;
08145 }

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

Definition at line 8027 of file chan_iax2.c.

References iax_prov_complete_template().

08028 {
08029    if (pos != 3)
08030       return NULL;
08031    return iax_prov_complete_template(line, word, pos, state);
08032 }

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

Definition at line 8034 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, LOG_DEBUG, NEW_FORCE, option_debug, iax_ie_data::pos, send_command(), and create_addr_info::sockfd.

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

08035 {
08036    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
08037       is found for template */
08038    struct iax_ie_data provdata;
08039    struct iax_ie_data ied;
08040    unsigned int sig;
08041    struct sockaddr_in sin;
08042    int callno;
08043    struct create_addr_info cai;
08044 
08045    memset(&cai, 0, sizeof(cai));
08046 
08047    if (option_debug)
08048       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
08049 
08050    if (iax_provision_build(&provdata, &sig, template, force)) {
08051       ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
08052       return 0;
08053    }
08054 
08055    if (end) {
08056       memcpy(&sin, end, sizeof(sin));
08057       cai.sockfd = sockfd;
08058    } else if (create_addr(dest, &sin, &cai))
08059       return -1;
08060 
08061    /* Build the rest of the message */
08062    memset(&ied, 0, sizeof(ied));
08063    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
08064 
08065    callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd);
08066    if (!callno)
08067       return -1;
08068 
08069    ast_mutex_lock(&iaxsl[callno]);
08070    if (iaxs[callno]) {
08071       /* Schedule autodestruct in case they don't ever give us anything back */
08072       if (iaxs[callno]->autoid > -1)
08073          ast_sched_del(sched, iaxs[callno]->autoid);
08074       iaxs[callno]->autoid = ast_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
08075       ast_set_flag(iaxs[callno], IAX_PROVISION);
08076       /* Got a call number now, so go ahead and send the provisioning information */
08077       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
08078    }
08079    ast_mutex_unlock(&iaxsl[callno]);
08080 
08081    return 1;
08082 }

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

Definition at line 1964 of file chan_iax2.c.

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

01965 {
01966    struct iax2_peer *peer;
01967 
01968    if (argc != 4)
01969         return RESULT_SHOWUSAGE;
01970    if (!strcmp(argv[3],"all")) {
01971       reload_config();
01972       ast_cli(fd, "OK cache is flushed.\n");
01973    } else if ((peer = find_peer(argv[3], 0))) {
01974       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
01975          ast_set_flag(peer, IAX_RTAUTOCLEAR);
01976          expire_registry((void *)peer->name);
01977          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
01978       } else {
01979          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
01980       }
01981    } else {
01982       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
01983    }
01984    
01985    return RESULT_SUCCESS;
01986 }

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

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

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 may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.

Definition at line 1347 of file chan_iax2.c.

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

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

01348 {
01349    /* Assumes lock for callno is already held... */
01350    for (;;) {
01351       if (iaxs[callno] && iaxs[callno]->owner) {
01352          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01353             /* Avoid deadlock by pausing and trying again */
01354             ast_mutex_unlock(&iaxsl[callno]);
01355             usleep(1);
01356             ast_mutex_lock(&iaxsl[callno]);
01357          } else {
01358             ast_queue_frame(iaxs[callno]->owner, f);
01359             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01360             break;
01361          }
01362       } else
01363          break;
01364    }
01365    return 0;
01366 }

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

Definition at line 3065 of file chan_iax2.c.

References ast_log(), ast_null_frame, and LOG_NOTICE.

03066 {
03067    ast_log(LOG_NOTICE, "I should never be called!\n");
03068    return &ast_null_frame;
03069 }

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

Definition at line 5499 of file chan_iax2.c.

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

Referenced by set_config().

05500 {
05501    struct iax2_registry *reg;
05502    char copy[256];
05503    char *username, *hostname, *secret;
05504    char *porta;
05505    char *stringp=NULL;
05506    
05507    if (!value)
05508       return -1;
05509    ast_copy_string(copy, value, sizeof(copy));
05510    stringp=copy;
05511    username = strsep(&stringp, "@");
05512    hostname = strsep(&stringp, "@");
05513    if (!hostname) {
05514       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
05515       return -1;
05516    }
05517    stringp=username;
05518    username = strsep(&stringp, ":");
05519    secret = strsep(&stringp, ":");
05520    stringp=hostname;
05521    hostname = strsep(&stringp, ":");
05522    porta = strsep(&stringp, ":");
05523    
05524    if (porta && !atoi(porta)) {
05525       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
05526       return -1;
05527    }
05528    if (!(reg = ast_calloc(1, sizeof(*reg))))
05529       return -1;
05530    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
05531       free(reg);
05532       return -1;
05533    }
05534    ast_copy_string(reg->username, username, sizeof(reg->username));
05535    if (secret)
05536       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
05537    reg->expire = -1;
05538    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
05539    reg->addr.sin_family = AF_INET;
05540    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
05541    AST_LIST_LOCK(&registrations);
05542    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
05543    AST_LIST_UNLOCK(&registrations);
05544    
05545    return 0;
05546 }

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

Definition at line 9542 of file chan_iax2.c.

References reload_config().

09543 {
09544    return reload_config();
09545 }

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

Definition at line 8235 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_info::capability, create_addr(), find_callno(), fmt, create_addr_info::found, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iaxsl, LOG_WARNING, make_trunk(), create_addr_info::maxtime, chan_iax2_pvt::maxtime, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), parsed_dial_string::peer, parsed_dial_string::port, ast_channel::readformat, create_addr_info::sockfd, and ast_channel::writeformat.

08236 {
08237    int callno;
08238    int res;
08239    int fmt, native;
08240    struct sockaddr_in sin;
08241    struct ast_channel *c;
08242    struct parsed_dial_string pds;
08243    struct create_addr_info cai;
08244    char *tmpstr;
08245 
08246    memset(&pds, 0, sizeof(pds));
08247    tmpstr = ast_strdupa(data);
08248    parse_dial_string(tmpstr, &pds);
08249 
08250    memset(&cai, 0, sizeof(cai));
08251    cai.capability = iax2_capability;
08252 
08253    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08254 
08255    if (!pds.peer) {
08256       ast_log(LOG_WARNING, "No peer given\n");
08257       return NULL;
08258    }
08259           
08260    
08261    /* Populate our address from the given */
08262    if (create_addr(pds.peer, &sin, &cai)) {
08263       *cause = AST_CAUSE_UNREGISTERED;
08264       return NULL;
08265    }
08266 
08267    if (pds.port)
08268       sin.sin_port = htons(atoi(pds.port));
08269 
08270    callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd);
08271    if (callno < 1) {
08272       ast_log(LOG_WARNING, "Unable to create call\n");
08273       *cause = AST_CAUSE_CONGESTION;
08274       return NULL;
08275    }
08276 
08277    ast_mutex_lock(&iaxsl[callno]);
08278 
08279    /* If this is a trunk, update it now */
08280    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
08281    if (ast_test_flag(&cai, IAX_TRUNK)) {
08282       int new_callno;
08283       if ((new_callno = make_trunk(callno, 1)) != -1)
08284          callno = new_callno;
08285    }
08286    iaxs[callno]->maxtime = cai.maxtime;
08287    if (cai.found)
08288       ast_string_field_set(iaxs[callno], host, pds.peer);
08289 
08290    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
08291 
08292    ast_mutex_unlock(&iaxsl[callno]);
08293 
08294    if (c) {
08295       /* Choose a format we can live with */
08296       if (c->nativeformats & format) 
08297          c->nativeformats &= format;
08298       else {
08299          native = c->nativeformats;
08300          fmt = format;
08301          res = ast_translator_best_choice(&fmt, &native);
08302          if (res < 0) {
08303             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
08304                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
08305             ast_hangup(c);
08306             return NULL;
08307          }
08308          c->nativeformats = native;
08309       }
08310       c->readformat = ast_best_codec(c->nativeformats);
08311       c->writeformat = c->readformat;
08312    }
08313 
08314    return c;
08315 }

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

References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_test_flag, calc_timestamp(), ast_iax2_mini_hdr::callno, ast_iax2_video_hdr::callno, chan_iax2_pvt::callno, iax_frame::callno, compress_subclass(), ast_iax2_full_hdr::csub, iax_frame::data, ast_frame::data, iax_frame::datalen, ast_frame::datalen, ast_iax2_full_hdr::dcallno, iax_frame::dcallno, DIRECTION_OUTGRESS, chan_iax2_pvt::ecx, encrypt_frame(), iax_frame::final, ast_frame::frametype, iax2_transmit(), iax2_trunk_queue(), IAX_COMMAND_ACK, IAX_ENCRYPTED, IAX_FLAG_FULL, iax_frame_new(), iax_frame_wrap(), IAX_KEYPOPULATED, iax_showframe(), IAX_TRUNK, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, chan_iax2_pvt::lastsent, 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, chan_iax2_pvt::semirand, send_packet(), ast_frame::subclass, chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, iax_frame::transfer, TRANSFER_MEDIAPASS, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, ast_iax2_mini_hdr::ts, ast_iax2_video_hdr::ts, ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_full_hdr::type, and ast_iax2_video_hdr::zeros.

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

03875 {
03876    /* Queue a packet for delivery on a given private structure.  Use "ts" for
03877       timestamp, or calculate if ts is 0.  Send immediately without retransmission
03878       or delayed, with retransmission */
03879    struct ast_iax2_full_hdr *fh;
03880    struct ast_iax2_mini_hdr *mh;
03881    struct ast_iax2_video_hdr *vh;
03882    struct {
03883       struct iax_frame fr2;
03884       unsigned char buffer[4096];
03885    } frb;
03886    struct iax_frame *fr;
03887    int res;
03888    int sendmini=0;
03889    unsigned int lastsent;
03890    unsigned int fts;
03891 
03892    frb.fr2.afdatalen = sizeof(frb.buffer);
03893 
03894    if (!pvt) {
03895       ast_log(LOG_WARNING, "No private structure for packet?\n");
03896       return -1;
03897    }
03898    
03899    lastsent = pvt->lastsent;
03900 
03901    /* Calculate actual timestamp */
03902    fts = calc_timestamp(pvt, ts, f);
03903 
03904    /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out
03905     * (the endpoint should detect the lost packet itself).  But, we want to do this here, so that we
03906     * increment the "predicted timestamps" for voice, if we're predecting */
03907    if(f->frametype == AST_FRAME_VOICE && f->datalen == 0)
03908        return 0;
03909 
03910 
03911    if ((ast_test_flag(pvt, IAX_TRUNK) || 
03912          (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) ||
03913          ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L))))
03914       /* High two bytes are the same on timestamp, or sending on a trunk */ &&
03915        (f->frametype == AST_FRAME_VOICE) 
03916       /* is a voice frame */ &&
03917       (f->subclass == pvt->svoiceformat) 
03918       /* is the same type */ ) {
03919          /* Force immediate rather than delayed transmission */
03920          now = 1;
03921          /* Mark that mini-style frame is appropriate */
03922          sendmini = 1;
03923    }
03924    if (((fts & 0xFFFF8000L) == (lastsent & 0xFFFF8000L)) && 
03925       (f->frametype == AST_FRAME_VIDEO) &&
03926       ((f->subclass & ~0x1) == pvt->svideoformat)) {
03927          now = 1;
03928          sendmini = 1;
03929    }
03930    /* Allocate an iax_frame */
03931    if (now) {
03932       fr = &frb.fr2;
03933    } else
03934       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));
03935    if (!fr) {
03936       ast_log(LOG_WARNING, "Out of memory\n");
03937       return -1;
03938    }
03939    /* Copy our prospective frame into our immediate or retransmitted wrapper */
03940    iax_frame_wrap(fr, f);
03941 
03942    fr->ts = fts;
03943    fr->callno = pvt->callno;
03944    fr->transfer = transfer;
03945    fr->final = final;
03946    if (!sendmini) {
03947       /* We need a full frame */
03948       if (seqno > -1)
03949          fr->oseqno = seqno;
03950       else
03951          fr->oseqno = pvt->oseqno++;
03952       fr->iseqno = pvt->iseqno;
03953       fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr));
03954       fh->scallno = htons(fr->callno | IAX_FLAG_FULL);
03955       fh->ts = htonl(fr->ts);
03956       fh->oseqno = fr->oseqno;
03957       if (transfer) {
03958          fh->iseqno = 0;
03959       } else
03960          fh->iseqno = fr->iseqno;
03961       /* Keep track of the last thing we've acknowledged */
03962       if (!transfer)
03963          pvt->aseqno = fr->iseqno;
03964       fh->type = fr->af.frametype & 0xFF;
03965       if (fr->af.frametype == AST_FRAME_VIDEO)
03966          fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6);
03967       else
03968          fh->csub = compress_subclass(fr->af.subclass);
03969       if (transfer) {
03970          fr->dcallno = pvt->transfercallno;
03971       } else
03972          fr->dcallno = pvt->peercallno;
03973       fh->dcallno = htons(fr->dcallno);
03974       fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr);
03975       fr->data = fh;
03976       fr->retries = 0;
03977       /* Retry after 2x the ping time has passed */
03978       fr->retrytime = pvt->pingtime * 2;
03979       if (fr->retrytime < MIN_RETRY_TIME)
03980          fr->retrytime = MIN_RETRY_TIME;
03981       if (fr->retrytime > MAX_RETRY_TIME)
03982          fr->retrytime = MAX_RETRY_TIME;
03983       /* Acks' don't get retried */
03984       if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK))
03985          fr->retries = -1;
03986       else if (f->frametype == AST_FRAME_VOICE)
03987          pvt->svoiceformat = f->subclass;
03988       else if (f->frametype == AST_FRAME_VIDEO)
03989          pvt->svideoformat = f->subclass & ~0x1;
03990       if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
03991          if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
03992             if (iaxdebug) {
03993                if (fr->transfer)
03994                   iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr));
03995                else
03996                   iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr));
03997             }
03998             encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen);
03999          } else
04000             ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04001       }
04002    
04003       if (now) {
04004          res = send_packet(fr);
04005       } else
04006          res = iax2_transmit(fr);
04007    } else {
04008       if (ast_test_flag(pvt, IAX_TRUNK)) {
04009          iax2_trunk_queue(pvt, fr);
04010          res = 0;
04011       } else if (fr->af.frametype == AST_FRAME_VIDEO) {
04012          /* Video frame have no sequence number */
04013          fr->oseqno = -1;
04014          fr->iseqno = -1;
04015          vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr));
04016          vh->zeros = 0;
04017          vh->callno = htons(0x8000 | fr->callno);
04018          vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0));
04019          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);
04020          fr->data = vh;
04021          fr->retries = -1;
04022          res = send_packet(fr);        
04023       } else {
04024          /* Mini-frames have no sequence number */
04025          fr->oseqno = -1;
04026          fr->iseqno = -1;
04027          /* Mini frame will do */
04028          mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr));
04029          mh->callno = htons(fr->callno);
04030          mh->ts = htons(fr->ts & 0xFFFF);
04031          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);
04032          fr->data = mh;
04033          fr->retries = -1;
04034          if (pvt->transferring == TRANSFER_MEDIAPASS)
04035             fr->transfer = 1;
04036          if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04037             if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04038                encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen);
04039             } else
04040                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04041          }
04042          res = send_packet(fr);
04043       }
04044    }
04045    return res;
04046 }

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

Definition at line 2488 of file chan_iax2.c.

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

02489 {
02490    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02491 }

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

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

02484 {
02485    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
02486 }

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

Definition at line 2476 of file chan_iax2.c.

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

02477 {
02478    
02479    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02480       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02481 }

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

Definition at line 3039 of file chan_iax2.c.

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

03040 {
03041    struct ast_option_header *h;
03042    int res;
03043 
03044    switch (option) {
03045    case AST_OPTION_TXGAIN:
03046    case AST_OPTION_RXGAIN:
03047       /* these two cannot be sent, because they require a result */
03048       errno = ENOSYS;
03049       return -1;
03050    default:
03051       if (!(h = ast_malloc(datalen + sizeof(*h))))
03052          return -1;
03053 
03054       h->flag = AST_OPTION_FLAG_REQUEST;
03055       h->option = htons(option);
03056       memcpy(h->data, data, datalen);
03057       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03058                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03059                  datalen + sizeof(*h), -1);
03060       free(h);
03061       return res;
03062    }
03063 }

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

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

02166 {
02167    struct iax2_dpcache *dp;
02168    char tmp[1024], *pc;
02169    int s;
02170    int x,y;
02171    struct timeval tv;
02172    gettimeofday(&tv, NULL);
02173    ast_mutex_lock(&dpcache_lock);
02174    dp = dpcache;
02175    ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02176    while(dp) {
02177       s = dp->expiry.tv_sec - tv.tv_sec;
02178       tmp[0] = '\0';
02179       if (dp->flags & CACHE_FLAG_EXISTS)
02180          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02181       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02182          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02183       if (dp->flags & CACHE_FLAG_CANEXIST)
02184          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02185       if (dp->flags & CACHE_FLAG_PENDING)
02186          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02187       if (dp->flags & CACHE_FLAG_TIMEOUT)
02188          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02189       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02190          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02191       if (dp->flags & CACHE_FLAG_MATCHMORE)
02192          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02193       if (dp->flags & CACHE_FLAG_UNKNOWN)
02194          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02195       /* Trim trailing pipe */
02196       if (!ast_strlen_zero(tmp))
02197          tmp[strlen(tmp) - 1] = '\0';
02198       else
02199          ast_copy_string(tmp, "(none)", sizeof(tmp));
02200       y=0;
02201       pc = strchr(dp->peercontext, '@');
02202       if (!pc)
02203          pc = dp->peercontext;
02204       else
02205          pc++;
02206       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
02207          if (dp->waiters[x] > -1)
02208             y++;
02209       if (s > 0)
02210          ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02211       else
02212          ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02213       dp = dp->next;
02214    }
02215    ast_mutex_unlock(&dpcache_lock);
02216    return RESULT_SUCCESS;
02217 }

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

Definition at line 4389 of file chan_iax2.c.

References iax2_registry::addr, ast_cli(), ast_getformatname(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, 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.

04390 {
04391 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04392 #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"
04393 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04394    int x;
04395    int numchans = 0;
04396 
04397    if (argc != 3)
04398       return RESULT_SHOWUSAGE;
04399    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04400    for (x=0;x<IAX_MAX_CALLS;x++) {
04401       ast_mutex_lock(&iaxsl[x]);
04402       if (iaxs[x]) {
04403          int lag, jitter, localdelay;
04404          jb_info jbinfo;
04405          
04406          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04407             jb_getinfo(iaxs[x]->jb, &jbinfo);
04408             jitter = jbinfo.jitter;
04409             localdelay = jbinfo.current - jbinfo.min;
04410          } else {
04411             jitter = -1;
04412             localdelay = 0;
04413          }
04414          lag = iaxs[x]->remote_rr.delay;
04415          ast_cli(fd, FORMAT,
04416             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04417             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04418             S_OR(iaxs[x]->username, "(None)"),
04419             iaxs[x]->callno, iaxs[x]->peercallno,
04420             iaxs[x]->oseqno, iaxs[x]->iseqno,
04421             lag,
04422             jitter,
04423             localdelay,
04424             ast_getformatname(iaxs[x]->voiceformat) );
04425          numchans++;
04426       }
04427       ast_mutex_unlock(&iaxsl[x]);
04428    }
04429    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04430    return RESULT_SUCCESS;
04431 #undef FORMAT
04432 #undef FORMAT2
04433 #undef FORMATB
04434 }

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

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

04301 {
04302 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04303 #if !defined(__FreeBSD__)
04304 #define FORMAT "%-15.15s  %-15d %-15d\n"
04305 #else /* __FreeBSD__ */
04306 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04307 #endif /* __FreeBSD__ */
04308    struct iax_firmware *cur;
04309    if ((argc != 3) && (argc != 4))
04310       return RESULT_SHOWUSAGE;
04311    ast_mutex_lock(&waresl.lock);
04312    
04313    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04314    for (cur = waresl.wares;cur;cur = cur->next) {
04315       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04316          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04317             (int)ntohl(cur->fwh->datalen));
04318    }
04319    ast_mutex_unlock(&waresl.lock);
04320    return RESULT_SUCCESS;
04321 #undef FORMAT
04322 #undef FORMAT2
04323 }

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

Definition at line 4512 of file chan_iax2.c.

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

04513 {
04514    int numchans = 0;
04515    if (argc != 3)
04516       return RESULT_SHOWUSAGE;
04517    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04518    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04519    numchans = ast_cli_netstats(NULL, fd, 1);
04520    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04521    return RESULT_SUCCESS;
04522 }

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

Show one peer in detail.

Definition at line 2057 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, destroy_peer(), iax2_peer::expire, find_peer(), iax2_peer::ha, IAX_DYNAMIC, IAX_TEMPONLY, peer_status(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax2_peer::prefs, RESULT_SHOWUSAGE, RESULT_SUCCESS, and iax2_peer::smoothing.

02058 {
02059    char status[30];
02060    char cbuf[256];
02061    struct iax2_peer *peer;
02062    char codec_buf[512];
02063    int x = 0, codec = 0, load_realtime = 0;
02064 
02065    if (argc < 4)
02066       return RESULT_SHOWUSAGE;
02067 
02068    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0;
02069 
02070    peer = find_peer(argv[3], load_realtime);
02071    if (peer) {
02072       ast_cli(fd,"\n\n");
02073       ast_cli(fd, "  * Name       : %s\n", peer->name);
02074       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
02075       ast_cli(fd, "  Context      : %s\n", peer->context);
02076       ast_cli(fd, "  Mailbox      : %s\n", peer->mailbox);
02077       ast_cli(fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No");
02078       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
02079       ast_cli(fd, "  Expire       : %d\n", peer->expire);
02080       ast_cli(fd, "  ACL          : %s\n", (peer->ha?"Yes":"No"));
02081       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));
02082       ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
02083       ast_cli(fd, "  Username     : %s\n", peer->username);
02084       ast_cli(fd, "  Codecs       : ");
02085       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
02086       ast_cli(fd, "%s\n", codec_buf);
02087 
02088       ast_cli(fd, "  Codec Order  : (");
02089       for(x = 0; x < 32 ; x++) {
02090          codec = ast_codec_pref_index(&peer->prefs,x);
02091          if(!codec)
02092             break;
02093          ast_cli(fd, "%s", ast_getformatname(codec));
02094          if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1))
02095             ast_cli(fd, "|");
02096       }
02097 
02098       if (!x)
02099          ast_cli(fd, "none");
02100       ast_cli(fd, ")\n");
02101 
02102       ast_cli(fd, "  Status       : ");
02103       peer_status(peer, status, sizeof(status));   
02104       ast_cli(fd, "%s\n",status);
02105       ast_cli(fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
02106       ast_cli(fd,"\n");
02107       if (ast_test_flag(peer, IAX_TEMPONLY))
02108          destroy_peer(peer);
02109    } else {
02110       ast_cli(fd,"Peer %s not found.\n", argv[3]);
02111       ast_cli(fd,"\n");
02112    }
02113 
02114    return RESULT_SUCCESS;
02115 }

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

Definition at line 4289 of file chan_iax2.c.

References __iax2_show_peers().

04290 {
04291    return __iax2_show_peers(0, fd, NULL, argc, argv);
04292 }

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

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

04362 {
04363 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04364 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04365    struct iax2_registry *reg = NULL;
04366 
04367    char host[80];
04368    char perceived[80];
04369    if (argc != 3)
04370       return RESULT_SHOWUSAGE;
04371    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04372    AST_LIST_LOCK(&registrations);
04373    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04374       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04375       if (reg->us.sin_addr.s_addr) 
04376          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04377       else
04378          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04379       ast_cli(fd, FORMAT, host, 
04380                (reg->dnsmgr) ? "Y" : "N", 
04381                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04382    }
04383    AST_LIST_UNLOCK(&registrations);
04384    return RESULT_SUCCESS;
04385 #undef FORMAT
04386 #undef FORMAT2
04387 }

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

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

02140 {
02141    struct iax_frame *cur;
02142    int cnt = 0, dead=0, final=0;
02143 
02144    if (argc != 3)
02145       return RESULT_SHOWUSAGE;
02146 
02147    AST_LIST_LOCK(&iaxq.queue);
02148    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02149       if (cur->retries < 0)
02150          dead++;
02151       if (cur->final)
02152          final++;
02153       cnt++;
02154    }
02155    AST_LIST_UNLOCK(&iaxq.queue);
02156 
02157    ast_cli(fd, "    IAX Statistics\n");
02158    ast_cli(fd, "---------------------\n");
02159    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02160    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02161    
02162    return RESULT_SUCCESS;
02163 }

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

Definition at line 4230 of file chan_iax2.c.

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

04231 {
04232    struct iax2_thread *thread = NULL;
04233    time_t t;
04234    int threadcount = 0, dynamiccount = 0;
04235    char type;
04236 
04237    if (argc != 3)
04238       return RESULT_SHOWUSAGE;
04239       
04240    ast_cli(fd, "IAX2 Thread Information\n");
04241    time(&t);
04242    ast_cli(fd, "Idle Threads:\n");
04243    AST_LIST_LOCK(&idle_list);
04244    AST_LIST_TRAVERSE(&idle_list, thread, list) {
04245 #ifdef DEBUG_SCHED_MULTITHREAD
04246       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04247          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04248 #else
04249       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
04250          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04251 #endif
04252       threadcount++;
04253    }
04254    AST_LIST_UNLOCK(&idle_list);
04255    ast_cli(fd, "Active Threads:\n");
04256    AST_LIST_LOCK(&active_list);
04257    AST_LIST_TRAVERSE(&active_list, thread, list) {
04258       if (thread->type == IAX_TYPE_DYNAMIC)
04259          type = 'D';
04260       else
04261          type = 'P';
04262 #ifdef DEBUG_SCHED_MULTITHREAD
04263       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04264          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04265 #else
04266       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04267          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04268 #endif
04269       threadcount++;
04270    }
04271    AST_LIST_UNLOCK(&active_list);
04272    ast_cli(fd, "Dynamic Threads:\n");
04273         AST_LIST_LOCK(&dynamic_list);
04274         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04275 #ifdef DEBUG_SCHED_MULTITHREAD
04276                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04277                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04278 #else
04279                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04280                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04281 #endif
04282       dynamiccount++;
04283         }
04284         AST_LIST_UNLOCK(&dynamic_list);
04285    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04286    return RESULT_SUCCESS;
04287 }

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

Definition at line 4048 of file chan_iax2.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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, and RESULT_SUCCESS.

04049 {
04050    regex_t regexbuf;
04051    int havepattern = 0;
04052 
04053 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
04054 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
04055 
04056    struct iax2_user *user = NULL;
04057    char auth[90];
04058    char *pstr = "";
04059 
04060    switch (argc) {
04061    case 5:
04062       if (!strcasecmp(argv[3], "like")) {
04063          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04064             return RESULT_SHOWUSAGE;
04065          havepattern = 1;
04066       } else
04067          return RESULT_SHOWUSAGE;
04068    case 3:
04069       break;
04070    default:
04071       return RESULT_SHOWUSAGE;
04072    }
04073 
04074    ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
04075    AST_LIST_LOCK(&users);
04076    AST_LIST_TRAVERSE(&users, user, entry) {
04077       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
04078          continue;
04079       
04080       if (!ast_strlen_zero(user->secret)) {
04081          ast_copy_string(auth,user->secret,sizeof(auth));
04082       } else if (!ast_strlen_zero(user->inkeys)) {
04083          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
04084       } else
04085          ast_copy_string(auth, "-no secret-", sizeof(auth));
04086       
04087       if(ast_test_flag(user,IAX_CODEC_NOCAP))
04088          pstr = "REQ Only";
04089       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
04090          pstr = "Disabled";
04091       else
04092          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
04093       
04094       ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
04095          user->contexts ? user->contexts->context : context,
04096          user->ha ? "Yes" : "No", pstr);
04097       
04098    }
04099    AST_LIST_UNLOCK(&users);
04100 
04101    if (havepattern)
04102       regfree(&regexbuf);
04103 
04104    return RESULT_SUCCESS;
04105 #undef FORMAT
04106 #undef FORMAT2
04107 }

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

Definition at line 3071 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03072 {
03073    int res;
03074    struct iax_ie_data ied0;
03075    struct iax_ie_data ied1;
03076    unsigned int transferid = (unsigned int)ast_random();
03077    memset(&ied0, 0, sizeof(ied0));
03078    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03079    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03080    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03081 
03082    memset(&ied1, 0, sizeof(ied1));
03083    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03084    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03085    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03086    
03087    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03088    if (res)
03089       return -1;
03090    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03091    if (res)
03092       return -1;
03093    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03094    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03095    return 0;
03096 }

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

Definition at line 1988 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01989 {
01990        if (argc != 4)
01991                return RESULT_SHOWUSAGE;
01992 
01993        test_losspct = atoi(argv[3]);
01994 
01995        return RESULT_SUCCESS;
01996 }

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

Definition at line 3306 of file chan_iax2.c.

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

03307 {
03308    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03309    struct iax_ie_data ied;
03310    char tmp[256], *context;
03311    ast_copy_string(tmp, dest, sizeof(tmp));
03312    context = strchr(tmp, '@');
03313    if (context) {
03314       *context = '\0';
03315       context++;
03316    }
03317    memset(&ied, 0, sizeof(ied));
03318    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03319    if (context)
03320       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03321    if (option_debug)
03322       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03323    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03324 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

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

02448 {
02449    /* Lock the queue and place this packet at the end */
02450    /* By setting this to 0, the network thread will send it for us, and
02451       queue retransmission if necessary */
02452    fr->sentyet = 0;
02453    AST_LIST_LOCK(&iaxq.queue);
02454    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02455    iaxq.count++;
02456    AST_LIST_UNLOCK(&iaxq.queue);
02457    /* Wake up the network and scheduler thread */
02458    if (netthreadid != AST_PTHREADT_NULL)
02459       pthread_kill(netthreadid, SIGURG);
02460    signal_condition(&sched_lock, &sched_cond);
02461    return 0;
02462 }

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

Definition at line 6018 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06019 {
06020    /* Drop when trunk is about 5 seconds idle */
06021    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06022       return 1;
06023    return 0;
06024 }

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

Definition at line 3649 of file chan_iax2.c.

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

03650 {
03651    struct ast_frame *f;
03652    struct iax2_trunk_peer *tpeer;
03653    void *tmp, *ptr;
03654    struct ast_iax2_meta_trunk_entry *met;
03655    struct ast_iax2_meta_trunk_mini *mtm;
03656 
03657    f = &fr->af;
03658    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
03659    if (tpeer) {
03660       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
03661          /* Need to reallocate space */
03662          if (tpeer->trunkdataalloc < MAX_TRUNKDATA) {
03663             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
03664                ast_mutex_unlock(&tpeer->lock);
03665                return -1;
03666             }
03667             
03668             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
03669             tpeer->trunkdata = tmp;
03670             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);
03671          } else {
03672             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));
03673             ast_mutex_unlock(&tpeer->lock);
03674             return -1;
03675          }
03676       }
03677 
03678       /* Append to meta frame */
03679       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
03680       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
03681          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
03682          mtm->len = htons(f->datalen);
03683          mtm->mini.callno = htons(pvt->callno);
03684          mtm->mini.ts = htons(0xffff & fr->ts);
03685          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
03686          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
03687       } else {
03688          met = (struct ast_iax2_meta_trunk_entry *)ptr;
03689          /* Store call number and length in meta header */
03690          met->callno = htons(pvt->callno);
03691          met->len = htons(f->datalen);
03692          /* Advance pointers/decrease length past trunk entry header */
03693          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
03694          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
03695       }
03696       /* Copy actual trunk data */
03697       memcpy(ptr, f->data, f->datalen);
03698       tpeer->trunkdatalen += f->datalen;
03699 
03700       tpeer->calls++;
03701       ast_mutex_unlock(&tpeer->lock);
03702    }
03703    return 0;
03704 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 5937 of file chan_iax2.c.

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

Referenced by socket_process().

05938 {
05939    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
05940 }

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

Definition at line 4579 of file chan_iax2.c.

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

04580 {
04581    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
04582    int res = -1;
04583    ast_mutex_lock(&iaxsl[callno]);
04584    if (iaxs[callno]) {
04585    /* If there's an outstanding error, return failure now */
04586       if (!iaxs[callno]->error) {
04587          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
04588             res = 0;
04589             /* Don't waste bandwidth sending null frames */
04590          else if (f->frametype == AST_FRAME_NULL)
04591             res = 0;
04592          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
04593             res = 0;
04594          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
04595             res = 0;
04596          else
04597          /* Simple, just queue for transmission */
04598             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
04599       } else {
04600          ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
04601       }
04602    }
04603    /* If it's already gone, just return */
04604    ast_mutex_unlock(&iaxsl[callno]);
04605    return res;
04606 }

static int iax_check_version ( char *  dev  )  [static]

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

01524 {
01525    int res = 0;
01526    struct iax_firmware *cur;
01527    if (!ast_strlen_zero(dev)) {
01528       ast_mutex_lock(&waresl.lock);
01529       cur = waresl.wares;
01530       while(cur) {
01531          if (!strcmp(dev, (char *)cur->fwh->devname)) {
01532             res = ntohs(cur->fwh->version);
01533             break;
01534          }
01535          cur = cur->next;
01536       }
01537       ast_mutex_unlock(&waresl.lock);
01538    }
01539    return res;
01540 }

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

Definition at line 749 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

00750 {
00751    if (iaxdebug)
00752       ast_verbose("%s", data);
00753 }

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

Definition at line 755 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

00756 {
00757    ast_log(LOG_WARNING, "%s", data);
00758 }

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

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

01543 {
01544    int res = -1;
01545    unsigned int bs = desc & 0xff;
01546    unsigned int start = (desc >> 8) & 0xffffff;
01547    unsigned int bytes;
01548    struct iax_firmware *cur;
01549    if (!ast_strlen_zero((char *)dev) && bs) {
01550       start *= bs;
01551       ast_mutex_lock(&waresl.lock);
01552       cur = waresl.wares;
01553       while(cur) {
01554          if (!strcmp((char *)dev, (char *)cur->fwh->devname)) {
01555             iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
01556             if (start < ntohl(cur->fwh->datalen)) {
01557                bytes = ntohl(cur->fwh->datalen) - start;
01558                if (bytes > bs)
01559                   bytes = bs;
01560                iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
01561             } else {
01562                bytes = 0;
01563                iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
01564             }
01565             if (bytes == bs)
01566                res = 0;
01567             else
01568                res = 1;
01569             break;
01570          }
01571          cur = cur->next;
01572       }
01573       ast_mutex_unlock(&waresl.lock);
01574    }
01575    return res;
01576 }

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

Definition at line 6200 of file chan_iax2.c.

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

Referenced by socket_process().

06201 {
06202    struct iax_dual *d;
06203    struct ast_channel *chan1m, *chan2m;
06204    pthread_t th;
06205    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
06206    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
06207    if (chan2m && chan1m) {
06208       /* Make formats okay */
06209       chan1m->readformat = chan1->readformat;
06210       chan1m->writeformat = chan1->writeformat;
06211       ast_channel_masquerade(chan1m, chan1);
06212       /* Setup the extensions and such */
06213       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
06214       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
06215       chan1m->priority = chan1->priority;
06216       
06217       /* We make a clone of the peer channel too, so we can play
06218          back the announcement */
06219       /* Make formats okay */
06220       chan2m->readformat = chan2->readformat;
06221       chan2m->writeformat = chan2->writeformat;
06222       ast_channel_masquerade(chan2m, chan2);
06223       /* Setup the extensions and such */
06224       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
06225       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
06226       chan2m->priority = chan2->priority;
06227       if (ast_do_masquerade(chan2m)) {
06228          ast_log(LOG_WARNING, "Masquerade failed :(\n");
06229          ast_hangup(chan2m);
06230          return -1;
06231       }
06232    } else {
06233       if (chan1m)
06234          ast_hangup(chan1m);
06235       if (chan2m)
06236          ast_hangup(chan2m);
06237       return -1;
06238    }
06239    if ((d = ast_calloc(1, sizeof(*d)))) {
06240       pthread_attr_t attr;
06241 
06242       pthread_attr_init(&attr);
06243       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06244 
06245       d->chan1 = chan1m;
06246       d->chan2 = chan2m;
06247       if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
06248          pthread_attr_destroy(&attr);
06249          return 0;
06250       }
06251       pthread_attr_destroy(&attr);
06252       free(d);
06253    }
06254    return -1;
06255 }

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

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

06181 {
06182    struct ast_channel *chan1, *chan2;
06183    struct iax_dual *d;
06184    struct ast_frame *f;
06185    int ext;
06186    int res;
06187    d = stuff;
06188    chan1 = d->chan1;
06189    chan2 = d->chan2;
06190    free(d);
06191    f = ast_read(chan1);
06192    if (f)
06193       ast_frfree(f);
06194    res = ast_park_call(chan1, chan2, 0, &ext);
06195    ast_hangup(chan2);
06196    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06197    return NULL;
06198 }

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

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

01133 {
01134    struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable);
01135    if (new) {
01136       size_t afdatalen = new->afdatalen;
01137       memcpy(new, fr, sizeof(*new));
01138       iax_frame_wrap(new, &fr->af);
01139       new->afdatalen = afdatalen;
01140       new->data = NULL;
01141       new->datalen = 0;
01142       new->direction = DIRECTION_INGRESS;
01143       new->retrans = -1;
01144    }
01145    return new;
01146 }

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

Definition at line 862 of file chan_iax2.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, and IAX_TYPE_DYNAMIC.

Referenced by iax2_process_thread().

00863 {
00864    if (thread->type == IAX_TYPE_DYNAMIC) {
00865       AST_LIST_LOCK(&dynamic_list);
00866       AST_LIST_INSERT_TAIL(&dynamic_list, thread, list);
00867       AST_LIST_UNLOCK(&dynamic_list);
00868    } else {
00869       AST_LIST_LOCK(&idle_list);
00870       AST_LIST_INSERT_TAIL(&idle_list, thread, list);
00871       AST_LIST_UNLOCK(&idle_list);
00872    }
00873 
00874    return;
00875 }

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

Definition at line 784 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 760 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

00761 {
00762    va_list args;
00763    char buf[1024];
00764 
00765    va_start(args, fmt);
00766    vsnprintf(buf, 1024, fmt, args);
00767    va_end(args);
00768 
00769    ast_log(LOG_ERROR, buf);
00770 }

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

Definition at line 772 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 10334 of file chan_iax2.c.

References __unload_module(), 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_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(), 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_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(), option_verbose, papp, pdescrip, psyn, reload_firmware(), sched_context_create(), set_config(), iax2_peer::sockfd, start_network_thread(), VERBOSE_PREFIX_2, and waresl.

10335 {
10336    char *config = "iax.conf";
10337    int res = 0;
10338    int x;
10339    struct iax2_registry *reg = NULL;
10340    struct iax2_peer *peer = NULL;
10341    
10342    ast_custom_function_register(&iaxpeer_function);
10343 
10344    iax_set_output(iax_debug_output);
10345    iax_set_error(iax_error_output);
10346    jb_setoutput(jb_error_output, jb_warning_output, NULL);
10347    
10348 #ifdef HAVE_ZAPTEL
10349 #ifdef ZT_TIMERACK
10350    timingfd = open("/dev/zap/timer", O_RDWR);
10351    if (timingfd < 0)
10352 #endif
10353       timingfd = open("/dev/zap/pseudo", O_RDWR);
10354    if (timingfd < 0) 
10355       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
10356 #endif      
10357 
10358    memset(iaxs, 0, sizeof(iaxs));
10359 
10360    for (x=0;x<IAX_MAX_CALLS;x++)
10361       ast_mutex_init(&iaxsl[x]);
10362    
10363    ast_cond_init(&sched_cond, NULL);
10364 
10365    io = io_context_create();
10366    sched = sched_context_create();
10367    
10368    if (!io || !sched) {
10369       ast_log(LOG_ERROR, "Out of memory\n");
10370       return -1;
10371    }
10372 
10373    netsock = ast_netsock_list_alloc();
10374    if (!netsock) {
10375       ast_log(LOG_ERROR, "Could not allocate netsock list.\n");
10376       return -1;
10377    }
10378    ast_netsock_init(netsock);
10379 
10380    outsock = ast_netsock_list_alloc();
10381    if (!outsock) {
10382       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
10383       return -1;
10384    }
10385    ast_netsock_init(outsock);
10386 
10387    ast_mutex_init(&waresl.lock);
10388 
10389    AST_LIST_HEAD_INIT(&iaxq.queue);
10390    
10391    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10392 
10393    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
10394    
10395    ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" );
10396    ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" );
10397 
10398    if(set_config(config, 0) == -1)
10399       return AST_MODULE_LOAD_DECLINE;
10400 
10401    if (ast_channel_register(&iax2_tech)) {
10402       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
10403       __unload_module();
10404       return -1;
10405    }
10406 
10407    if (ast_register_switch(&iax2_switch)) 
10408       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
10409 
10410    res = start_network_thread();
10411    if (!res) {
10412       if (option_verbose > 1) 
10413          ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n");
10414    } else {
10415       ast_log(LOG_ERROR, "Unable to start network thread\n");
10416       ast_netsock_release(netsock);
10417       ast_netsock_release(outsock);
10418    }
10419 
10420    AST_LIST_LOCK(&registrations);
10421    AST_LIST_TRAVERSE(&registrations, reg, entry)
10422       iax2_do_register(reg);
10423    AST_LIST_UNLOCK(&registrations); 
10424 
10425    AST_LIST_LOCK(&peers);
10426    AST_LIST_TRAVERSE(&peers, peer, entry) {
10427       if (peer->sockfd < 0)
10428          peer->sockfd = defaultsockfd;
10429       iax2_poke_peer(peer, 0);
10430    }
10431    AST_LIST_UNLOCK(&peers);
10432    reload_firmware();
10433    iax_provision_reload();
10434    return res;
10435 }

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

Definition at line 3098 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03099 {
03100    ast_mutex_lock(&iaxsl[callno0]);
03101    while (ast_mutex_trylock(&iaxsl[callno1])) {
03102       ast_mutex_unlock(&iaxsl[callno0]);
03103       usleep(10);
03104       ast_mutex_lock(&iaxsl[callno0]);
03105    }
03106 }

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

Definition at line 1200 of file chan_iax2.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), chan_iax2_pvt::callno, IAX_MAX_CALLS, iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, MIN_REUSE_TIME, chan_iax2_pvt::pingid, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().

Referenced by iax2_request(), and socket_process().

01201 {
01202    int x;
01203    int res= 0;
01204    struct timeval now;
01205    if (iaxs[callno]->oseqno) {
01206       ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n");
01207       return -1;
01208    }
01209    if (callno & TRUNK_CALL_START) {
01210       ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno);
01211       return -1;
01212    }
01213    gettimeofday(&now, NULL);
01214    for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) {
01215       ast_mutex_lock(&iaxsl[x]);
01216       if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01217          iaxs[x] = iaxs[callno];
01218          iaxs[x]->callno = x;
01219          iaxs[callno] = NULL;
01220          /* Update the two timers that should have been started */
01221          if (iaxs[x]->pingid > -1)
01222             ast_sched_del(sched, iaxs[x]->pingid);
01223          if (iaxs[x]->lagid > -1)
01224             ast_sched_del(sched, iaxs[x]->lagid);
01225          iaxs[x]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01226          iaxs[x]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01227          if (locked)
01228             ast_mutex_unlock(&iaxsl[callno]);
01229          res = x;
01230          if (!locked)
01231             ast_mutex_unlock(&iaxsl[x]);
01232          break;
01233       }
01234       ast_mutex_unlock(&iaxsl[x]);
01235    }
01236    if (x >= IAX_MAX_CALLS - 1) {
01237       ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n");
01238       return -1;
01239    }
01240    ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x);
01241    /* We move this call from a non-trunked to a trunked call */
01242    update_max_trunk();
01243    update_max_nontrunk();
01244    return res;
01245 }

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

Definition at line 4293 of file chan_iax2.c.

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

Referenced by load_module().

04294 {
04295    ast_cli_netstats(s, -1, 0);
04296    astman_append(s, "\r\n");
04297    return RESULT_SUCCESS;
04298 }

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

Definition at line 4326 of file chan_iax2.c.

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

Referenced by load_module().

04327 {
04328    char *a[] = { "iax2", "show", "users" };
04329    int ret;
04330    const char *id = astman_get_header(m,"ActionID");
04331 
04332    if (!ast_strlen_zero(id))
04333       astman_append(s, "ActionID: %s\r\n",id);
04334    ret = __iax2_show_peers(1, -1, s, 3, a );
04335    astman_append(s, "\r\n\r\n" );
04336    return ret;
04337 } /* /JDG */

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

Definition at line 1152 of file chan_iax2.c.

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

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

01153 {
01154    if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01155       (cur->addr.sin_port == sin->sin_port)) {
01156       /* This is the main host */
01157       if ((cur->peercallno == callno) ||
01158          ((dcallno == cur->callno) && !cur->peercallno)) {
01159          /* That's us.  Be sure we keep track of the peer call number */
01160          return 1;
01161       }
01162    }
01163    if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01164        (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {
01165       /* We're transferring */
01166       if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno))
01167          return 1;
01168    }
01169    return 0;
01170 }

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

Definition at line 3712 of file chan_iax2.c.

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

Referenced by decode_frame().

03713 {
03714 #if 0
03715    /* Debug with "fake encryption" */
03716    int x;
03717    if (len % 16)
03718       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
03719    for (x=0;x<len;x++)
03720       dst[x] = src[x] ^ 0xff;
03721 #else 
03722    unsigned char lastblock[16] = { 0 };
03723    int x;
03724    while(len > 0) {
03725       aes_decrypt(src, dst, dcx);
03726       for (x=0;x<16;x++)
03727          dst[x] ^= lastblock[x];
03728       memcpy(lastblock, src, sizeof(lastblock));
03729       dst += 16;
03730       src += 16;
03731       len -= 16;
03732    }
03733 #endif
03734 }

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

Definition at line 3736 of file chan_iax2.c.

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

Referenced by encrypt_frame().

03737 {
03738 #if 0
03739    /* Debug with "fake encryption" */
03740    int x;
03741    if (len % 16)
03742       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
03743    for (x=0;x<len;x++)
03744       dst[x] = src[x] ^ 0xff;
03745 #else
03746    unsigned char curblock[16] = { 0 };
03747    int x;
03748    while(len > 0) {
03749       for (x=0;x<16;x++)
03750          curblock[x] ^= src[x];
03751       aes_encrypt(curblock, dst, ecx);
03752       memcpy(curblock, dst, sizeof(curblock)); 
03753       dst += 16;
03754       src += 16;
03755       len -= 16;
03756    }
03757 #endif
03758 }

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

Definition at line 4884 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

04885 {
04886    /* Select exactly one common encryption if there are any */
04887    p->encmethods &= enc;
04888    if (p->encmethods) {
04889       if (p->encmethods & IAX_ENCRYPT_AES128)
04890          p->encmethods = IAX_ENCRYPT_AES128;
04891       else
04892          p->encmethods = 0;
04893    }
04894 }

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

Definition at line 8345 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(), iax_frame::callno, f, iax_frame_free(), iaxq, iaxs, iaxsl, LOG_DEBUG, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_packet(), iax_frame::sentyet, signal_condition(), and timing_read().

Referenced by start_network_thread().

08346 {
08347    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
08348       from the network, and queue them for delivery to the channels */
08349    int res, count, wakeup;
08350    struct iax_frame *f;
08351 
08352    if (timingfd > -1)
08353       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
08354    
08355    for(;;) {
08356       pthread_testcancel();
08357 
08358       /* Go through the queue, sending messages which have not yet been
08359          sent, and scheduling retransmissions if appropriate */
08360       AST_LIST_LOCK(&iaxq.queue);
08361       count = 0;
08362       wakeup = -1;
08363       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
08364          if (f->sentyet)
08365             continue;
08366          
08367          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
08368          if (ast_mutex_trylock(&iaxsl[f->callno])) {
08369             wakeup = 1;
08370             continue;
08371          }
08372 
08373          f->sentyet++;
08374 
08375          if (iaxs[f->callno]) {
08376             send_packet(f);
08377             count++;
08378          } 
08379 
08380          ast_mutex_unlock(&iaxsl[f->callno]);
08381 
08382          if (f->retries < 0) {
08383             /* This is not supposed to be retransmitted */
08384             AST_LIST_REMOVE_CURRENT(&iaxq.queue, list);
08385             iaxq.count--;
08386             /* Free the iax frame */
08387             iax_frame_free(f);
08388          } else {
08389             /* We need reliable delivery.  Schedule a retransmission */
08390             f->retries++;
08391             f->retrans = ast_sched_add(sched, f->retrytime, attempt_transmit, f);
08392             signal_condition(&sched_lock, &sched_cond);
08393          }
08394       }
08395       AST_LIST_TRAVERSE_SAFE_END
08396       AST_LIST_UNLOCK(&iaxq.queue);
08397 
08398       pthread_testcancel();
08399 
08400       if (count >= 20)
08401          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
08402 
08403       /* Now do the IO, and run scheduled tasks */
08404       res = ast_io_wait(io, wakeup);
08405       if (res >= 0) {
08406          if (res >= 20)
08407             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
08408       }
08409    }
08410    return NULL;
08411 }

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

Definition at line 1094 of file chan_iax2.c.

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

Referenced by find_callno().

01095 {
01096    struct chan_iax2_pvt *tmp;
01097    jb_conf jbconf;
01098 
01099    if (!(tmp = ast_calloc(1, sizeof(*tmp))))
01100       return NULL;
01101 
01102    if (ast_string_field_init(tmp, 32)) {
01103       free(tmp);
01104       tmp = NULL;
01105       return NULL;
01106    }
01107       
01108    tmp->prefs = prefs;
01109    tmp->callno = 0;
01110    tmp->peercallno = 0;
01111    tmp->transfercallno = 0;
01112    tmp->bridgecallno = 0;
01113    tmp->pingid = -1;
01114    tmp->lagid = -1;
01115    tmp->autoid = -1;
01116    tmp->authid = -1;
01117    tmp->initid = -1;
01118 
01119    ast_string_field_set(tmp,exten, "s");
01120    ast_string_field_set(tmp,host, host);
01121 
01122    tmp->jb = jb_new();
01123    tmp->jbid = -1;
01124    jbconf.max_jitterbuf = maxjitterbuffer;
01125    jbconf.resync_threshold = resyncthreshold;
01126    jbconf.max_contig_interp = maxjitterinterps;
01127    jb_setconf(tmp->jb,&jbconf);
01128 
01129    return tmp;
01130 }

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

02831 {
02832    if (ast_strlen_zero(data))
02833       return;
02834 
02835    pds->peer = strsep(&data, "/");
02836    pds->exten = strsep(&data, "/");
02837    pds->options = data;
02838 
02839    if (pds->exten) {
02840       data = pds->exten;
02841       pds->exten = strsep(&data, "@");
02842       pds->context = data;
02843    }
02844 
02845    if (strchr(pds->peer, '@')) {
02846       data = pds->peer;
02847       pds->username = strsep(&data, "@");
02848       pds->peer = data;
02849    }
02850 
02851    if (pds->username) {
02852       data = pds->username;
02853       pds->username = strsep(&data, ":");
02854       pds->password = data;
02855    }
02856 
02857    data = pds->peer;
02858    pds->peer = strsep(&data, ":");
02859    pds->port = data;
02860 
02861    /* check for a key name wrapped in [] in the secret position, if found,
02862       move it to the key field instead
02863    */
02864    if (pds->password && (pds->password[0] == '[')) {
02865       pds->key = ast_strip_quoted(pds->password, "[", "]");
02866       pds->password = NULL;
02867    }
02868 }

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 8495 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, LOG_DEBUG, LOG_WARNING, socket_read(), iax2_peer::sockfd, and strsep().

Referenced by build_peer().

08496 {
08497    struct sockaddr_in sin;
08498    int nonlocal = 1;
08499    int port = IAX_DEFAULT_PORTNO;
08500    int sockfd = defaultsockfd;
08501    char *tmp;
08502    char *addr;
08503    char *portstr;
08504 
08505    if (!(tmp = ast_strdupa(srcaddr)))
08506       return -1;
08507 
08508    addr = strsep(&tmp, ":");
08509    portstr = tmp;
08510 
08511    if (portstr) {
08512       port = atoi(portstr);
08513       if (port < 1)
08514          port = IAX_DEFAULT_PORTNO;
08515    }
08516    
08517    if (!ast_get_ip(&sin, addr)) {
08518       struct ast_netsock *sock;
08519       int res;
08520 
08521       sin.sin_port = 0;
08522       sin.sin_family = AF_INET;
08523       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
08524       if (res == 0) {
08525          /* ip address valid. */
08526          sin.sin_port = htons(port);
08527          if (!(sock = ast_netsock_find(netsock, &sin)))
08528             sock = ast_netsock_find(outsock, &sin);
08529          if (sock) {
08530             sockfd = ast_netsock_sockfd(sock);
08531             nonlocal = 0;
08532          } else {
08533             unsigned int orig_saddr = sin.sin_addr.s_addr;
08534             /* INADDR_ANY matches anyway! */
08535             sin.sin_addr.s_addr = INADDR_ANY;
08536             if (ast_netsock_find(netsock, &sin)) {
08537                sin.sin_addr.s_addr = orig_saddr;
08538                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
08539                if (sock) {
08540                   sockfd = ast_netsock_sockfd(sock);
08541                   ast_netsock_unref(sock);
08542                   nonlocal = 0;
08543                } else {
08544                   nonlocal = 2;
08545                }
08546             }
08547          }
08548       }
08549    }
08550       
08551    peer->sockfd = sockfd;
08552 
08553    if (nonlocal == 1) {
08554       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
08555          srcaddr, peer->name);
08556       return -1;
08557         } else if (nonlocal == 2) {
08558       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
08559          srcaddr, peer->name);
08560          return -1;
08561    } else {
08562       ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
08563       return 0;
08564    }
08565 }

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

peer_status: Report Peer status in character string

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

02035 {
02036    int res = 0;
02037    if (peer->maxms) {
02038       if (peer->lastms < 0) {
02039          ast_copy_string(status, "UNREACHABLE", statuslen);
02040       } else if (peer->lastms > peer->maxms) {
02041          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02042          res = 1;
02043       } else if (peer->lastms) {
02044          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02045          res = 1;
02046       } else {
02047          ast_copy_string(status, "UNKNOWN", statuslen);
02048       }
02049    } else { 
02050       ast_copy_string(status, "Unmonitored", statuslen);
02051       res = -1;
02052    }
02053    return res;
02054 }

static void prune_peers ( void   )  [static]

Definition at line 9118 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_test_flag, destroy_peer(), and IAX_DELME.

09118                              {
09119    /* Prune peers who still are supposed to be deleted */
09120    struct iax2_peer *peer = NULL;
09121 
09122    AST_LIST_LOCK(&peers);
09123    AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, entry) {
09124       if (ast_test_flag(peer, IAX_DELME)) {
09125          destroy_peer(peer);
09126          AST_LIST_REMOVE_CURRENT(&peers, entry);
09127       }
09128    }
09129    AST_LIST_TRAVERSE_SAFE_END
09130    AST_LIST_UNLOCK(&peers);
09131 }

static void prune_users ( void   )  [static]

Definition at line 9077 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_test_flag, destroy_user(), and IAX_DELME.

Referenced by reload_config().

09078 {
09079    struct iax2_user *user = NULL;
09080 
09081    AST_LIST_LOCK(&users);
09082    AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, entry) {
09083       if (ast_test_flag(user, IAX_DELME)) {
09084          destroy_user(user);
09085          AST_LIST_REMOVE_CURRENT(&users, entry);
09086       }
09087    }
09088    AST_LIST_TRAVERSE_SAFE_END
09089    AST_LIST_UNLOCK(&users);
09090 
09091 }

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

Definition at line 4864 of file chan_iax2.c.

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

Referenced by socket_process().

04865 {
04866    struct ast_iax2_full_hdr fh;
04867    fh.scallno = htons(src | IAX_FLAG_FULL);
04868    fh.dcallno = htons(dst);
04869    fh.ts = 0;
04870    fh.oseqno = 0;
04871    fh.iseqno = 0;
04872    fh.type = AST_FRAME_IAX;
04873    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
04874    if (iaxdebug)
04875        iax_showframe(NULL, &fh, 0, sin, 0);
04876 #if 0
04877    if (option_debug)
04878 #endif   
04879       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
04880          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
04881    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
04882 }

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

Definition at line 2505 of file chan_iax2.c.

References iax2_peer::addr, ast_copy_flags, ast_get_time_t(), ast_inet_ntoa(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_load_realtime(), ast_log(), ast_sched_add(), ast_sched_del(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_peer(), destroy_peer(), iax2_peer::expire, expire_registry(), IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_TEMPONLY, LOG_DEBUG, ast_variable::name, ast_variable::next, option_debug, realtime_update_peer(), reg_source_db(), ast_variable::value, and var.

02506 {
02507    struct ast_variable *var;
02508    struct ast_variable *tmp;
02509    struct iax2_peer *peer=NULL;
02510    time_t regseconds = 0, nowtime;
02511    int dynamic=0;
02512 
02513    if (peername)
02514       var = ast_load_realtime("iaxpeers", "name", peername, NULL);
02515    else {
02516       char porta[25];
02517       sprintf(porta, "%d", ntohs(sin->sin_port));
02518       var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02519       if (var) {
02520          /* We'll need the peer name in order to build the structure! */
02521          for (tmp = var; tmp; tmp = tmp->next) {
02522             if (!strcasecmp(tmp->name, "name"))
02523                peername = tmp->value;
02524          }
02525       }
02526    }
02527    if (!var)
02528       return NULL;
02529 
02530    peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
02531    
02532    if (!peer) {
02533       ast_variables_destroy(var);
02534       return NULL;
02535    }
02536 
02537    for (tmp = var; tmp; tmp = tmp->next) {
02538       /* Make sure it's not a user only... */
02539       if (!strcasecmp(tmp->name, "type")) {
02540          if (strcasecmp(tmp->value, "friend") &&
02541              strcasecmp(tmp->value, "peer")) {
02542             /* Whoops, we weren't supposed to exist! */
02543             destroy_peer(peer);
02544             peer = NULL;
02545             break;
02546          } 
02547       } else if (!strcasecmp(tmp->name, "regseconds")) {
02548          ast_get_time_t(tmp->value, &regseconds, 0, NULL);
02549       } else if (!strcasecmp(tmp->name, "ipaddr")) {
02550          inet_aton(tmp->value, &(peer->addr.sin_addr));
02551       } else if (!strcasecmp(tmp->name, "port")) {
02552          peer->addr.sin_port = htons(atoi(tmp->value));
02553       } else if (!strcasecmp(tmp->name, "host")) {
02554          if (!strcasecmp(tmp->value, "dynamic"))
02555             dynamic = 1;
02556       }
02557    }
02558 
02559    ast_variables_destroy(var);
02560 
02561    if (!peer)
02562       return NULL;
02563 
02564    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02565       ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
02566       if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
02567          if (peer->expire > -1)
02568             ast_sched_del(sched, peer->expire);
02569          peer->expire = ast_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, (void*)peer->name);
02570       }
02571       AST_LIST_LOCK(&peers);
02572       AST_LIST_INSERT_HEAD(&peers, peer, entry);
02573       AST_LIST_UNLOCK(&peers);
02574       if (ast_test_flag(peer, IAX_DYNAMIC))
02575          reg_source_db(peer);
02576    } else {
02577       ast_set_flag(peer, IAX_TEMPONLY);   
02578    }
02579 
02580    if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) {
02581       time(&nowtime);
02582       if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) {
02583          memset(&peer->addr, 0, sizeof(peer->addr));
02584          realtime_update_peer(peer->name, &peer->addr, 0);
02585          if (option_debug)
02586             ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n",
02587                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02588       }
02589       else {
02590          if (option_debug)
02591             ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n",
02592                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02593       }
02594    }
02595 
02596    return peer;
02597 }

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

Definition at line 2640 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

02641 {
02642    char port[10];
02643    char regseconds[20];
02644    
02645    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
02646    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
02647    ast_update_realtime("iaxpeers", "name", peername, 
02648       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
02649       "regseconds", regseconds, NULL);
02650 }

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

Definition at line 2599 of file chan_iax2.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_load_realtime(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_user(), IAX_RTCACHEFRIENDS, IAX_TEMPONLY, ast_variable::name, ast_variable::next, ast_variable::value, and var.

02600 {
02601    struct ast_variable *var;
02602    struct ast_variable *tmp;
02603    struct iax2_user *user=NULL;
02604 
02605    var = ast_load_realtime("iaxusers", "name", username, NULL);
02606    if (!var)
02607       return NULL;
02608 
02609    tmp = var;
02610    while(tmp) {
02611       /* Make sure it's not a peer only... */
02612       if (!strcasecmp(tmp->name, "type")) {
02613          if (strcasecmp(tmp->value, "friend") &&
02614              strcasecmp(tmp->value, "user")) {
02615             return NULL;
02616          } 
02617       }
02618       tmp = tmp->next;
02619    }
02620 
02621    user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
02622 
02623    ast_variables_destroy(var);
02624 
02625    if (!user)
02626       return NULL;
02627 
02628    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02629       ast_set_flag(user, IAX_RTCACHEFRIENDS);
02630       AST_LIST_LOCK(&users);
02631       AST_LIST_INSERT_HEAD(&users, user, entry);
02632       AST_LIST_UNLOCK(&users);
02633    } else {
02634       ast_set_flag(user, IAX_TEMPONLY);   
02635    }
02636 
02637    return user;
02638 }

static void reg_source_db ( struct iax2_peer p  )  [static]

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

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

05620 {
05621    char data[80];
05622    struct in_addr in;
05623    char *c, *d;
05624    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
05625       c = strchr(data, ':');
05626       if (c) {
05627          *c = '\0';
05628          c++;
05629          if (inet_aton(data, &in)) {
05630             d = strchr(c, ':');
05631             if (d) {
05632                *d = '\0';
05633                d++;
05634                if (option_verbose > 2)
05635                   ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 
05636                   ast_inet_ntoa(in), atoi(c), atoi(d));
05637                iax2_poke_peer(p, 0);
05638                p->expiry = atoi(d);
05639                memset(&p->addr, 0, sizeof(p->addr));
05640                p->addr.sin_family = AF_INET;
05641                p->addr.sin_addr = in;
05642                p->addr.sin_port = htons(atoi(c));
05643                if (p->expire > -1)
05644                   ast_sched_del(sched, p->expire);
05645                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05646                p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name);
05647                if (iax2_regfunk)
05648                   iax2_regfunk(p->name, 1);
05649                register_peer_exten(p, 1);
05650             }              
05651                
05652          }
05653       }
05654    }
05655 }

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

Definition at line 5548 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(), destroy_peer(), expire_register(), parse_register_contact(), reg_source_db(), sip_destroy_peer(), and update_registry().

05549 {
05550    char multi[256];
05551    char *stringp, *ext;
05552    if (!ast_strlen_zero(regcontext)) {
05553       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
05554       stringp = multi;
05555       while((ext = strsep(&stringp, "&"))) {
05556          if (onoff) {
05557             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
05558                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
05559                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
05560          } else
05561             ast_context_remove_extension(regcontext, ext, 1, NULL);
05562       }
05563    }
05564 }

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

Verify inbound registration.

Definition at line 5025 of file chan_iax2.c.

References iax2_peer::addr, ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_device_state_changed(), ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, destroy_peer(), chan_iax2_pvt::expiry, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, IAX_STATE_UNCHANGED, IAX_TEMPONLY, iaxs, inaddrcmp(), key(), LOG_NOTICE, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, iax_ies::refresh, iax_ies::rsa_result, secret, strsep(), and iax_ies::username.

Referenced by handle_request_register(), and socket_process().

05026 {
05027    char requeststr[256] = "";
05028    char peer[256] = "";
05029    char md5secret[256] = "";
05030    char rsasecret[256] = "";
05031    char secret[256] = "";
05032    struct iax2_peer *p;
05033    struct ast_key *key;
05034    char *keyn;
05035    int x;
05036    int expire = 0;
05037 
05038    ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED);
05039    /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
05040    if (ies->username)
05041       ast_copy_string(peer, ies->username, sizeof(peer));
05042    if (ies->password)
05043       ast_copy_string(secret, ies->password, sizeof(secret));
05044    if (ies->md5_result)
05045       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05046    if (ies->rsa_result)
05047       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05048    if (ies->refresh)
05049       expire = ies->refresh;
05050 
05051    if (ast_strlen_zero(peer)) {
05052       ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr));
05053       return -1;
05054    }
05055 
05056    /* SLD: first call to lookup peer during registration */
05057    p = find_peer(peer, 1);
05058 
05059    if (!p) {
05060       if (authdebug)
05061          ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05062       return -1;
05063    }
05064 
05065    if (!ast_test_flag(p, IAX_DYNAMIC)) {
05066       if (authdebug)
05067          ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05068       if (ast_test_flag(p, IAX_TEMPONLY))
05069          destroy_peer(p);
05070       return -1;
05071    }
05072 
05073    if (!ast_apply_ha(p->ha, sin)) {
05074       if (authdebug)
05075          ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05076       if (ast_test_flag(p, IAX_TEMPONLY))
05077          destroy_peer(p);
05078       return -1;
05079    }
05080    if (!inaddrcmp(&p->addr, sin))
05081       ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED);
05082    ast_string_field_set(iaxs[callno], secret, p->secret);
05083    ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
05084    /* Check secret against what we have on file */
05085    if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05086       if (!ast_strlen_zero(p->inkeys)) {
05087          char tmpkeys[256];
05088          char *stringp=NULL;
05089          ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys));
05090          stringp=tmpkeys;
05091          keyn = strsep(&stringp, ":");
05092          while(keyn) {
05093             key = ast_key_get(keyn, AST_KEY_PUBLIC);
05094             if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
05095                ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05096                break;
05097             } else if (!key) 
05098                ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
05099             keyn = strsep(&stringp, ":");
05100          }
05101          if (!keyn) {
05102             if (authdebug)
05103                ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
05104             if (ast_test_flag(p, IAX_TEMPONLY))
05105                destroy_peer(p);
05106             return -1;
05107          }
05108       } else {
05109          if (authdebug)
05110             ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
05111          if (ast_test_flag(p, IAX_TEMPONLY))
05112             destroy_peer(p);
05113          return -1;
05114       }
05115    } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05116       struct MD5Context md5;
05117       unsigned char digest[16];
05118       char *tmppw, *stringp;
05119       
05120       tmppw = ast_strdupa(p->secret);
05121       stringp = tmppw;
05122       while((tmppw = strsep(&stringp, ";"))) {
05123          MD5Init(&md5);
05124          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
05125          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05126          MD5Final(digest, &md5);
05127          for (x=0;x<16;x++)
05128             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05129          if (!strcasecmp(requeststr, md5secret)) 
05130             break;
05131       }
05132       if (tmppw) {
05133          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05134       } else {
05135          if (authdebug)
05136             ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret);
05137          if (ast_test_flag(p, IAX_TEMPONLY))
05138             destroy_peer(p);
05139          return -1;
05140       }
05141    } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
05142       /* They've provided a plain text password and we support that */
05143       if (strcmp(secret, p->secret)) {
05144          if (authdebug)
05145             ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05146          if (ast_test_flag(p, IAX_TEMPONLY))
05147             destroy_peer(p);
05148          return -1;
05149       } else
05150          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05151    } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) {
05152       if (authdebug)
05153          ast_log(LOG_NOTICE, "Inappropriate authentication received\n");
05154       if (ast_test_flag(p, IAX_TEMPONLY))
05155          destroy_peer(p);
05156       return -1;
05157    }
05158    ast_string_field_set(iaxs[callno], peer, peer);
05159    /* Choose lowest expiry number */
05160    if (expire && (expire < iaxs[callno]->expiry)) 
05161       iaxs[callno]->expiry = expire;
05162 
05163    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05164 
05165    if (ast_test_flag(p, IAX_TEMPONLY))
05166       destroy_peer(p);
05167    return 0;
05168    
05169 }

static int registry_authrequest ( const char *  name,
int  callno 
) [static]

Definition at line 5764 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_random(), ast_string_field_set, ast_test_flag, iax2_peer::authmethods, iax_ie_data::buf, destroy_peer(), 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, IAX_TEMPONLY, iaxs, LOG_WARNING, iax_ie_data::pos, and send_command().

Referenced by socket_process().

05765 {
05766    struct iax_ie_data ied;
05767    struct iax2_peer *p;
05768    char challenge[10];
05769    /* SLD: third call to find_peer in registration */
05770    p = find_peer(name, 1);
05771    if (p) {
05772       memset(&ied, 0, sizeof(ied));
05773       iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
05774       if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
05775          /* Build the challenge */
05776          snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
05777          ast_string_field_set(iaxs[callno], challenge, challenge);
05778          /* snprintf(iaxs[callno]->challenge, sizeof(iaxs[callno]->challenge), "%d", (int)ast_random()); */
05779          iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
05780       }
05781       iax_ie_append_str(&ied, IAX_IE_USERNAME, name);
05782       if (ast_test_flag(p, IAX_TEMPONLY))
05783          destroy_peer(p);
05784       return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
05785    } 
05786    ast_log(LOG_WARNING, "No such peer '%s'\n", name);
05787    return 0;
05788 }

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

Definition at line 5790 of file chan_iax2.c.

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

Referenced by socket_process().

05791 {
05792    struct iax2_registry *reg;
05793    /* Start pessimistic */
05794    struct iax_ie_data ied;
05795    char peer[256] = "";
05796    char challenge[256] = "";
05797    int res;
05798    int authmethods = 0;
05799    if (ies->authmethods)
05800       authmethods = ies->authmethods;
05801    if (ies->username)
05802       ast_copy_string(peer, ies->username, sizeof(peer));
05803    if (ies->challenge)
05804       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
05805    memset(&ied, 0, sizeof(ied));
05806    reg = iaxs[callno]->reg;
05807    if (reg) {
05808          if (inaddrcmp(&reg->addr, sin)) {
05809             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
05810             return -1;
05811          }
05812          if (ast_strlen_zero(reg->secret)) {
05813             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
05814             reg->regstate = REG_STATE_NOAUTH;
05815             return -1;
05816          }
05817          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
05818          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
05819          if (reg->secret[0] == '[') {
05820             char tmpkey[256];
05821             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
05822             tmpkey[strlen(tmpkey) - 1] = '\0';
05823             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL);
05824          } else
05825             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL);
05826          if (!res) {
05827             reg->regstate = REG_STATE_AUTHSENT;
05828             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
05829          } else
05830             return -1;
05831          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
05832    } else   
05833       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
05834    return -1;
05835 }

static char* regstate2str ( int  regstate  )  [static]

Definition at line 4339 of file chan_iax2.c.

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

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

04340 {
04341    switch(regstate) {
04342    case REG_STATE_UNREGISTERED:
04343       return "Unregistered";
04344    case REG_STATE_REGSENT:
04345       return "Request Sent";
04346    case REG_STATE_AUTHSENT:
04347       return "Auth. Sent";
04348    case REG_STATE_REGISTERED:
04349       return "Registered";
04350    case REG_STATE_REJECTED:
04351       return "Rejected";
04352    case REG_STATE_TIMEOUT:
04353       return "Timeout";
04354    case REG_STATE_NOAUTH:
04355       return "No Authentication";
04356    default:
04357       return "Unknown";
04358    }
04359 }

static int reload ( void   )  [static]

Definition at line 9547 of file chan_iax2.c.

References reload_config().

09548 {
09549    return reload_config();
09550 }

static int reload_config ( void   )  [static]

Definition at line 9507 of file chan_iax2.c.

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

09508 {
09509    char *config = "iax.conf";
09510    struct iax2_registry *reg;
09511    struct iax2_peer *peer;
09512 
09513    strcpy(accountcode, "");
09514    strcpy(language, "");
09515    strcpy(mohinterpret, "default");
09516    strcpy(mohsuggest, "");
09517    amaflags = 0;
09518    delayreject = 0;
09519    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09520    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09521    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09522    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09523    delete_users();
09524    set_config(config, 1);
09525    prune_peers();
09526    prune_users();
09527    AST_LIST_LOCK(&registrations);
09528    AST_LIST_TRAVERSE(&registrations, reg, entry)
09529       iax2_do_register(reg);
09530    AST_LIST_UNLOCK(&registrations);
09531    /* Qualify hosts, too */
09532    AST_LIST_LOCK(&peers);
09533    AST_LIST_TRAVERSE(&peers, peer, entry)
09534       iax2_poke_peer(peer, 0);
09535    AST_LIST_UNLOCK(&peers);
09536    reload_firmware();
09537    iax_provision_reload();
09538 
09539    return 0;
09540 }

static void reload_firmware ( void   )  [static]

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

01580 {
01581    struct iax_firmware *cur, *curl, *curp;
01582    DIR *fwd;
01583    struct dirent *de;
01584    char dir[256];
01585    char fn[256];
01586    /* Mark all as dead */
01587    ast_mutex_lock(&waresl.lock);
01588    cur = waresl.wares;
01589    while(cur) {
01590       cur->dead = 1;
01591       cur = cur->next;
01592    }
01593    /* Now that we've freed them, load the new ones */
01594    snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
01595    fwd = opendir(dir);
01596    if (fwd) {
01597       while((de = readdir(fwd))) {
01598          if (de->d_name[0] != '.') {
01599             snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name);
01600             if (!try_firmware(fn)) {
01601                if (option_verbose > 1)
01602                   ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name);
01603             }
01604          }
01605       }
01606       closedir(fwd);
01607    } else 
01608       ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
01609 
01610    /* Clean up leftovers */
01611    cur = waresl.wares;
01612    curp = NULL;
01613    while(cur) {
01614       curl = cur;
01615       cur = cur->next;
01616       if (curl->dead) {
01617          if (curp) {
01618             curp->next = cur;
01619          } else {
01620             waresl.wares = cur;
01621          }
01622          destroy_firmware(curl);
01623       } else {
01624          curp = cur;
01625       }
01626    }
01627    ast_mutex_unlock(&waresl.lock);
01628 }

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

Definition at line 6290 of file chan_iax2.c.

References iax_frame::callno, iax_rr::delay, iax_rr::dropped, iaxs, iax_rr::jitter, iax_rr::losscnt, iax_rr::losspct, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::remote_rr, iax_ies::rr_delay, iax_ies::rr_dropped, iax_ies::rr_jitter, iax_ies::rr_loss, iax_ies::rr_ooo, and iax_ies::rr_pkts.

Referenced by socket_process().

06291 {
06292    iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter;
06293    iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24;
06294    iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff;
06295    iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts;
06296    iaxs[fr->callno]->remote_rr.delay = ies->rr_delay;
06297    iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped;
06298    iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo;
06299 }

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

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

Referenced by start_network_thread().

08318 {
08319    int count;
08320    int res;
08321    struct timeval tv;
08322    struct timespec ts;
08323 
08324    for (;;) {
08325       res = ast_sched_wait(sched);
08326       if ((res > 1000) || (res < 0))
08327          res = 1000;
08328       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
08329       ts.tv_sec = tv.tv_sec;
08330       ts.tv_nsec = tv.tv_usec * 1000;
08331 
08332       pthread_testcancel();
08333       ast_mutex_lock(&sched_lock);
08334       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
08335       ast_mutex_unlock(&sched_lock);
08336       pthread_testcancel();
08337 
08338       count = ast_sched_runq(sched);
08339       if (count >= 20)
08340          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
08341    }
08342    return NULL;
08343 }

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 2363 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, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().

Referenced by socket_process().

02364 {
02365    int type, len;
02366    int ret;
02367    int needfree = 0;
02368 
02369    /* Attempt to recover wrapped timestamps */
02370    unwrap_timestamp(fr);
02371 
02372    /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
02373    if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore))
02374       fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000));
02375    else {
02376 #if 0
02377       ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n");
02378 #endif
02379       fr->af.delivery = ast_tv(0,0);
02380    }
02381 
02382    type = JB_TYPE_CONTROL;
02383    len = 0;
02384 
02385    if(fr->af.frametype == AST_FRAME_VOICE) {
02386       type = JB_TYPE_VOICE;
02387       len = ast_codec_get_samples(&fr->af) / 8;
02388    } else if(fr->af.frametype == AST_FRAME_CNG) {
02389       type = JB_TYPE_SILENCE;
02390    }
02391 
02392    if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
02393       if (tsout)
02394          *tsout = fr->ts;
02395       __do_deliver(fr);
02396       return -1;
02397    }
02398 
02399    /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
02400     * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
02401    if( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) &&
02402        iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner) &&
02403        (ast_bridged_channel(iaxs[fr->callno]->owner)->tech->properties & AST_CHAN_TP_WANTSJITTER)) {
02404       jb_frame frame;
02405 
02406       /* deliver any frames in the jb */
02407       while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
02408          __do_deliver(frame.data);
02409          /* __do_deliver() can make the call disappear */
02410          if (!iaxs[fr->callno])
02411             return -1;
02412       }
02413 
02414       jb_reset(iaxs[fr->callno]->jb);
02415 
02416       if (iaxs[fr->callno]->jbid > -1)
02417          ast_sched_del(sched, iaxs[fr->callno]->jbid);
02418 
02419       iaxs[fr->callno]->jbid = -1;
02420 
02421       /* deliver this frame now */
02422       if (tsout)
02423          *tsout = fr->ts;
02424       __do_deliver(fr);
02425       return -1;
02426    }
02427 
02428    /* insert into jitterbuffer */
02429    /* TODO: Perhaps we could act immediately if it's not droppable and late */
02430    ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
02431          calc_rxstamp(iaxs[fr->callno],fr->ts));
02432    if (ret == JB_DROP) {
02433       needfree++;
02434    } else if (ret == JB_SCHED) {
02435       update_jbsched(iaxs[fr->callno]);
02436    }
02437    if (tsout)
02438       *tsout = fr->ts;
02439    if (needfree) {
02440       /* Free our iax frame */
02441       iax2_frame_free(fr);
02442       return -1;
02443    }
02444    return 0;
02445 }

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

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

04623 {
04624    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
04625 }

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

Definition at line 4636 of file chan_iax2.c.

References __send_command(), chan_iax2_pvt::callno, and iax2_predestroy().

Referenced by __auth_reject(), __auto_hangup(), authenticate_request(), iax2_hangup(), socket_process(), and update_registry().

04637 {
04638    /* It is assumed that the callno has already been locked */
04639    iax2_predestroy(i->callno);
04640    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
04641 }

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

Definition at line 4643 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

04644 {
04645    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
04646 }

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

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

04628 {
04629    int res;
04630    ast_mutex_lock(&iaxsl[callno]);
04631    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
04632    ast_mutex_unlock(&iaxsl[callno]);
04633    return res;
04634 }

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

Definition at line 4648 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

04649 {
04650    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
04651 }

static int send_lagrq ( void *  data  )  [static]

Definition at line 1002 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

01003 {
01004 #ifdef SCHED_MULTITHREADED
01005    if (schedule_action(__send_lagrq, data))
01006 #endif      
01007       __send_lagrq(data);
01008    return 0;
01009 }

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 1701 of file chan_iax2.c.

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

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

01702 {
01703    int res;
01704    int callno = f->callno;
01705 
01706    /* Don't send if there was an error, but return error instead */
01707    if (!callno || !iaxs[callno] || iaxs[callno]->error)
01708        return -1;
01709    
01710    /* Called with iaxsl held */
01711    if (option_debug > 2 && iaxdebug)
01712       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));
01713    if (f->transfer) {
01714       if (iaxdebug)
01715          iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
01716       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer,
01717                sizeof(iaxs[callno]->transfer));
01718    } else {
01719       if (iaxdebug)
01720          iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
01721       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr,
01722                sizeof(iaxs[callno]->addr));
01723    }
01724    if (res < 0) {
01725       if (option_debug && iaxdebug)
01726          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
01727       handle_error();
01728    } else
01729       res = 0;
01730    return res;
01731 }

static int send_ping ( void *  data  )  [static]

Definition at line 967 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

00968 {
00969 #ifdef SCHED_MULTITHREADED
00970    if (schedule_action(__send_ping, data))
00971 #endif      
00972       __send_ping(data);
00973    return 0;
00974 }

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

Definition at line 5975 of file chan_iax2.c.

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

05976 {
05977    int res = 0;
05978    struct iax_frame *fr;
05979    struct ast_iax2_meta_hdr *meta;
05980    struct ast_iax2_meta_trunk_hdr *mth;
05981    int calls = 0;
05982    
05983    /* Point to frame */
05984    fr = (struct iax_frame *)tpeer->trunkdata;
05985    /* Point to meta data */
05986    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
05987    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
05988    if (tpeer->trunkdatalen) {
05989       /* We're actually sending a frame, so fill the meta trunk header and meta header */
05990       meta->zeros = 0;
05991       meta->metacmd = IAX_META_TRUNK;
05992       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
05993          meta->cmddata = IAX_META_TRUNK_MINI;
05994       else
05995          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
05996       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
05997       /* And the rest of the ast_iax2 header */
05998       fr->direction = DIRECTION_OUTGRESS;
05999       fr->retrans = -1;
06000       fr->transfer = 0;
06001       /* Any appropriate call will do */
06002       fr->data = fr->afdata;
06003       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
06004       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
06005       calls = tpeer->calls;
06006 #if 0
06007       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));
06008 #endif      
06009       /* Reset transmit trunk side data */
06010       tpeer->trunkdatalen = 0;
06011       tpeer->calls = 0;
06012    }
06013    if (res < 0)
06014       return res;
06015    return calls;
06016 }

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

Load configuration.

Definition at line 9150 of file chan_iax2.c.

References ast_category_browse(), ast_cdr_amaflags2int(), ast_clear_flag, ast_config_destroy(), ast_config_load(), ast_context_create(), ast_context_find(), AST_LIST_INSERT_HEAD, 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(), DEFAULT_MAXMS, format, gen, get_encrypt_methods(), 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, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, option_verbose, portno, iax2_user::prefs, reg_source_db(), secret, set_timing(), socket_read(), ast_variable::value, and VERBOSE_PREFIX_2.

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

09151 {
09152    struct ast_config *cfg, *ucfg;
09153    int capability=iax2_capability;
09154    struct ast_variable *v;
09155    char *cat;
09156    const char *utype;
09157    const char *tosval;
09158    int format;
09159    int portno = IAX_DEFAULT_PORTNO;
09160    int  x;
09161    struct iax2_user *user;
09162    struct iax2_peer *peer;
09163    struct ast_netsock *ns;
09164 #if 0
09165    static unsigned short int last_port=0;
09166 #endif
09167 
09168    cfg = ast_config_load(config_file);
09169    
09170    if (!cfg) {
09171       ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
09172       return -1;
09173    }
09174 
09175    /* Reset global codec prefs */   
09176    memset(&prefs, 0 , sizeof(struct ast_codec_pref));
09177    
09178    /* Reset Global Flags */
09179    memset(&globalflags, 0, sizeof(globalflags));
09180    ast_set_flag(&globalflags, IAX_RTUPDATE);
09181 
09182 #ifdef SO_NO_CHECK
09183    nochecksums = 0;
09184 #endif
09185 
09186    min_reg_expire = IAX_DEFAULT_REG_EXPIRE;
09187    max_reg_expire = IAX_DEFAULT_REG_EXPIRE;
09188 
09189    maxauthreq = 3;
09190 
09191    v = ast_variable_browse(cfg, "general");
09192 
09193    /* Seed initial tos value */
09194    tosval = ast_variable_retrieve(cfg, "general", "tos");
09195    if (tosval) {
09196       if (ast_str2tos(tosval, &tos))
09197          ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n");
09198    }
09199    while(v) {
09200       if (!strcasecmp(v->name, "bindport")){ 
09201          if (reload)
09202             ast_log(LOG_NOTICE, "Ignoring bindport on reload\n");
09203          else
09204             portno = atoi(v->value);
09205       } else if (!strcasecmp(v->name, "pingtime")) 
09206          ping_time = atoi(v->value);
09207       else if (!strcasecmp(v->name, "iaxthreadcount")) {
09208          if (reload) {
09209             if (atoi(v->value) != iaxthreadcount)
09210                ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n");
09211          } else {
09212             iaxthreadcount = atoi(v->value);
09213             if (iaxthreadcount < 1) {
09214                ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n");
09215                iaxthreadcount = 1;
09216             } else if (iaxthreadcount > 256) {
09217                ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n");
09218                iaxthreadcount = 256;
09219             }
09220          }
09221       } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) {
09222          if (reload) {
09223             AST_LIST_LOCK(&dynamic_list);
09224             iaxmaxthreadcount = atoi(v->value);
09225             AST_LIST_UNLOCK(&dynamic_list);
09226          } else {
09227             iaxmaxthreadcount = atoi(v->value);
09228             if (iaxmaxthreadcount < 0) {
09229                ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n");
09230                iaxmaxthreadcount = 0;
09231             } else if (iaxmaxthreadcount > 256) {
09232                ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n");
09233                iaxmaxthreadcount = 256;
09234             }
09235          }
09236       } else if (!strcasecmp(v->name, "nochecksums")) {
09237 #ifdef SO_NO_CHECK
09238          if (ast_true(v->value))
09239             nochecksums = 1;
09240          else
09241             nochecksums = 0;
09242 #else
09243          if (ast_true(v->value))
09244             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
09245 #endif
09246       }
09247       else if (!strcasecmp(v->name, "maxjitterbuffer")) 
09248          maxjitterbuffer = atoi(v->value);
09249       else if (!strcasecmp(v->name, "resyncthreshold")) 
09250          resyncthreshold = atoi(v->value);
09251       else if (!strcasecmp(v->name, "maxjitterinterps")) 
09252          maxjitterinterps = atoi(v->value);
09253       else if (!strcasecmp(v->name, "lagrqtime")) 
09254          lagrq_time = atoi(v->value);
09255       else if (!strcasecmp(v->name, "maxregexpire")) 
09256          max_reg_expire = atoi(v->value);
09257       else if (!strcasecmp(v->name, "minregexpire")) 
09258          min_reg_expire = atoi(v->value);
09259       else if (!strcasecmp(v->name, "bindaddr")) {
09260          if (reload) {
09261             ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n");
09262          } else {
09263             if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) {
09264                ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno);
09265             } else {
09266                if (option_verbose > 1) {
09267                   if (strchr(v->value, ':'))
09268                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value);
09269                   else
09270                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno);
09271                }
09272                if (defaultsockfd < 0) 
09273                   defaultsockfd = ast_netsock_sockfd(ns);
09274                ast_netsock_unref(ns);
09275             }
09276          }
09277       } else if (!strcasecmp(v->name, "authdebug"))
09278          authdebug = ast_true(v->value);
09279       else if (!strcasecmp(v->name, "encryption"))
09280          iax2_encryption = get_encrypt_methods(v->value);
09281       else if (!strcasecmp(v->name, "notransfer")) {
09282          ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09283          ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09284          ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER);   
09285       } else if (!strcasecmp(v->name, "transfer")) {
09286          if (!strcasecmp(v->value, "mediaonly")) {
09287             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 
09288          } else if (ast_true(v->value)) {
09289             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09290          } else 
09291             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09292       } else if (!strcasecmp(v->name, "codecpriority")) {
09293          if(!strcasecmp(v->value, "caller"))
09294             ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST);
09295          else if(!strcasecmp(v->value, "disabled"))
09296             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
09297          else if(!strcasecmp(v->value, "reqonly")) {
09298             ast_set_flag((&globalflags), IAX_CODEC_NOCAP);
09299             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
09300          }
09301       } else if (!strcasecmp(v->name, "jitterbuffer"))
09302          ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 
09303       else if (!strcasecmp(v->name, "forcejitterbuffer"))
09304          ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);  
09305       else if (!strcasecmp(v->name, "delayreject"))
09306          delayreject = ast_true(v->value);
09307       else if (!strcasecmp(v->name, "rtcachefriends"))
09308          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS);  
09309       else if (!strcasecmp(v->name, "rtignoreregexpire"))
09310          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE);  
09311       else if (!strcasecmp(v->name, "rtupdate"))
09312          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE);
09313       else if (!strcasecmp(v->name, "trunktimestamps"))
09314          ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS);
09315       else if (!strcasecmp(v->name, "rtautoclear")) {
09316          int i = atoi(v->value);
09317          if(i > 0)
09318             global_rtautoclear = i;
09319          else
09320             i = 0;
09321          ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR);   
09322       } else if (!strcasecmp(v->name, "trunkfreq")) {
09323          trunkfreq = atoi(v->value);
09324          if (trunkfreq < 10)
09325             trunkfreq = 10;
09326       } else if (!strcasecmp(v->name, "autokill")) {
09327          if (sscanf(v->value, "%d", &x) == 1) {
09328             if (x >= 0)
09329                autokill = x;
09330             else
09331                ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
09332          } else if (ast_true(v->value)) {
09333             autokill = DEFAULT_MAXMS;
09334          } else {
09335             autokill = 0;
09336          }
09337       } else if (!strcasecmp(v->name, "bandwidth")) {
09338          if (!strcasecmp(v->value, "low")) {
09339             capability = IAX_CAPABILITY_LOWBANDWIDTH;
09340          } else if (!strcasecmp(v->value, "medium")) {
09341             capability = IAX_CAPABILITY_MEDBANDWIDTH;
09342          } else if (!strcasecmp(v->value, "high")) {
09343             capability = IAX_CAPABILITY_FULLBANDWIDTH;
09344          } else
09345             ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n");
09346       } else if (!strcasecmp(v->name, "allow")) {
09347          ast_parse_allow_disallow(&prefs, &capability, v->value, 1);
09348       } else if (!strcasecmp(v->name, "disallow")) {
09349          ast_parse_allow_disallow(&prefs, &capability, v->value, 0);
09350       } else if (!strcasecmp(v->name, "register")) {
09351          iax2_register(v->value, v->lineno);
09352       } else if (!strcasecmp(v->name, "iaxcompat")) {
09353          iaxcompat = ast_true(v->value);
09354       } else if (!strcasecmp(v->name, "regcontext")) {
09355          ast_copy_string(regcontext, v->value, sizeof(regcontext));
09356          /* Create context if it doesn't exist already */
09357          if (!ast_context_find(regcontext))
09358             ast_context_create(NULL, regcontext, "IAX2");
09359       } else if (!strcasecmp(v->name, "tos")) {
09360          if (ast_str2tos(v->value, &tos))
09361             ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno);
09362       } else if (!strcasecmp(v->name, "accountcode")) {
09363          ast_copy_string(accountcode, v->value, sizeof(accountcode));
09364       } else if (!strcasecmp(v->name, "mohinterpret")) {
09365          ast_copy_string(mohinterpret, v->value, sizeof(user->mohinterpret));
09366       } else if (!strcasecmp(v->name, "mohsuggest")) {
09367          ast_copy_string(mohsuggest, v->value, sizeof(user->mohsuggest));
09368       } else if (!strcasecmp(v->name, "amaflags")) {
09369          format = ast_cdr_amaflags2int(v->value);
09370          if (format < 0) {
09371             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
09372          } else {
09373             amaflags = format;
09374          }
09375       } else if (!strcasecmp(v->name, "language")) {
09376          ast_copy_string(language, v->value, sizeof(language));
09377       } else if (!strcasecmp(v->name, "maxauthreq")) {
09378          maxauthreq = atoi(v->value);
09379          if (maxauthreq < 0)
09380             maxauthreq = 0;
09381       } else if (!strcasecmp(v->name, "adsi")) {
09382          adsi = ast_true(v->value);
09383       } /*else if (strcasecmp(v->name,"type")) */
09384       /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09385       v = v->next;
09386    }
09387    
09388    if (defaultsockfd < 0) {
09389       if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) {
09390          ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
09391       } else {
09392          if (option_verbose > 1)
09393             ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno);
09394          defaultsockfd = ast_netsock_sockfd(ns);
09395          ast_netsock_unref(ns);
09396       }
09397    }
09398    if (reload) {
09399       ast_netsock_release(outsock);
09400       outsock = ast_netsock_list_alloc();
09401       if (!outsock) {
09402          ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
09403          return -1;
09404       }
09405       ast_netsock_init(outsock);
09406    }
09407 
09408    if (min_reg_expire > max_reg_expire) {
09409       ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n",
09410          min_reg_expire, max_reg_expire, max_reg_expire);
09411       min_reg_expire = max_reg_expire;
09412    }
09413    iax2_capability = capability;
09414    
09415    ucfg = ast_config_load("users.conf");
09416    if (ucfg) {
09417       struct ast_variable *gen;
09418       int genhasiax;
09419       int genregisteriax;
09420       const char *hasiax, *registeriax;
09421       
09422       genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax"));
09423       genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax"));
09424       gen = ast_variable_browse(ucfg, "general");
09425       cat = ast_category_browse(ucfg, NULL);
09426       while (cat) {
09427          if (strcasecmp(cat, "general")) {
09428             hasiax = ast_variable_retrieve(ucfg, cat, "hasiax");
09429             registeriax = ast_variable_retrieve(ucfg, cat, "registeriax");
09430             if (ast_true(hasiax) || (!hasiax && genhasiax)) {
09431                /* Start with general parameters, then specific parameters, user and peer */
09432                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
09433                if (user) {
09434                   AST_LIST_LOCK(&users);
09435                   AST_LIST_INSERT_HEAD(&users, user, entry);
09436                   AST_LIST_UNLOCK(&users);
09437                }
09438                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
09439                if (peer) {
09440                   AST_LIST_LOCK(&peers);
09441                   AST_LIST_INSERT_HEAD(&peers, peer, entry);
09442                   AST_LIST_UNLOCK(&peers);
09443                   if (ast_test_flag(peer, IAX_DYNAMIC))
09444                      reg_source_db(peer);
09445                }
09446             }
09447             if (ast_true(registeriax) || (!registeriax && genregisteriax)) {
09448                char tmp[256];
09449                const char *host = ast_variable_retrieve(ucfg, cat, "host");
09450                const char *username = ast_variable_retrieve(ucfg, cat, "username");
09451                const char *secret = ast_variable_retrieve(ucfg, cat, "secret");
09452                if (!host)
09453                   host = ast_variable_retrieve(ucfg, "general", "host");
09454                if (!username)
09455                   username = ast_variable_retrieve(ucfg, "general", "username");
09456                if (!secret)
09457                   secret = ast_variable_retrieve(ucfg, "general", "secret");
09458                if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
09459                   if (!ast_strlen_zero(secret))
09460                      snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host);
09461                   else
09462                      snprintf(tmp, sizeof(tmp), "%s@%s", username, host);
09463                   iax2_register(tmp, 0);
09464                }
09465             }
09466          }
09467          cat = ast_category_browse(ucfg, cat);
09468       }
09469       ast_config_destroy(ucfg);
09470    }
09471    
09472    cat = ast_category_browse(cfg, NULL);
09473    while(cat) {
09474       if (strcasecmp(cat, "general")) {
09475          utype = ast_variable_retrieve(cfg, cat, "type");
09476          if (utype) {
09477             if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
09478                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
09479                if (user) {
09480                   AST_LIST_LOCK(&users);
09481                   AST_LIST_INSERT_HEAD(&users, user, entry);
09482                   AST_LIST_UNLOCK(&users);
09483                }
09484             }
09485             if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
09486                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
09487                if (peer) {
09488                   AST_LIST_LOCK(&peers);
09489                   AST_LIST_INSERT_HEAD(&peers, peer, entry);
09490                   AST_LIST_UNLOCK(&peers);
09491                   if (ast_test_flag(peer, IAX_DYNAMIC))
09492                      reg_source_db(peer);
09493                }
09494             } else if (strcasecmp(utype, "user")) {
09495                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file);
09496             }
09497          } else
09498             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
09499       }
09500       cat = ast_category_browse(cfg, cat);
09501    }
09502    ast_config_destroy(cfg);
09503    set_timing();
09504    return capability;
09505 }

static void set_timing ( void   )  [static]

Definition at line 9133 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09134 {
09135 #ifdef HAVE_ZAPTEL
09136    int bs = trunkfreq * 8;
09137    if (timingfd > -1) {
09138       if (
09139 #ifdef ZT_TIMERACK
09140          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09141 #endif         
09142          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09143          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09144    }
09145 #endif
09146 }

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

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

00743 {
00744    ast_mutex_lock(lock);
00745    ast_cond_signal(cond);
00746    ast_mutex_unlock(lock);
00747 }

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 6442 of file chan_iax2.c.

References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, ast_async_goto(), ast_best_codec(), ast_bridged_channel(), AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_clear_flag, ast_codec_choose(), ast_codec_get_samples(), ast_codec_pref_convert(), ast_codec_pref_index(), ast_codec_pref_string(), AST_CONTROL_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_queue_control(), ast_queue_control_data(), 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(), chan_iax2_pvt::authmethods, iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, calc_timestamp(), iax_ies::called_number, iax2_peer::callno, chan_iax2_pvt::callno, ast_iax2_meta_trunk_entry::callno, ast_iax2_mini_hdr::callno, iax_frame::callno, chan_iax2_pvt::capability, iax_ies::cause, iax_ies::causecode, check_access(), check_provisioning(), chan_iax2_pvt::chosenformat, cid_num, ast_iax2_meta_hdr::cmddata, iax_ies::codec_prefs, complete_dpreply(), complete_transfer(), construct_rr(), ast_iax2_full_hdr::csub, ast_frame::data, ast_iax2_meta_trunk_hdr::data, ast_iax2_meta_hdr::data, ast_frame::datalen, ast_iax2_full_hdr::dcallno, decrypt_frame(), iax_ies::devicetype, dp_lookup(), chan_iax2_pvt::encmethods, iax_ies::encmethods, chan_iax2_pvt::error, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, iax_frame::final, find_callno(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, iax_ies::format, format, chan_iax2_pvt::frames_received, ast_frame::frametype, iax_ies::fwdesc, ast_channel::hangupcause, iax2_peer::historicms, iax2_ack_registry(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_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, iax_ies::iax_unknown, iaxfrdup2(), iaxq, iaxs, iaxsl, inaddrcmp(), chan_iax2_pvt::initid, chan_iax2_pvt::iseqno, ast_iax2_full_hdr::iseqno, iax_frame::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_frame::len, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, len, ast_channel::lock, iax2_trunk_peer::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_trunk(), ast_frame::mallocd, manager_event(), iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, iax_ies::musiconhold, ast_channel::nativeformats, NEW_ALLOW, NEW_PREVENT, ast_frame::offset, option_debug, option_verbose, chan_iax2_pvt::oseqno, iax_frame::oseqno, ast_iax2_full_hdr::oseqno, iax_frame::outoforder, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), iax2_dpcache::peer, chan_iax2_pvt::peercallno, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, chan_iax2_pvt::prefs, iax_ies::provver, iax_ies::provverpres, raw_hangup(), ast_channel::readformat, iax_ies::refresh, REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), iax_frame::retries, chan_iax2_pvt::rprefs, chan_iax2_pvt::rseqno, iax2_trunk_peer::rxtrunktime, S_OR, ast_frame::samples, save_rr(), schedule_delivery(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax_ies::serviceident, iax2_peer::smoothing, spawn_dp_lookup(), ast_frame::src, chan_iax2_pvt::state, stop_stuff(), ast_frame::subclass, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MEDIAPASS, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, iax2_trunk_peer::trunkact, try_transfer(), ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_mini_hdr::ts, ast_iax2_meta_trunk_hdr::ts, ast_iax2_full_hdr::type, uncompress_subclass(), update_registry(), iax_ies::username, VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, chan_iax2_pvt::videoformat, vnak_retransmit(), chan_iax2_pvt::voiceformat, and ast_iax2_meta_hdr::zeros.

Referenced by handle_deferred_full_frames(), and iax2_process_thread().

06443 {
06444    struct sockaddr_in sin;
06445    int res;
06446    int updatehistory=1;
06447    int new = NEW_PREVENT;
06448    void *ptr;
06449    int dcallno = 0;
06450    struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf;
06451    struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf;
06452    struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf;
06453    struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf;
06454    struct ast_iax2_meta_trunk_hdr *mth;
06455    struct ast_iax2_meta_trunk_entry *mte;
06456    struct ast_iax2_meta_trunk_mini *mtm;
06457    struct iax_frame *fr;
06458    struct iax_frame *cur;
06459    struct ast_frame f = { 0, };
06460    struct ast_channel *c;
06461    struct iax2_dpcache *dp;
06462    struct iax2_peer *peer;
06463    struct iax2_trunk_peer *tpeer;
06464    struct timeval rxtrunktime;
06465    struct iax_ies ies;
06466    struct iax_ie_data ied0, ied1;
06467    int format;
06468    int fd;
06469    int exists;
06470    int minivid = 0;
06471    unsigned int ts;
06472    char empty[32]="";      /* Safety measure */
06473    struct iax_frame *duped_fr;
06474    char host_pref_buf[128];
06475    char caller_pref_buf[128];
06476    struct ast_codec_pref pref;
06477    char *using_prefs = "mine";
06478 
06479    /* allocate an iax_frame with 4096 bytes of data buffer */
06480    fr = alloca(sizeof(*fr) + 4096);
06481    fr->callno = 0;
06482    fr->afdatalen = 4096; /* From alloca() above */
06483 
06484    /* Copy frequently used parameters to the stack */
06485    res = thread->buf_len;
06486    fd = thread->iofd;
06487    memcpy(&sin, &thread->iosin, sizeof(sin));
06488 
06489    if (res < sizeof(*mh)) {
06490       ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*mh));
06491       return 1;
06492    }
06493    if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) {
06494       if (res < sizeof(*vh)) {
06495          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));
06496          return 1;
06497       }
06498 
06499       /* This is a video frame, get call number */
06500       fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, 1, fd);
06501       minivid = 1;
06502    } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) {
06503       unsigned char metatype;
06504 
06505       if (res < sizeof(*meta)) {
06506          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));
06507          return 1;
06508       }
06509 
06510       /* This is a meta header */
06511       switch(meta->metacmd) {
06512       case IAX_META_TRUNK:
06513          if (res < (sizeof(*meta) + sizeof(*mth))) {
06514             ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %zd min)\n", res,
06515                sizeof(*meta) + sizeof(*mth));
06516             return 1;
06517          }
06518          mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data);
06519          ts = ntohl(mth->ts);
06520          metatype = meta->cmddata;
06521          res -= (sizeof(*meta) + sizeof(*mth));
06522          ptr = mth->data;
06523          tpeer = find_tpeer(&sin, fd);
06524          if (!tpeer) {
06525             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));
06526             return 1;
06527          }
06528          tpeer->trunkact = ast_tvnow();
06529          if (!ts || ast_tvzero(tpeer->rxtrunktime))
06530             tpeer->rxtrunktime = tpeer->trunkact;
06531          rxtrunktime = tpeer->rxtrunktime;
06532          ast_mutex_unlock(&tpeer->lock);
06533          while(res >= sizeof(*mte)) {
06534             /* Process channels */
06535             unsigned short callno, trunked_ts, len;
06536 
06537             if (metatype == IAX_META_TRUNK_MINI) {
06538                mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
06539                ptr += sizeof(*mtm);
06540                res -= sizeof(*mtm);
06541                len = ntohs(mtm->len);
06542                callno = ntohs(mtm->mini.callno);
06543                trunked_ts = ntohs(mtm->mini.ts);
06544             } else if (metatype == IAX_META_TRUNK_SUPERMINI) {
06545                mte = (struct ast_iax2_meta_trunk_entry *)ptr;
06546                ptr += sizeof(*mte);
06547                res -= sizeof(*mte);
06548                len = ntohs(mte->len);
06549                callno = ntohs(mte->callno);
06550                trunked_ts = 0;
06551             } else {
06552                ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
06553                break;
06554             }
06555             /* Stop if we don't have enough data */
06556             if (len > res)
06557                break;
06558             fr->callno = find_callno(callno & ~IAX_FLAG_FULL, 0, &sin, NEW_PREVENT, 1, fd);
06559             if (fr->callno) {
06560                ast_mutex_lock(&iaxsl[fr->callno]);
06561                /* If it's a valid call, deliver the contents.  If not, we
06562                   drop it, since we don't have a scallno to use for an INVAL */
06563                /* Process as a mini frame */
06564                memset(&f, 0, sizeof(f));
06565                f.frametype = AST_FRAME_VOICE;
06566                if (iaxs[fr->callno]) {
06567                   if (iaxs[fr->callno]->voiceformat > 0) {
06568                      f.subclass = iaxs[fr->callno]->voiceformat;
06569                      f.datalen = len;
06570                      if (f.datalen >= 0) {
06571                         if (f.datalen)
06572                            f.data = ptr;
06573                         if(trunked_ts) {
06574                            fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff);
06575                         } else
06576                            fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts);
06577                         /* Don't pass any packets until we're started */
06578                         if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
06579                            /* Common things */
06580                            f.src = "IAX2";
06581                            if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 
06582                               f.samples = ast_codec_get_samples(&f);
06583                            iax_frame_wrap(fr, &f);
06584                            duped_fr = iaxfrdup2(fr);
06585                            if (duped_fr) {
06586                               schedule_delivery(duped_fr, updatehistory, 1, &fr->ts);
06587                            }
06588                            /* It is possible for the pvt structure to go away after we call schedule_delivery */
06589                            if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) {
06590                               iaxs[fr->callno]->last = fr->ts;
06591 #if 1
06592                               if (option_debug && iaxdebug)
06593                                  ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts);
06594 #endif
06595                            }
06596                         }
06597                      } else {
06598                         ast_log(LOG_WARNING, "Datalen < 0?\n");
06599                      }
06600                   } else {
06601                      ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n ");
06602                      iax2_vnak(fr->callno);
06603                   }
06604                }
06605                ast_mutex_unlock(&iaxsl[fr->callno]);
06606             }
06607             ptr += len;
06608             res -= len;
06609          }
06610          
06611       }
06612       return 1;
06613    }
06614 
06615 #ifdef DEBUG_SUPPORT
06616    if (iaxdebug && (res >= sizeof(*fh)))
06617       iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh));
06618 #endif
06619    if (ntohs(mh->callno) & IAX_FLAG_FULL) {
06620       if (res < sizeof(*fh)) {
06621          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));
06622          return 1;
06623       }
06624 
06625       /* Get the destination call number */
06626       dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS;
06627       /* Retrieve the type and subclass */
06628       f.frametype = fh->type;
06629       if (f.frametype == AST_FRAME_VIDEO) {
06630          f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
06631       } else {
06632          f.subclass = uncompress_subclass(fh->csub);
06633       }
06634       if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) ||
06635                          (f.subclass == IAX_COMMAND_POKE) || (f.subclass == IAX_COMMAND_FWDOWNL) ||
06636                          (f.subclass == IAX_COMMAND_REGREL)))
06637          new = NEW_ALLOW;
06638    } else {
06639       /* Don't know anything about it yet */
06640       f.frametype = AST_FRAME_NULL;
06641       f.subclass = 0;
06642    }
06643 
06644    if (!fr->callno)
06645       fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, 1, fd);
06646 
06647    if (fr->callno > 0)
06648       ast_mutex_lock(&iaxsl[fr->callno]);
06649 
06650    if (!fr->callno || !iaxs[fr->callno]) {
06651       /* A call arrived for a nonexistent destination.  Unless it's an "inval"
06652          frame, reply with an inval */
06653       if (ntohs(mh->callno) & IAX_FLAG_FULL) {
06654          /* We can only raw hangup control frames */
06655          if (((f.subclass != IAX_COMMAND_INVAL) &&
06656              (f.subclass != IAX_COMMAND_TXCNT) &&
06657              (f.subclass != IAX_COMMAND_TXACC) &&
06658              (f.subclass != IAX_COMMAND_FWDOWNL))||
06659              (f.frametype != AST_FRAME_IAX))
06660             raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL,
06661             fd);
06662       }
06663       if (fr->callno > 0) 
06664          ast_mutex_unlock(&iaxsl[fr->callno]);
06665       return 1;
06666    }
06667    if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) {
06668       if (decrypt_frame(fr->callno, fh, &f, &res)) {
06669          ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n");
06670          ast_mutex_unlock(&iaxsl[fr->callno]);
06671          return 1;
06672       }
06673 #ifdef DEBUG_SUPPORT
06674       else if (iaxdebug)
06675          iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh));
06676 #endif
06677    }
06678 
06679    /* count this frame */
06680    iaxs[fr->callno]->frames_received++;
06681 
06682    if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid &&
06683       f.subclass != IAX_COMMAND_TXCNT &&     /* for attended transfer */
06684       f.subclass != IAX_COMMAND_TXACC)    /* for attended transfer */
06685       iaxs[fr->callno]->peercallno = (unsigned short)(ntohs(mh->callno) & ~IAX_FLAG_FULL);
06686    if (ntohs(mh->callno) & IAX_FLAG_FULL) {
06687       if (option_debug  && iaxdebug)
06688          ast_log(LOG_DEBUG, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass);
06689       /* Check if it's out of order (and not an ACK or INVAL) */
06690       fr->oseqno = fh->oseqno;
06691       fr->iseqno = fh->iseqno;
06692       fr->ts = ntohl(fh->ts);
06693 #ifdef IAXTESTS
06694       if (test_resync) {
06695          if (option_debug)
06696             ast_log(LOG_DEBUG, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync);
06697          fr->ts += test_resync;
06698       }
06699 #endif /* IAXTESTS */
06700 #if 0
06701       if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) ||
06702            ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX &&
06703                         (f.subclass == IAX_COMMAND_NEW ||
06704                          f.subclass == IAX_COMMAND_AUTHREQ ||
06705                          f.subclass == IAX_COMMAND_ACCEPT ||
06706                          f.subclass == IAX_COMMAND_REJECT))      ) )
06707 #endif
06708       if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE))
06709          updatehistory = 0;
06710       if ((iaxs[fr->callno]->iseqno != fr->oseqno) &&
06711          (iaxs[fr->callno]->iseqno ||
06712             ((f.subclass != IAX_COMMAND_TXCNT) &&
06713             (f.subclass != IAX_COMMAND_TXREADY) &&    /* for attended transfer */
06714             (f.subclass != IAX_COMMAND_TXREL) &&      /* for attended transfer */
06715             (f.subclass != IAX_COMMAND_UNQUELCH ) &&  /* for attended transfer */
06716             (f.subclass != IAX_COMMAND_TXACC)) ||
06717             (f.frametype != AST_FRAME_IAX))) {
06718          if (
06719           ((f.subclass != IAX_COMMAND_ACK) &&
06720            (f.subclass != IAX_COMMAND_INVAL) &&
06721            (f.subclass != IAX_COMMAND_TXCNT) &&
06722            (f.subclass != IAX_COMMAND_TXREADY) &&     /* for attended transfer */
06723            (f.subclass != IAX_COMMAND_TXREL) &&    /* for attended transfer */
06724            (f.subclass != IAX_COMMAND_UNQUELCH ) &&   /* for attended transfer */
06725            (f.subclass != IAX_COMMAND_TXACC) &&
06726            (f.subclass != IAX_COMMAND_VNAK)) ||
06727            (f.frametype != AST_FRAME_IAX)) {
06728             /* If it's not an ACK packet, it's out of order. */
06729             if (option_debug)
06730                ast_log(LOG_DEBUG, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 
06731                iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass);
06732             /* Check to see if we need to request retransmission,
06733              * and take sequence number wraparound into account */
06734             if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) {
06735                /* If we've already seen it, ack it XXX There's a border condition here XXX */
06736                if ((f.frametype != AST_FRAME_IAX) || 
06737                      ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) {
06738                   if (option_debug)
06739                      ast_log(LOG_DEBUG, "Acking anyway\n");
06740                   /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if
06741                      we have anything to send, we'll retransmit and get an ACK back anyway XXX */
06742                   send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
06743                }
06744             } else {
06745                /* Send a VNAK requesting retransmission */
06746                iax2_vnak(fr->callno);
06747             }
06748             ast_mutex_unlock(&iaxsl[fr->callno]);
06749             return 1;
06750          }
06751       } else {
06752          /* Increment unless it's an ACK or VNAK */
06753          if (((f.subclass != IAX_COMMAND_ACK) &&
06754              (f.subclass != IAX_COMMAND_INVAL) &&
06755              (f.subclass != IAX_COMMAND_TXCNT) &&
06756              (f.subclass != IAX_COMMAND_TXACC) &&
06757             (f.subclass != IAX_COMMAND_VNAK)) ||
06758              (f.frametype != AST_FRAME_IAX))
06759             iaxs[fr->callno]->iseqno++;
06760       }
06761       /* A full frame */
06762       if (res < sizeof(*fh)) {
06763          ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*fh));
06764          ast_mutex_unlock(&iaxsl[fr->callno]);
06765          return 1;
06766       }
06767       /* Ensure text frames are NULL-terminated */
06768       if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') {
06769          if (res < thread->buf_size)
06770             thread->buf[res++] = '\0';
06771          else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */
06772             thread->buf[res - 1] = '\0';
06773       }
06774       f.datalen = res - sizeof(*fh);
06775 
06776       /* Handle implicit ACKing unless this is an INVAL, and only if this is 
06777          from the real peer, not the transfer peer */
06778       if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 
06779           ((f.subclass != IAX_COMMAND_INVAL) ||
06780            (f.frametype != AST_FRAME_IAX))) {
06781          unsigned char x;
06782          int call_to_destroy;
06783          /* XXX This code is not very efficient.  Surely there is a better way which still
06784                 properly handles boundary conditions? XXX */
06785          /* First we have to qualify that the ACKed value is within our window */
06786          for (x=iaxs[fr->callno]->rseqno; x != iaxs[fr->callno]->oseqno; x++)
06787             if (fr->iseqno == x)
06788                break;
06789          if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) {
06790             /* The acknowledgement is within our window.  Time to acknowledge everything
06791                that it says to */
06792             for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) {
06793                /* Ack the packet with the given timestamp */
06794                if (option_debug && iaxdebug)
06795                   ast_log(LOG_DEBUG, "Cancelling transmission of packet %d\n", x);
06796                call_to_destroy = 0;
06797                AST_LIST_LOCK(&iaxq.queue);
06798                AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
06799                   /* If it's our call, and our timestamp, mark -1 retries */
06800                   if ((fr->callno == cur->callno) && (x == cur->oseqno)) {
06801                      cur->retries = -1;
06802                      /* Destroy call if this is the end */
06803                      if (cur->final)
06804                         call_to_destroy = fr->callno;
06805                   }
06806                }
06807                AST_LIST_UNLOCK(&iaxq.queue);
06808                if (call_to_destroy) {
06809                   if (iaxdebug && option_debug)
06810                      ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", call_to_destroy);
06811                   iax2_destroy(call_to_destroy);
06812                }
06813             }
06814             /* Note how much we've received acknowledgement for */
06815             if (iaxs[fr->callno])
06816                iaxs[fr->callno]->rseqno = fr->iseqno;
06817             else {
06818                /* Stop processing now */
06819                ast_mutex_unlock(&iaxsl[fr->callno]);
06820                return 1;
06821             }
06822          } else
06823             ast_log(LOG_DEBUG, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno);
06824       }
06825       if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 
06826          ((f.frametype != AST_FRAME_IAX) || 
06827           ((f.subclass != IAX_COMMAND_TXACC) &&
06828            (f.subclass != IAX_COMMAND_TXCNT)))) {
06829          /* Only messages we accept from a transfer host are TXACC and TXCNT */
06830          ast_mutex_unlock(&iaxsl[fr->callno]);
06831          return 1;
06832       }
06833 
06834       if (f.datalen) {
06835          if (f.frametype == AST_FRAME_IAX) {
06836             if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) {
06837                ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr));
06838                ast_mutex_unlock(&iaxsl[fr->callno]);
06839                return 1;
06840             }
06841             f.data = NULL;
06842             f.datalen = 0;
06843          } else
06844             f.data = thread->buf + sizeof(*fh);
06845       } else {
06846          if (f.frametype == AST_FRAME_IAX)
06847             f.data = NULL;
06848          else
06849             f.data = empty;
06850          memset(&ies, 0, sizeof(ies));
06851       }
06852 
06853       /* when we receive the first full frame for a new incoming channel,
06854          it is safe to start the PBX on the channel because we have now
06855          completed a 3-way handshake with the peer */
06856       if ((f.frametype == AST_FRAME_VOICE) ||
06857           (f.frametype == AST_FRAME_VIDEO) ||
06858           (f.frametype == AST_FRAME_IAX)) {
06859          if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) {
06860             ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART);
06861             if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) {
06862                ast_mutex_unlock(&iaxsl[fr->callno]);
06863                return 1;
06864             }
06865          }
06866       }
06867 
06868       if (f.frametype == AST_FRAME_VOICE) {
06869          if (f.subclass != iaxs[fr->callno]->voiceformat) {
06870                iaxs[fr->callno]->voiceformat = f.subclass;
06871                ast_log(LOG_DEBUG, "Ooh, voice format changed to %d\n", f.subclass);
06872                if (iaxs[fr->callno]->owner) {
06873                   int orignative;
06874 retryowner:
06875                   if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) {
06876                      ast_mutex_unlock(&iaxsl[fr->callno]);
06877                      usleep(1);
06878                      ast_mutex_lock(&iaxsl[fr->callno]);
06879                      if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner;
06880                   }
06881                   if (iaxs[fr->callno]) {
06882                      if (iaxs[fr->callno]->owner) {
06883                         orignative = iaxs[fr->callno]->owner->nativeformats;
06884                         iaxs[fr->callno]->owner->nativeformats = f.subclass;
06885                         if (iaxs[fr->callno]->owner->readformat)
06886                            ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat);
06887                         iaxs[fr->callno]->owner->nativeformats = orignative;
06888                         ast_mutex_unlock(&iaxs[fr->callno]->owner->lock);
06889                      }
06890                   } else {
06891                      ast_log(LOG_DEBUG, "Neat, somebody took away the channel at a magical time but i found it!\n");
06892                      ast_mutex_unlock(&iaxsl[fr->callno]);
06893                      return 1;
06894                   }
06895                }
06896          }
06897       }
06898       if (f.frametype == AST_FRAME_VIDEO) {
06899          if (f.subclass != iaxs[fr->callno]->videoformat) {
06900             ast_log(LOG_DEBUG, "Ooh, video format changed to %d\n", f.subclass & ~0x1);
06901             iaxs[fr->callno]->videoformat = f.subclass & ~0x1;
06902          }
06903       }
06904       if (f.frametype == AST_FRAME_IAX) {
06905          if (iaxs[fr->callno]->initid > -1) {
06906             /* Don't auto congest anymore since we've gotten something usefulb ack */
06907             ast_sched_del(sched, iaxs[fr->callno]->initid);
06908             iaxs[fr->callno]->initid = -1;
06909          }
06910          /* Handle the IAX pseudo frame itself */
06911          if (option_debug && iaxdebug)
06912             ast_log(LOG_DEBUG, "IAX subclass %d received\n", f.subclass);
06913 
06914                         /* Update last ts unless the frame's timestamp originated with us. */
06915          if (iaxs[fr->callno]->last < fr->ts &&
06916                             f.subclass != IAX_COMMAND_ACK &&
06917                             f.subclass != IAX_COMMAND_PONG &&
06918                             f.subclass != IAX_COMMAND_LAGRP) {
06919             iaxs[fr->callno]->last = fr->ts;
06920             if (option_debug && iaxdebug)
06921                ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts);
06922          }
06923 
06924          switch(f.subclass) {
06925          case IAX_COMMAND_ACK:
06926             /* Do nothing */
06927             break;
06928          case IAX_COMMAND_QUELCH:
06929             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
06930                     /* Generate Manager Hold event, if necessary*/
06931                if (iaxs[fr->callno]->owner) {
06932                   manager_event(EVENT_FLAG_CALL, "Hold",
06933                      "Channel: %s\r\n"
06934                      "Uniqueid: %s\r\n",
06935                      iaxs[fr->callno]->owner->name, 
06936                      iaxs[fr->callno]->owner->uniqueid);
06937                }
06938 
06939                ast_set_flag(iaxs[fr->callno], IAX_QUELCH);
06940                if (ies.musiconhold) {
06941                   if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) {
06942                      const char *mohsuggest = iaxs[fr->callno]->mohsuggest;
06943                      ast_queue_control_data(iaxs[fr->callno]->owner, AST_CONTROL_HOLD, 
06944                         S_OR(mohsuggest, NULL),
06945                         !ast_strlen_zero(mohsuggest) ? strlen(mohsuggest) + 1 : 0);
06946                   }
06947                }
06948             }
06949             break;
06950          case IAX_COMMAND_UNQUELCH:
06951             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
06952                     /* Generate Manager Unhold event, if necessary*/
06953                if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) {
06954                   manager_event(EVENT_FLAG_CALL, "Unhold",
06955                      "Channel: %s\r\n"
06956                      "Uniqueid: %s\r\n",
06957                      iaxs[fr->callno]->owner->name, 
06958                      iaxs[fr->callno]->owner->uniqueid);
06959                }
06960 
06961                ast_clear_flag(iaxs[fr->callno], IAX_QUELCH);
06962                if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner))
06963                   ast_queue_control(iaxs[fr->callno]->owner, AST_CONTROL_UNHOLD);
06964             }
06965             break;
06966          case IAX_COMMAND_TXACC:
06967             if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) {
06968                /* Ack the packet with the given timestamp */
06969                AST_LIST_LOCK(&iaxq.queue);
06970                AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
06971                   /* Cancel any outstanding txcnt's */
06972                   if ((fr->callno == cur->callno) && (cur->transfer))
06973                      cur->retries = -1;
06974                }
06975                AST_LIST_UNLOCK(&iaxq.queue);
06976                memset(&ied1, 0, sizeof(ied1));
06977                iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno);
06978                send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1);
06979                iaxs[fr->callno]->transferring = TRANSFER_READY;
06980             }
06981             break;
06982          case IAX_COMMAND_NEW:
06983             /* Ignore if it's already up */
06984             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD))
06985                break;
06986             if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr)
06987                check_provisioning(&sin, fd, ies.serviceident, ies.provver);
06988             /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */
06989             if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) {
06990                int new_callno;
06991                if ((new_callno = make_trunk(fr->callno, 1)) != -1)
06992                   fr->callno = new_callno;
06993             }
06994             /* For security, always ack immediately */
06995             if (delayreject)
06996                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
06997             if (check_access(fr->callno, &sin, &ies)) {
06998                /* They're not allowed on */
06999                auth_fail(fr->callno, IAX_COMMAND_REJECT);
07000                if (authdebug)
07001                   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);
07002                break;
07003             }
07004             if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) {
07005                const char *context, *exten, *cid_num;
07006 
07007                context = ast_strdupa(iaxs[fr->callno]->context);
07008                exten = ast_strdupa(iaxs[fr->callno]->exten);
07009                cid_num = ast_strdupa(iaxs[fr->callno]->cid_num);
07010 
07011                /* This might re-enter the IAX code and need the lock */
07012                ast_mutex_unlock(&iaxsl[fr->callno]);
07013                exists = ast_exists_extension(NULL, context, exten, 1, cid_num);
07014                ast_mutex_lock(&iaxsl[fr->callno]);
07015 
07016                if (!iaxs[fr->callno]) {
07017                   ast_mutex_unlock(&iaxsl[fr->callno]);
07018                   return 1;
07019                }
07020             } else
07021                exists = 0;
07022             if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) {
07023                if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) {
07024                   memset(&ied0, 0, sizeof(ied0));
07025                   iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
07026                   iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
07027                   send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07028                   if (authdebug)
07029                      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);
07030                } else {
07031                   /* Select an appropriate format */
07032 
07033                   if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
07034                      if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07035                         using_prefs = "reqonly";
07036                      } else {
07037                         using_prefs = "disabled";
07038                      }
07039                      format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability;
07040                      memset(&pref, 0, sizeof(pref));
07041                      strcpy(caller_pref_buf, "disabled");
07042                      strcpy(host_pref_buf, "disabled");
07043                   } else {
07044                      using_prefs = "mine";
07045                      /* If the information elements are in here... use them */
07046                      if (ies.codec_prefs)
07047                         ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
07048                      if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
07049                         /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
07050                         if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
07051                            pref = iaxs[fr->callno]->rprefs;
07052                            using_prefs = "caller";
07053                         } else {
07054                            pref = iaxs[fr->callno]->prefs;
07055                         }
07056                      } else
07057                         pref = iaxs[fr->callno]->prefs;
07058                      
07059                      format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
07060                      ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
07061                      ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
07062                   }
07063                   if (!format) {
07064                      if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
07065                         format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
07066                      if (!format) {
07067                         memset(&ied0, 0, sizeof(ied0));
07068                         iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07069                         iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07070                         send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07071                         if (authdebug) {
07072                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
07073                               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);
07074                            else 
07075                               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);
07076                         }
07077                      } else {
07078                         /* Pick one... */
07079                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07080                            if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability))
07081                               format = 0;
07082                         } else {
07083                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
07084                               using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
07085                               memset(&pref, 0, sizeof(pref));
07086                               format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
07087                               strcpy(caller_pref_buf,"disabled");
07088                               strcpy(host_pref_buf,"disabled");
07089                            } else {
07090                               using_prefs = "mine";
07091                               if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
07092                                  /* Do the opposite of what we tried above. */
07093                                  if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
07094                                     pref = iaxs[fr->callno]->prefs;                       
07095                                  } else {
07096                                     pref = iaxs[fr->callno]->rprefs;
07097                                     using_prefs = "caller";
07098                                  }
07099                                  format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1);
07100                            
07101                               } else /* if no codec_prefs IE do it the old way */
07102                                  format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 
07103                            }
07104                         }
07105 
07106                         if (!format) {
07107                            memset(&ied0, 0, sizeof(ied0));
07108                            iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07109                            iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07110                            ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
07111                            send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07112                            if (authdebug)
07113                               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);
07114                            ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);   
07115                            break;
07116                         }
07117                      }
07118                   }
07119                   if (format) {
07120                      /* No authentication required, let them in */
07121                      memset(&ied1, 0, sizeof(ied1));
07122                      iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
07123                      send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
07124                      if (strcmp(iaxs[fr->callno]->exten, "TBD")) {
07125                         ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07126                         if (option_verbose > 2) 
07127                            ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n"
07128                                     "%srequested format = %s,\n"
07129                                     "%srequested prefs = %s,\n"
07130                                     "%sactual format = %s,\n"
07131                                     "%shost prefs = %s,\n"
07132                                     "%spriority = %s\n",
07133                                     ast_inet_ntoa(sin.sin_addr), 
07134                                     VERBOSE_PREFIX_4,
07135                                     ast_getformatname(iaxs[fr->callno]->peerformat), 
07136                                     VERBOSE_PREFIX_4,
07137                                     caller_pref_buf,
07138                                     VERBOSE_PREFIX_4,
07139                                     ast_getformatname(format), 
07140                                     VERBOSE_PREFIX_4,
07141                                     host_pref_buf, 
07142                                     VERBOSE_PREFIX_4,
07143                                     using_prefs);
07144                         
07145                         iaxs[fr->callno]->chosenformat = format;
07146                         ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART);
07147                      } else {
07148                         ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
07149                         /* If this is a TBD call, we're ready but now what...  */
07150                         if (option_verbose > 2)
07151                            ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr));
07152                      }
07153                   }
07154                }
07155                break;
07156             }
07157             if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5)
07158                merge_encryption(iaxs[fr->callno],ies.encmethods);
07159             else
07160                iaxs[fr->callno]->encmethods = 0;
07161             if (!authenticate_request(iaxs[fr->callno]))
07162                ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED);
07163             break;
07164          case IAX_COMMAND_DPREQ:
07165             /* Request status in the dialplan */
07166             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) &&
07167                !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) {
07168                if (iaxcompat) {
07169                   /* Spawn a thread for the lookup */
07170                   spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num);
07171                } else {
07172                   /* Just look it up */
07173                   dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1);
07174                }
07175             }
07176             break;
07177          case IAX_COMMAND_HANGUP:
07178             ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
07179             ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr->callno);
07180             /* Set hangup cause according to remote */
07181             if (ies.causecode && iaxs[fr->callno]->owner)
07182                iaxs[fr->callno]->owner->hangupcause = ies.causecode;
07183             /* Send ack immediately, before we destroy */
07184             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07185             iax2_destroy(fr->callno);
07186             break;
07187          case IAX_COMMAND_REJECT:
07188             /* Set hangup cause according to remote */
07189             if (ies.causecode && iaxs[fr->callno]->owner)
07190                iaxs[fr->callno]->owner->hangupcause = ies.causecode;
07191 
07192             if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) {
07193                if (iaxs[fr->callno]->owner && authdebug)
07194                   ast_log(LOG_WARNING, "Call rejected by %s: %s\n",
07195                      ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr),
07196                      ies.cause ? ies.cause : "<Unknown>");
07197                ast_log(LOG_DEBUG, "Immediately destroying %d, having received reject\n",
07198                   fr->callno);
07199             }
07200             /* Send ack immediately, before we destroy */
07201             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK,
07202                          fr->ts, NULL, 0, fr->iseqno);
07203             if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION))
07204                iaxs[fr->callno]->error = EPERM;
07205             iax2_destroy(fr->callno);
07206             break;
07207          case IAX_COMMAND_TRANSFER:
07208             if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner) && ies.called_number) {
07209                /* Set BLINDTRANSFER channel variables */
07210                pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", ast_bridged_channel(iaxs[fr->callno]->owner)->name);
07211                pbx_builtin_setvar_helper(ast_bridged_channel(iaxs[fr->callno]->owner), "BLINDTRANSFER", iaxs[fr->callno]->owner->name);
07212                if (!strcmp(ies.called_number, ast_parking_ext())) {
07213                   if (iax_park(ast_bridged_channel(iaxs[fr->callno]->owner), iaxs[fr->callno]->owner)) {
07214                      ast_log(LOG_WARNING, "Failed to park call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name);
07215                   } else if (ast_bridged_channel(iaxs[fr->callno]->owner))
07216                      ast_log(LOG_DEBUG, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name);
07217                } else {
07218                   if (ast_async_goto(ast_bridged_channel(iaxs[fr->callno]->owner), iaxs[fr->callno]->context, ies.called_number, 1))
07219                      ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name, 
07220                         ies.called_number, iaxs[fr->callno]->context);
07221                   else
07222                      ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name, 
07223                         ies.called_number, iaxs[fr->callno]->context);
07224                }
07225             } else
07226                   ast_log(LOG_DEBUG, "Async goto not applicable on call %d\n", fr->callno);
07227             break;
07228          case IAX_COMMAND_ACCEPT:
07229             /* Ignore if call is already up or needs authentication or is a TBD */
07230             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED))
07231                break;
07232             if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) {
07233                /* Send ack immediately, before we destroy */
07234                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07235                iax2_destroy(fr->callno);
07236                break;
07237             }
07238             if (ies.format) {
07239                iaxs[fr->callno]->peerformat = ies.format;
07240             } else {
07241                if (iaxs[fr->callno]->owner)
07242                   iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats;
07243                else
07244                   iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability;
07245             }
07246             if (option_verbose > 2)
07247                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));
07248             if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) {
07249                memset(&ied0, 0, sizeof(ied0));
07250                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07251                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07252                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07253                if (authdebug)
07254                   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);
07255             } else {
07256                ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07257                if (iaxs[fr->callno]->owner) {
07258                   /* Switch us to use a compatible format */
07259                   iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat;
07260                   if (option_verbose > 2)
07261                      ast_verbose(VERBOSE_PREFIX_3 "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats));
07262 retryowner2:
07263                   if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) {
07264                      ast_mutex_unlock(&iaxsl[fr->callno]);
07265                      usleep(1);
07266                      ast_mutex_lock(&iaxsl[fr->callno]);
07267                      if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2;
07268                   }
07269                   
07270                   if (iaxs[fr->callno] && iaxs[fr->callno]->owner) {
07271                      /* Setup read/write formats properly. */
07272                      if (iaxs[fr->callno]->owner->writeformat)
07273                         ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat);   
07274                      if (iaxs[fr->callno]->owner->readformat)
07275                         ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat);  
07276                      ast_mutex_unlock(&iaxs[fr->callno]->owner->lock);
07277                   }
07278                }
07279             }
07280             if (iaxs[fr->callno]) {
07281                ast_mutex_lock(&dpcache_lock);
07282                dp = iaxs[fr->callno]->dpentries;
07283                while(dp) {
07284                   if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) {
07285                      iax2_dprequest(dp, fr->callno);
07286                   }
07287                   dp = dp->peer;
07288                }
07289                ast_mutex_unlock(&dpcache_lock);
07290             }
07291             break;
07292          case IAX_COMMAND_POKE:
07293             /* Send back a pong packet with the original timestamp */
07294             send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1);
07295             break;
07296          case IAX_COMMAND_PING:
07297          {
07298             struct iax_ie_data pingied;
07299             construct_rr(iaxs[fr->callno], &pingied);
07300             /* Send back a pong packet with the original timestamp */
07301             send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1);
07302          }
07303             break;
07304          case IAX_COMMAND_PONG:
07305             /* Calculate ping time */
07306             iaxs[fr->callno]->pingtime =  calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts;
07307             /* save RR info */
07308             save_rr(fr, &ies);
07309 
07310             if (iaxs[fr->callno]->peerpoke) {
07311                peer = iaxs[fr->callno]->peerpoke;
07312                if ((peer->lastms < 0)  || (peer->historicms > peer->maxms)) {
07313                   if (iaxs[fr->callno]->pingtime <= peer->maxms) {
07314                      ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime);
07315                      manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 
07316                      ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
07317                   }
07318                } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) {
07319                   if (iaxs[fr->callno]->pingtime > peer->maxms) {
07320                      ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime);
07321                      manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 
07322                      ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
07323                   }
07324                }
07325                peer->lastms = iaxs[fr->callno]->pingtime;
07326                if (peer->smoothing && (peer->lastms > -1))
07327                   peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2;
07328                else if (peer->smoothing && peer->lastms < 0)
07329                   peer->historicms = (0 + peer->historicms) / 2;
07330                else              
07331                   peer->historicms = iaxs[fr->callno]->pingtime;
07332 
07333                /* Remove scheduled iax2_poke_noanswer */
07334                if (peer->pokeexpire > -1)
07335                   ast_sched_del(sched, peer->pokeexpire);
07336                /* Schedule the next cycle */
07337                if ((peer->lastms < 0)  || (peer->historicms > peer->maxms)) 
07338                   peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer);
07339                else
07340                   peer->pokeexpire = ast_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer);
07341                /* and finally send the ack */
07342                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07343                /* And wrap up the qualify call */
07344                iax2_destroy(fr->callno);
07345                peer->callno = 0;
07346                if (option_debug)
07347                   ast_log(LOG_DEBUG, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms);
07348             }
07349             break;
07350          case IAX_COMMAND_LAGRQ:
07351          case IAX_COMMAND_LAGRP:
07352             f.src = "LAGRQ";
07353             f.mallocd = 0;
07354             f.offset = 0;
07355             f.samples = 0;
07356             iax_frame_wrap(fr, &f);
07357             if(f.subclass == IAX_COMMAND_LAGRQ) {
07358                /* Received a LAGRQ - echo back a LAGRP */
07359                fr->af.subclass = IAX_COMMAND_LAGRP;
07360                iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0);
07361             } else {
07362                /* Received LAGRP in response to our LAGRQ */
07363                unsigned int ts;
07364                /* This is a reply we've been given, actually measure the difference */
07365                ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af);
07366                iaxs[fr->callno]->lag = ts - fr->ts;
07367                if (option_debug && iaxdebug)
07368                   ast_log(LOG_DEBUG, "Peer %s lag measured as %dms\n",
07369                      ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag);
07370             }
07371             break;
07372          case IAX_COMMAND_AUTHREQ:
07373             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
07374                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>");
07375                break;
07376             }
07377             if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) {
07378                ast_log(LOG_WARNING, 
07379                   "I don't know how to authenticate %s to %s\n", 
07380                   ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr));
07381             }
07382             break;
07383          case IAX_COMMAND_AUTHREP:
07384             /* For security, always ack immediately */
07385             if (delayreject)
07386                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07387             /* Ignore once we've started */
07388             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
07389                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>");
07390                break;
07391             }
07392             if (authenticate_verify(iaxs[fr->callno], &ies)) {
07393                if (authdebug)
07394                   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);
07395                memset(&ied0, 0, sizeof(ied0));
07396                auth_fail(fr->callno, IAX_COMMAND_REJECT);
07397                break;
07398             }
07399             if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) {
07400                /* This might re-enter the IAX code and need the lock */
07401                exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num);
07402             } else
07403                exists = 0;
07404             if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) {
07405                if (authdebug)
07406                   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);
07407                memset(&ied0, 0, sizeof(ied0));
07408                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
07409                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
07410                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07411             } else {
07412                /* Select an appropriate format */
07413                if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
07414                   if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07415                      using_prefs = "reqonly";
07416                   } else {
07417                      using_prefs = "disabled";
07418                   }
07419                   format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability;
07420                   memset(&pref, 0, sizeof(pref));
07421                   strcpy(caller_pref_buf, "disabled");
07422                   strcpy(host_pref_buf, "disabled");
07423                } else {
07424                   using_prefs = "mine";
07425                   if (ies.codec_prefs)
07426                      ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
07427                   if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
07428                      if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
07429                         pref = iaxs[fr->callno]->rprefs;
07430                         using_prefs = "caller";
07431                      } else {
07432                         pref = iaxs[fr->callno]->prefs;
07433                      }
07434                   } else /* if no codec_prefs IE do it the old way */
07435                      pref = iaxs[fr->callno]->prefs;
07436                
07437                   format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
07438                   ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
07439                   ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
07440                }
07441                if (!format) {
07442                   if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07443                      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);
07444                      format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
07445                   }
07446                   if (!format) {
07447                      if (authdebug) {
07448                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 
07449                            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);
07450                         else
07451                            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);
07452                      }
07453                      memset(&ied0, 0, sizeof(ied0));
07454                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07455                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07456                      send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07457                   } else {
07458                      /* Pick one... */
07459                      if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
07460                         if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability))
07461                            format = 0;
07462                      } else {
07463                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
07464                            using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
07465                            memset(&pref, 0, sizeof(pref));
07466                            format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ?
07467                               iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
07468                            strcpy(caller_pref_buf,"disabled");
07469                            strcpy(host_pref_buf,"disabled");
07470                         } else {
07471                            using_prefs = "mine";
07472                            if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
07473                               /* Do the opposite of what we tried above. */
07474                               if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
07475                                  pref = iaxs[fr->callno]->prefs;                 
07476                               } else {
07477                                  pref = iaxs[fr->callno]->rprefs;
07478                                  using_prefs = "caller";
07479                               }
07480                               format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1);
07481                            } else /* if no codec_prefs IE do it the old way */
07482                               format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 
07483                         }
07484                      }
07485                      if (!format) {
07486                         ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
07487                         if (authdebug) {
07488                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
07489                               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);
07490                            else
07491                               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);
07492                         }
07493                         memset(&ied0, 0, sizeof(ied0));
07494                         iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
07495                         iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
07496                         send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07497                      }
07498                   }
07499                }
07500                if (format) {
07501                   /* Authentication received */
07502                   memset(&ied1, 0, sizeof(ied1));
07503                   iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
07504                   send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
07505                   if (strcmp(iaxs[fr->callno]->exten, "TBD")) {
07506                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07507                      if (option_verbose > 2) 
07508                         ast_verbose(VERBOSE_PREFIX_3 "Accepting AUTHENTICATED call from %s:\n"
07509                                  "%srequested format = %s,\n"
07510                                  "%srequested prefs = %s,\n"
07511                                  "%sactual format = %s,\n"
07512                                  "%shost prefs = %s,\n"
07513                                  "%spriority = %s\n", 
07514                                  ast_inet_ntoa(sin.sin_addr), 
07515                                  VERBOSE_PREFIX_4,
07516                                  ast_getformatname(iaxs[fr->callno]->peerformat),
07517                                  VERBOSE_PREFIX_4,
07518                                  caller_pref_buf,
07519                                  VERBOSE_PREFIX_4,
07520                                  ast_getformatname(format),
07521                                  VERBOSE_PREFIX_4,
07522                                  host_pref_buf,
07523                                  VERBOSE_PREFIX_4,
07524                                  using_prefs);
07525 
07526                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07527                      if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format)))
07528                         iax2_destroy(fr->callno);
07529                   } else {
07530                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
07531                      /* If this is a TBD call, we're ready but now what...  */
07532                      if (option_verbose > 2)
07533                         ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr));
07534                   }
07535                }
07536             }
07537             break;
07538          case IAX_COMMAND_DIAL:
07539             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) {
07540                ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
07541                ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s");
07542                if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) {
07543                   if (authdebug)
07544                      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);
07545                   memset(&ied0, 0, sizeof(ied0));
07546                   iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
07547                   iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
07548                   send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07549                } else {
07550                   ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07551                   if (option_verbose > 2) 
07552                      ast_verbose(VERBOSE_PREFIX_3 "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat);
07553                   ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
07554                   send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1);
07555                   if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat)))
07556                      iax2_destroy(fr->callno);
07557                }
07558             }
07559             break;
07560          case IAX_COMMAND_INVAL:
07561             iaxs[fr->callno]->error = ENOTCONN;
07562             ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr->callno);
07563             iax2_destroy(fr->callno);
07564             if (option_debug)
07565                ast_log(LOG_DEBUG, "Destroying call %d\n", fr->callno);
07566             break;
07567          case IAX_COMMAND_VNAK:
07568             ast_log(LOG_DEBUG, "Received VNAK: resending outstanding frames\n");
07569             /* Force retransmission */
07570             vnak_retransmit(fr->callno, fr->iseqno);
07571             break;
07572          case IAX_COMMAND_REGREQ:
07573          case IAX_COMMAND_REGREL:
07574             /* For security, always ack immediately */
07575             if (delayreject)
07576                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07577             if (register_verify(fr->callno, &sin, &ies)) {
07578                /* Send delayed failure */
07579                auth_fail(fr->callno, IAX_COMMAND_REGREJ);
07580                break;
07581             }
07582             if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 
07583                   ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED)) {
07584                if (f.subclass == IAX_COMMAND_REGREL)
07585                   memset(&sin, 0, sizeof(sin));
07586                if (update_registry(iaxs[fr->callno]->peer, &sin, fr->callno, ies.devicetype, fd, ies.refresh))
07587                   ast_log(LOG_WARNING, "Registry error\n");
07588                if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr)
07589                   check_provisioning(&sin, fd, ies.serviceident, ies.provver);
07590                break;
07591             }
07592             registry_authrequest(iaxs[fr->callno]->peer, fr->callno);
07593             break;
07594          case IAX_COMMAND_REGACK:
07595             if (iax2_ack_registry(&ies, &sin, fr->callno)) 
07596                ast_log(LOG_WARNING, "Registration failure\n");
07597             /* Send ack immediately, before we destroy */
07598             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07599             iax2_destroy(fr->callno);
07600             break;
07601          case IAX_COMMAND_REGREJ:
07602             if (iaxs[fr->callno]->reg) {
07603                if (authdebug) {
07604                   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));
07605                   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>");
07606                }
07607                iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED;
07608             }
07609             /* Send ack immediately, before we destroy */
07610             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07611             iax2_destroy(fr->callno);
07612             break;
07613          case IAX_COMMAND_REGAUTH:
07614             /* Authentication request */
07615             if (registry_rerequest(&ies, fr->callno, &sin)) {
07616                memset(&ied0, 0, sizeof(ied0));
07617                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found");
07618                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
07619                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07620             }
07621             break;
07622          case IAX_COMMAND_TXREJ:
07623             iaxs[fr->callno]->transferring = 0;
07624             if (option_verbose > 2) 
07625                ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
07626             memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer));
07627             if (iaxs[fr->callno]->bridgecallno) {
07628                if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) {
07629                   iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0;
07630                   send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
07631                }
07632             }
07633             break;
07634          case IAX_COMMAND_TXREADY:
07635             if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) ||
07636                 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) {
07637                if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)
07638                   iaxs[fr->callno]->transferring = TRANSFER_MREADY;
07639                else
07640                   iaxs[fr->callno]->transferring = TRANSFER_READY;
07641                if (option_verbose > 2) 
07642                   ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
07643                if (iaxs[fr->callno]->bridgecallno) {
07644                   if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) ||
07645                       (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) {
07646                      /* They're both ready, now release them. */
07647                      if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) {
07648                         if (option_verbose > 2) 
07649                            ast_verbose(VERBOSE_PREFIX_3 "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
07650                               iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
07651 
07652                         iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA;
07653                         iaxs[fr->callno]->transferring = TRANSFER_MEDIA;
07654 
07655                         memset(&ied0, 0, sizeof(ied0));
07656                         memset(&ied1, 0, sizeof(ied1));
07657                         iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
07658                         iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
07659                         send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1);
07660                         send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1);
07661                      } else {
07662                         if (option_verbose > 2) 
07663                            ast_verbose(VERBOSE_PREFIX_3 "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
07664                               iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
07665 
07666                         iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED;
07667                         iaxs[fr->callno]->transferring = TRANSFER_RELEASED;
07668                         ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
07669                         ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
07670 
07671                         /* Stop doing lag & ping requests */
07672                         stop_stuff(fr->callno);
07673                         stop_stuff(iaxs[fr->callno]->bridgecallno);
07674 
07675                         memset(&ied0, 0, sizeof(ied0));
07676                         memset(&ied1, 0, sizeof(ied1));
07677                         iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
07678                         iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
07679                         send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1);
07680                         send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1);
07681                      }
07682 
07683                   }
07684                }
07685             }
07686             break;
07687          case IAX_COMMAND_TXREQ:
07688             try_transfer(iaxs[fr->callno], &ies);
07689             break;
07690          case IAX_COMMAND_TXCNT:
07691             if (iaxs[fr->callno]->transferring)
07692                send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0);
07693             break;
07694          case IAX_COMMAND_TXREL:
07695             /* Send ack immediately, rather than waiting until we've changed addresses */
07696             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07697             complete_transfer(fr->callno, &ies);
07698             stop_stuff(fr->callno); /* for attended transfer to work with libiax */
07699             break;   
07700          case IAX_COMMAND_TXMEDIA:
07701             if (iaxs[fr->callno]->transferring == TRANSFER_READY) {
07702                                         AST_LIST_LOCK(&iaxq.queue);
07703                                         AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
07704                                                 /* Cancel any outstanding frames and start anew */
07705                                                 if ((fr->callno == cur->callno) && (cur->transfer)) {
07706                                                         cur->retries = -1;
07707                                                 }
07708                                         }
07709                                         AST_LIST_UNLOCK(&iaxq.queue);
07710                /* Start sending our media to the transfer address, but otherwise leave the call as-is */
07711                iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS;
07712             }
07713             break;   
07714          case IAX_COMMAND_DPREP:
07715             complete_dpreply(iaxs[fr->callno], &ies);
07716             break;
07717          case IAX_COMMAND_UNSUPPORT:
07718             ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown);
07719             break;
07720          case IAX_COMMAND_FWDOWNL:
07721             /* Firmware download */
07722             memset(&ied0, 0, sizeof(ied0));
07723             res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc);
07724             if (res < 0)
07725                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
07726             else if (res > 0)
07727                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1);
07728             else
07729                send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1);
07730             break;
07731          default:
07732             ast_log(LOG_DEBUG, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno);
07733             memset(&ied0, 0, sizeof(ied0));
07734             iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass);
07735             send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1);
07736          }
07737          /* Don't actually pass these frames along */
07738          if ((f.subclass != IAX_COMMAND_ACK) && 
07739            (f.subclass != IAX_COMMAND_TXCNT) && 
07740            (f.subclass != IAX_COMMAND_TXACC) && 
07741            (f.subclass != IAX_COMMAND_INVAL) &&
07742            (f.subclass != IAX_COMMAND_VNAK)) { 
07743             if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno)
07744                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07745          }
07746          ast_mutex_unlock(&iaxsl[fr->callno]);
07747          return 1;
07748       }
07749       /* Unless this is an ACK or INVAL frame, ack it */
07750       if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno)
07751          send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
07752    } else if (minivid) {
07753       f.frametype = AST_FRAME_VIDEO;
07754       if (iaxs[fr->callno]->videoformat > 0) 
07755          f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0);
07756       else {
07757          ast_log(LOG_WARNING, "Received mini frame before first full video frame\n ");
07758          iax2_vnak(fr->callno);
07759          ast_mutex_unlock(&iaxsl[fr->callno]);
07760          return 1;
07761       }
07762       f.datalen = res - sizeof(*vh);
07763       if (f.datalen)
07764          f.data = thread->buf + sizeof(*vh);
07765       else
07766          f.data = NULL;
07767 #ifdef IAXTESTS
07768       if (test_resync) {
07769          fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff);
07770       } else
07771 #endif /* IAXTESTS */
07772          fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff);
07773    } else {
07774       /* A mini frame */
07775       f.frametype = AST_FRAME_VOICE;
07776       if (iaxs[fr->callno]->voiceformat > 0)
07777          f.subclass = iaxs[fr->callno]->voiceformat;
07778       else {
07779          ast_log(LOG_WARNING, "Received mini frame before first full voice frame\n ");
07780          iax2_vnak(fr->callno);
07781          ast_mutex_unlock(&iaxsl[fr->callno]);
07782          return 1;
07783       }
07784       f.datalen = res - sizeof(struct ast_iax2_mini_hdr);
07785       if (f.datalen < 0) {
07786          ast_log(LOG_WARNING, "Datalen < 0?\n");
07787          ast_mutex_unlock(&iaxsl[fr->callno]);
07788          return 1;
07789       }
07790       if (f.datalen)
07791          f.data = thread->buf + sizeof(*mh);
07792       else
07793          f.data = NULL;
07794 #ifdef IAXTESTS
07795       if (test_resync) {
07796          fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff);
07797       } else
07798 #endif /* IAXTESTS */
07799       fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts);
07800       /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */
07801    }
07802    /* Don't pass any packets until we're started */
07803    if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
07804       ast_mutex_unlock(&iaxsl[fr->callno]);
07805       return 1;
07806    }
07807    /* Common things */
07808    f.src = "IAX2";
07809    f.mallocd = 0;
07810    f.offset = 0;
07811    f.len = 0;
07812    if (f.datalen && (f.frametype == AST_FRAME_VOICE)) {
07813       f.samples = ast_codec_get_samples(&f);
07814       /* We need to byteswap incoming slinear samples from network byte order */
07815       if (f.subclass == AST_FORMAT_SLINEAR)
07816          ast_frame_byteswap_be(&f);
07817    } else
07818       f.samples = 0;
07819    iax_frame_wrap(fr, &f);
07820 
07821    /* If this is our most recent packet, use it as our basis for timestamping */
07822    if (iaxs[fr->callno]->last < fr->ts) {
07823       /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/
07824       fr->outoforder = 0;
07825    } else {
07826       if (option_debug && iaxdebug)
07827          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);
07828       fr->outoforder = -1;
07829    }
07830    duped_fr = iaxfrdup2(fr);
07831    if (duped_fr) {
07832       schedule_delivery(duped_fr, updatehistory, 0, &fr->ts);
07833    }
07834    if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) {
07835       iaxs[fr->callno]->last = fr->ts;
07836 #if 1
07837       if (option_debug && iaxdebug)
07838          ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts);
07839 #endif
07840    }
07841 
07842    /* Always run again */
07843    ast_mutex_unlock(&iaxsl[fr->callno]);
07844    return 1;
07845 }

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

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

06365 {
06366    struct iax2_thread *thread;
06367    socklen_t len;
06368    time_t t;
06369    static time_t last_errtime = 0;
06370    struct ast_iax2_full_hdr *fh;
06371 
06372    if (!(thread = find_idle_thread())) {
06373       time(&t);
06374       if (t != last_errtime)
06375          ast_log(LOG_NOTICE, "Out of idle IAX2 threads for I/O, pausing!\n");
06376       last_errtime = t;
06377       usleep(1);
06378       return 1;
06379    }
06380 
06381    len = sizeof(thread->iosin);
06382    thread->iofd = fd;
06383    thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
06384    thread->buf_size = sizeof(thread->readbuf);
06385    thread->buf = thread->readbuf;
06386    if (thread->buf_len < 0) {
06387       if (errno != ECONNREFUSED && errno != EAGAIN)
06388          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
06389       handle_error();
06390       thread->iostate = IAX_IOSTATE_IDLE;
06391       signal_condition(&thread->lock, &thread->cond);
06392       return 1;
06393    }
06394    if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
06395       thread->iostate = IAX_IOSTATE_IDLE;
06396       signal_condition(&thread->lock, &thread->cond);
06397       return 1;
06398    }
06399    
06400    /* Determine if this frame is a full frame; if so, and any thread is currently
06401       processing a full frame for the same callno from this peer, then drop this
06402       frame (and the peer will retransmit it) */
06403    fh = (struct ast_iax2_full_hdr *) thread->buf;
06404    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
06405       struct iax2_thread *cur = NULL;
06406       uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
06407       
06408       AST_LIST_LOCK(&active_list);
06409       AST_LIST_TRAVERSE(&active_list, cur, list) {
06410          if ((cur->ffinfo.callno == callno) &&
06411              !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
06412             break;
06413       }
06414       if (cur) {
06415          /* we found another thread processing a full frame for this call,
06416             so queue it up for processing later. */
06417          defer_full_frame(thread, cur);
06418          AST_LIST_UNLOCK(&active_list);
06419          thread->iostate = IAX_IOSTATE_IDLE;
06420          signal_condition(&thread->lock, &thread->cond);
06421          return 1;
06422       } else {
06423          /* this thread is going to process this frame, so mark it */
06424          thread->ffinfo.callno = callno;
06425          memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
06426          thread->ffinfo.type = fh->type;
06427          thread->ffinfo.csub = fh->csub;
06428       }
06429       AST_LIST_UNLOCK(&active_list);
06430    }
06431    
06432    /* Mark as ready and send on its way */
06433    thread->iostate = IAX_IOSTATE_READY;
06434 #ifdef DEBUG_SCHED_MULTITHREAD
06435    ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
06436 #endif
06437    signal_condition(&thread->lock, &thread->cond);
06438 
06439    return 1;
06440 }

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

Definition at line 6151 of file chan_iax2.c.

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

Referenced by socket_process().

06152 {
06153    pthread_t newthread;
06154    struct dpreq_data *dpr;
06155    pthread_attr_t attr;
06156    
06157    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06158       return;
06159 
06160    pthread_attr_init(&attr);
06161    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06162 
06163    dpr->callno = callno;
06164    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06165    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06166    if (callerid)
06167       dpr->callerid = ast_strdup(callerid);
06168    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06169       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06170    }
06171 
06172    pthread_attr_destroy(&attr);
06173 }

static int start_network_thread ( void   )  [static]

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

08414 {
08415    pthread_attr_t attr;
08416    int threadcount = 0;
08417    int x;
08418    for (x = 0; x < iaxthreadcount; x++) {
08419       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
08420       if (thread) {
08421          thread->type = IAX_TYPE_POOL;
08422          thread->threadnum = ++threadcount;
08423          ast_mutex_init(&thread->lock);
08424          ast_cond_init(&thread->cond, NULL);
08425          pthread_attr_init(&attr);
08426          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
08427          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
08428             ast_log(LOG_WARNING, "Failed to create new thread!\n");
08429             free(thread);
08430             thread = NULL;
08431          }
08432          AST_LIST_LOCK(&idle_list);
08433          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
08434          AST_LIST_UNLOCK(&idle_list);
08435       }
08436    }
08437    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
08438    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
08439    if (option_verbose > 1)
08440       ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount);
08441    return 0;
08442 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 5837 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

05838 {
05839    iax2_destroy_helper(iaxs[callno]);
05840 }

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

Definition at line 6026 of file chan_iax2.c.

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

Referenced by network_thread().

06027 {
06028    char buf[1024];
06029    int res;
06030    struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL;
06031    int processed = 0;
06032    int totalcalls = 0;
06033 #ifdef ZT_TIMERACK
06034    int x = 1;
06035 #endif
06036    struct timeval now;
06037    if (iaxtrunkdebug)
06038       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA);
06039    gettimeofday(&now, NULL);
06040    if (events & AST_IO_PRI) {
06041 #ifdef ZT_TIMERACK
06042       /* Great, this is a timing interface, just call the ioctl */
06043       if (ioctl(fd, ZT_TIMERACK, &x)) 
06044          ast_log(LOG_WARNING, "Unable to acknowledge zap timer\n");
06045       res = 0;
06046 #endif      
06047    } else {
06048       /* Read and ignore from the pseudo channel for timing */
06049       res = read(fd, buf, sizeof(buf));
06050       if (res < 1) {
06051          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
06052          return 1;
06053       }
06054    }
06055    /* For each peer that supports trunking... */
06056    ast_mutex_lock(&tpeerlock);
06057    tpeer = tpeers;
06058    while(tpeer) {
06059       processed++;
06060       res = 0;
06061       ast_mutex_lock(&tpeer->lock);
06062       /* We can drop a single tpeer per pass.  That makes all this logic
06063          substantially easier */
06064       if (!drop && iax2_trunk_expired(tpeer, &now)) {
06065          /* Take it out of the list, but don't free it yet, because it
06066             could be in use */
06067          if (prev)
06068             prev->next = tpeer->next;
06069          else
06070             tpeers = tpeer->next;
06071          drop = tpeer;
06072       } else {
06073          res = send_trunk(tpeer, &now);
06074          if (iaxtrunkdebug)
06075             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);
06076       }     
06077       totalcalls += res;   
06078       res = 0;
06079       ast_mutex_unlock(&tpeer->lock);
06080       prev = tpeer;
06081       tpeer = tpeer->next;
06082    }
06083    ast_mutex_unlock(&tpeerlock);
06084    if (drop) {
06085       ast_mutex_lock(&drop->lock);
06086       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
06087          because by the time they could get tpeerlock, we've already grabbed it */
06088       ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
06089       free(drop->trunkdata);
06090       ast_mutex_unlock(&drop->lock);
06091       ast_mutex_destroy(&drop->lock);
06092       free(drop);
06093       
06094    }
06095    if (iaxtrunkdebug)
06096       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
06097    iaxtrunkdebug =0;
06098    return 1;
06099 }

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

Definition at line 1687 of file chan_iax2.c.

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

Referenced by send_trunk().

01688 {
01689    int res;
01690    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
01691                sizeof(*sin));
01692    if (res < 0) {
01693       if (option_debug)
01694          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
01695       handle_error();
01696    } else
01697       res = 0;
01698    return res;
01699 }

static int try_firmware ( char *  s  )  [static]

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

Referenced by reload_firmware().

01379 {
01380    struct stat stbuf;
01381    struct iax_firmware *cur;
01382    int ifd;
01383    int fd;
01384    int res;
01385    
01386    struct ast_iax2_firmware_header *fwh, fwh2;
01387    struct MD5Context md5;
01388    unsigned char sum[16];
01389    unsigned char buf[1024];
01390    int len, chunk;
01391    char *s2;
01392    char *last;
01393    s2 = alloca(strlen(s) + 100);
01394    if (!s2) {
01395       ast_log(LOG_WARNING, "Alloca failed!\n");
01396       return -1;
01397    }
01398    last = strrchr(s, '/');
01399    if (last)
01400       last++;
01401    else
01402       last = s;
01403    snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random());
01404    res = stat(s, &stbuf);
01405    if (res < 0) {
01406       ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno));
01407       return -1;
01408    }
01409    /* Make sure it's not a directory */
01410    if (S_ISDIR(stbuf.st_mode))
01411       return -1;
01412    ifd = open(s, O_RDONLY);
01413    if (ifd < 0) {
01414       ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno));
01415       return -1;
01416    }
01417    fd = open(s2, O_RDWR | O_CREAT | O_EXCL);
01418    if (fd < 0) {
01419       ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno));
01420       close(ifd);
01421       return -1;
01422    }
01423    /* Unlink our newly created file */
01424    unlink(s2);
01425    
01426    /* Now copy the firmware into it */
01427    len = stbuf.st_size;
01428    while(len) {
01429       chunk = len;
01430       if (chunk > sizeof(buf))
01431          chunk = sizeof(buf);
01432       res = read(ifd, buf, chunk);
01433       if (res != chunk) {
01434          ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01435          close(ifd);
01436          close(fd);
01437          return -1;
01438       }
01439       res = write(fd, buf, chunk);
01440       if (res != chunk) {
01441          ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01442          close(ifd);
01443          close(fd);
01444          return -1;
01445       }
01446       len -= chunk;
01447    }
01448    close(ifd);
01449    /* Return to the beginning */
01450    lseek(fd, 0, SEEK_SET);
01451    if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) {
01452       ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s);
01453       close(fd);
01454       return -1;
01455    }
01456    if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) {
01457       ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s);
01458       close(fd);
01459       return -1;
01460    }
01461    if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) {
01462       ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s);
01463       close(fd);
01464       return -1;
01465    }
01466    if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) {
01467       ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s);
01468       close(fd);
01469       return -1;
01470    }
01471    fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 
01472    if (fwh == (void *) -1) {
01473       ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno));
01474       close(fd);
01475       return -1;
01476    }
01477    MD5Init(&md5);
01478    MD5Update(&md5, fwh->data, ntohl(fwh->datalen));
01479    MD5Final(sum, &md5);
01480    if (memcmp(sum, fwh->chksum, sizeof(sum))) {
01481       ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s);
01482       munmap((void*)fwh, stbuf.st_size);
01483       close(fd);
01484       return -1;
01485    }
01486    cur = waresl.wares;
01487    while(cur) {
01488       if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) {
01489          /* Found a candidate */
01490          if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version)))
01491             /* The version we have on loaded is older, load this one instead */
01492             break;
01493          /* This version is no newer than what we have.  Don't worry about it.
01494             We'll consider it a proper load anyhow though */
01495          munmap((void*)fwh, stbuf.st_size);
01496          close(fd);
01497          return 0;
01498       }
01499       cur = cur->next;
01500    }
01501    if (!cur) {
01502       /* Allocate a new one and link it */
01503       if ((cur = ast_calloc(1, sizeof(*cur)))) {
01504          cur->fd = -1;
01505          cur->next = waresl.wares;
01506          waresl.wares = cur;
01507       }
01508    }
01509    if (cur) {
01510       if (cur->fwh) {
01511          munmap((void*)cur->fwh, cur->mmaplen);
01512       }
01513       if (cur->fd > -1)
01514          close(cur->fd);
01515       cur->fwh = fwh;
01516       cur->fd = fd;
01517       cur->mmaplen = stbuf.st_size;
01518       cur->dead = 0;
01519    }
01520    return 0;
01521 }

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

Definition at line 5300 of file chan_iax2.c.

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

Referenced by socket_process().

05301 {
05302    int newcall = 0;
05303    char newip[256];
05304    struct iax_ie_data ied;
05305    struct sockaddr_in new;
05306    
05307    
05308    memset(&ied, 0, sizeof(ied));
05309    if (ies->apparent_addr)
05310       bcopy(ies->apparent_addr, &new, sizeof(new));
05311    if (ies->callno)
05312       newcall = ies->callno;
05313    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05314       ast_log(LOG_WARNING, "Invalid transfer request\n");
05315       return -1;
05316    }
05317    pvt->transfercallno = newcall;
05318    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05319    inet_aton(newip, &pvt->transfer.sin_addr);
05320    pvt->transfer.sin_family = AF_INET;
05321    pvt->transferring = TRANSFER_BEGIN;
05322    pvt->transferid = ies->transferid;
05323    if (ies->transferid)
05324       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05325    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05326    return 0; 
05327 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1031 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

01032 {
01033    /* If the SC_LOG flag is set, return 2^csub otherwise csub */
01034    if (csub & IAX_FLAG_SC_LOG) {
01035       /* special case for 'compressed' -1 */
01036       if (csub == 0xff)
01037          return -1;
01038       else
01039          return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT);
01040    }
01041    else
01042       return csub;
01043 }

static int unload_module ( void   )  [static]

Definition at line 10326 of file chan_iax2.c.

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

10327 {
10328    ast_custom_function_unregister(&iaxpeer_function);
10329    return __unload_module();
10330 }

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

Definition at line 3108 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03109 {
03110    ast_mutex_unlock(&iaxsl[callno1]);
03111    ast_mutex_unlock(&iaxsl[callno0]);
03112 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

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

02222 {
02223    int x;
02224 
02225    if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) {
02226       x = fr->ts - iaxs[fr->callno]->last;
02227       if (x < -50000) {
02228          /* Sudden big jump backwards in timestamp:
02229             What likely happened here is that miniframe timestamp has circled but we haven't
02230             gotten the update from the main packet.  We'll just pretend that we did, and
02231             update the timestamp appropriately. */
02232          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
02233          if (option_debug && iaxdebug)
02234             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02235       }
02236       if (x > 50000) {
02237          /* Sudden apparent big jump forwards in timestamp:
02238             What's likely happened is this is an old miniframe belonging to the previous
02239             top-16-bit timestamp that has turned up out of order.
02240             Adjust the timestamp appropriately. */
02241          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
02242          if (option_debug && iaxdebug)
02243             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02244       }
02245    }
02246 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

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

Referenced by __get_from_jb(), and schedule_delivery().

02251 {
02252    int when;
02253    
02254    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02255    
02256    when = jb_next(pvt->jb) - when;
02257    
02258    if(pvt->jbid > -1) ast_sched_del(sched, pvt->jbid);
02259    
02260    if(when <= 0) {
02261       /* XXX should really just empty until when > 0.. */
02262       when = 1;
02263    }
02264    
02265    pvt->jbid = ast_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02266    
02267    /* Signal scheduler thread */
02268    signal_condition(&sched_lock, &sched_cond);
02269 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1186 of file chan_iax2.c.

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

Referenced by find_callno(), and make_trunk().

01187 {
01188    int max = 1;
01189    int x;
01190    /* XXX Prolly don't need locks here XXX */
01191    for (x=1;x<TRUNK_CALL_START - 1; x++) {
01192       if (iaxs[x])
01193          max = x + 1;
01194    }
01195    maxnontrunkcall = max;
01196    if (option_debug && iaxdebug)
01197       ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max);
01198 }

static void update_max_trunk ( void   )  [static]

Definition at line 1172 of file chan_iax2.c.

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

Referenced by iax2_destroy(), and make_trunk().

01173 {
01174    int max = TRUNK_CALL_START;
01175    int x;
01176    /* XXX Prolly don't need locks here XXX */
01177    for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) {
01178       if (iaxs[x])
01179          max = x + 1;
01180    }
01181    maxtrunkcall = max;
01182    if (option_debug && iaxdebug)
01183       ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max);
01184 }

static int update_packet ( struct iax_frame f  )  [static]

Definition at line 1861 of file chan_iax2.c.

References iax_frame::callno, iax_frame::data, iax_frame::dcallno, ast_iax2_full_hdr::dcallno, IAX_FLAG_RETRANS, iaxs, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, and iax_frame::iseqno.

Referenced by __attempt_transmit().

01862 {
01863    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
01864    struct ast_iax2_full_hdr *fh = f->data;
01865    /* Mark this as a retransmission */
01866    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
01867    /* Update iseqno */
01868    f->iseqno = iaxs[f->callno]->iseqno;
01869    fh->iseqno = f->iseqno;
01870    return 0;
01871 }

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

Definition at line 5657 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_sched_add(), ast_sched_del(), ast_strlen_zero(), ast_test_flag, ast_verbose(), iax_ie_data::buf, destroy_peer(), EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), 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, inaddrcmp(), LOG_NOTICE, LOG_WARNING, manager_event(), option_verbose, iax_ie_data::pos, realtime_update_peer(), register_peer_exten(), send_command_final(), iax2_peer::sockfd, and VERBOSE_PREFIX_3.

Referenced by socket_process().

05658 {
05659    /* Called from IAX thread only, with proper iaxsl lock */
05660    struct iax_ie_data ied;
05661    struct iax2_peer *p;
05662    int msgcount;
05663    char data[80];
05664    int version;
05665 
05666    memset(&ied, 0, sizeof(ied));
05667 
05668    /* SLD: Another find_peer call during registration - this time when we are really updating our registration */
05669    if (!(p = find_peer(name, 1))) {
05670       ast_log(LOG_WARNING, "No such peer '%s'\n", name);
05671       return -1;
05672    }
05673 
05674    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) {
05675       if (sin->sin_addr.s_addr) {
05676          time_t nowtime;
05677          time(&nowtime);
05678          realtime_update_peer(name, sin, nowtime);
05679       } else {
05680          realtime_update_peer(name, sin, 0);
05681       }
05682    }
05683    if (inaddrcmp(&p->addr, sin)) {
05684       if (iax2_regfunk)
05685          iax2_regfunk(p->name, 1);
05686       /* Stash the IP address from which they registered */
05687       memcpy(&p->addr, sin, sizeof(p->addr));
05688       snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry);
05689       if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) {
05690          ast_db_put("IAX/Registry", p->name, data);
05691          if  (option_verbose > 2)
05692             ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 
05693                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
05694          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name);
05695          register_peer_exten(p, 1);
05696          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05697       } else if (!ast_test_flag(p, IAX_TEMPONLY)) {
05698          if  (option_verbose > 2)
05699             ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 
05700                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED");
05701          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name);
05702          register_peer_exten(p, 0);
05703          ast_db_del("IAX/Registry", p->name);
05704          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05705       }
05706       /* Update the host */
05707       /* Verify that the host is really there */
05708       iax2_poke_peer(p, callno);
05709    }     
05710 
05711    /* Make sure our call still exists, an INVAL at the right point may make it go away */
05712    if (!iaxs[callno])
05713       return 0;
05714 
05715    /* Store socket fd */
05716    p->sockfd = fd;
05717    /* Setup the expiry */
05718    if (p->expire > -1)
05719       ast_sched_del(sched, p->expire);
05720    /* treat an unspecified refresh interval as the minimum */
05721    if (!refresh)
05722       refresh = min_reg_expire;
05723    if (refresh > max_reg_expire) {
05724       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
05725          p->name, max_reg_expire, refresh);
05726       p->expiry = max_reg_expire;
05727    } else if (refresh < min_reg_expire) {
05728       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
05729          p->name, min_reg_expire, refresh);
05730       p->expiry = min_reg_expire;
05731    } else {
05732       p->expiry = refresh;
05733    }
05734    if (p->expiry && sin->sin_addr.s_addr)
05735       p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name);
05736    iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
05737    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag));
05738    if (sin->sin_addr.s_addr) {
05739       iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry);
05740       iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
05741       if (!ast_strlen_zero(p->mailbox)) {
05742          int new, old;
05743          ast_app_inboxcount(p->mailbox, &new, &old);
05744          if (new > 255)
05745             new = 255;
05746          if (old > 255)
05747             old = 255;
05748          msgcount = (old << 8) | new;
05749          iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
05750       }
05751       if (ast_test_flag(p, IAX_HASCALLERID)) {
05752          iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num);
05753          iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name);
05754       }
05755    }
05756    version = iax_check_version(devtype);
05757    if (version) 
05758       iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version);
05759    if (ast_test_flag(p, IAX_TEMPONLY))
05760       destroy_peer(p);
05761    return send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
05762 }

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

Definition at line 5942 of file chan_iax2.c.

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

Referenced by socket_process().

05943 {
05944    struct iax_frame *f;
05945 
05946    AST_LIST_LOCK(&iaxq.queue);
05947    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
05948       /* Send a copy immediately */
05949       if ((f->callno == callno) && iaxs[f->callno] &&
05950          ((unsigned char ) (f->oseqno - last) < 128) &&
05951          (f->retries >= 0)) {
05952          send_packet(f);
05953       }
05954    }
05955    AST_LIST_UNLOCK(&iaxq.queue);
05956 }


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

Definition at line 218 of file chan_iax2.c.

Referenced by __oh323_new(), ast_cdr_setaccount(), ast_channel_alloc(), begin_dial(), check_user_full(), disa_exec(), features_call(), gtalk_new(), local_call(), sip_new(), tds_log(), wait_for_answer(), and zt_new().

int adsi = 0 [static]

Definition at line 222 of file chan_iax2.c.

int amaflags = 0 [static]

Definition at line 221 of file chan_iax2.c.

int authdebug = 1 [static]

Definition at line 158 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 159 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 10150 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 10130 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 10135 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 10145 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 10140 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 10125 of file chan_iax2.c.

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

Definition at line 143 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 10099 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 10091 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 10083 of file chan_iax2.c.

int defaultsockfd = -1 [static]

Definition at line 175 of file chan_iax2.c.

int delayreject = 0 [static]

Definition at line 223 of file chan_iax2.c.

struct iax2_dpcache * dpcache [static]

Referenced by find_cache(), and iax2_show_cache().

int global_rtautoclear = 120 [static]

Definition at line 276 of file chan_iax2.c.

struct ast_flags globalflags = { 0 } [static]

Definition at line 226 of file chan_iax2.c.

Referenced by find_or_create(), find_user(), find_user_realtime(), forward_message(), load_config(), make_email_file(), notify_new_message(), populate_defaults(), sendmail(), and vm_execmain().

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 204 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 224 of file chan_iax2.c.

enum { ... } iax2_flags

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

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

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10015 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

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

int iaxactivethreadcount = 0 [static]

Definition at line 454 of file chan_iax2.c.

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

int iaxcompat = 0 [static]

Definition at line 160 of file chan_iax2.c.

int iaxdebug = 0 [static]

Definition at line 206 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 162 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 164 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 453 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 452 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

struct ast_custom_function iaxpeer_function

Definition at line 9953 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 797 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(), 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_frame(), 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_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 798 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_fail(), auth_reject(), auto_hangup(), cache_get_callno_locked(), delete_users(), destroy_peer(), 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_frame(), iax2_request(), iax2_show_channels(), iax2_write(), load_module(), lock_both(), make_trunk(), network_thread(), send_command_locked(), socket_process(), and unlock_both().

int iaxthreadcount = DEFAULT_THREAD_COUNT [static]

Definition at line 451 of file chan_iax2.c.

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

int iaxtrunkdebug = 0 [static]

Definition at line 208 of file chan_iax2.c.

struct io_context* io [static]

Definition at line 201 of file chan_iax2.c.

int lagrq_time = 10 [static]

Definition at line 151 of file chan_iax2.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 145 of file chan_iax2.c.

struct timeval lastused[IAX_MAX_CALLS] [static]

Definition at line 799 of file chan_iax2.c.

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

int max_reg_expire [static]

Definition at line 169 of file chan_iax2.c.

int max_retries = 4 [static]

Definition at line 149 of file chan_iax2.c.

int maxauthreq = 3 [static]

Definition at line 148 of file chan_iax2.c.

int maxjitterbuffer = 1000 [static]

Definition at line 154 of file chan_iax2.c.

int maxjitterinterps = 10 [static]

Definition at line 156 of file chan_iax2.c.

int maxnontrunkcall = 1 [static]

Definition at line 153 of file chan_iax2.c.

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 152 of file chan_iax2.c.

int min_reg_expire [static]

Definition at line 168 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 219 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

Definition at line 220 of file chan_iax2.c.

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

struct ast_netsock_list* netsock [static]

Definition at line 173 of file chan_iax2.c.

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 228 of file chan_iax2.c.

char no_debug_jb_usage[] [static]

Initial value:

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

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

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 174 of file chan_iax2.c.

char* papp = "IAX2Provision" [static]

Definition at line 8084 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

char* pdescrip [static]

Initial value:

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

Definition at line 8086 of file chan_iax2.c.

Referenced by load_module().

int ping_time = 21 [static]

Definition at line 150 of file chan_iax2.c.

struct ast_codec_pref prefs [static]

Definition at line 139 of file chan_iax2.c.

Referenced by ast_best_codec().

char prune_realtime_usage[] [static]

Initial value:

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

Definition at line 10037 of file chan_iax2.c.

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

Definition at line 8085 of file chan_iax2.c.

Referenced by load_module().

char regcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 146 of file chan_iax2.c.

int resyncthreshold = 1000 [static]

Definition at line 155 of file chan_iax2.c.

struct sched_context* sched [static]

Definition at line 202 of file chan_iax2.c.

ast_cond_t sched_cond [static]

Definition at line 231 of file chan_iax2.c.

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 229 of file chan_iax2.c.

char show_cache_usage[] [static]

Initial value:

"Usage: iax2 show cache\n"
"       Display currently cached IAX Dialplan results.\n"

Definition at line 10029 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 10057 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 10075 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 10061 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 10033 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 10069 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10045 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 10079 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 10025 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 10065 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 10052 of file chan_iax2.c.

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

Definition at line 141 of file chan_iax2.c.

int test_losspct = 0 [static]

Definition at line 210 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 171 of file chan_iax2.c.

unsigned int tos = 0 [static]

Definition at line 166 of file chan_iax2.c.

struct iax2_trunk_peer * tpeers [static]

Referenced by find_tpeer(), and timing_read().

int trunkfreq = 20 [static]

Definition at line 157 of file chan_iax2.c.

struct 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 Wed Aug 15 01:24:51 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.3